Rewrite registry.h

This rewrites registry.h, removing all the macros and replacing it
with relatively ordinary template classes.  The result is less code
than the previous setup.  It replaces large macros with a relatively
straightforward C++ class, and now manages its own cleanup.

The existing type-safe "key" class is replaced with the equivalent
template class.  This approach ended up requiring relatively few
changes to the users of the registry code in gdb -- code using the key
system just required a small change to the key's declaration.

All existing users of the old C-like API are now converted to use the
type-safe API.  This mostly involved changing explicit deletion
functions to be an operator() in a deleter class.

The old "save/free" two-phase process is removed, and replaced with a
single "free" phase.  No existing code used both phases.

The old "free" callbacks took a parameter for the enclosing container
object.  However, this wasn't truly needed and is removed here as
well.
This commit is contained in:
Tom Tromey 2020-10-18 11:38:10 -06:00
parent 8f83e7b926
commit 08b8a139c9
64 changed files with 664 additions and 1052 deletions

View File

@ -1152,7 +1152,6 @@ COMMON_SFILES = \
regcache.c \
regcache-dump.c \
reggroups.c \
registry.c \
remote.c \
remote-fileio.c \
remote-notif.c \

View File

@ -334,7 +334,7 @@ struct ada_inferior_data
};
/* Our key to this module's inferior data. */
static const struct inferior_key<ada_inferior_data> ada_inferior_data;
static const registry<inferior>::key<ada_inferior_data> ada_inferior_data;
/* Return our inferior data for the given inferior (INF).
@ -376,7 +376,8 @@ struct ada_pspace_data
};
/* Key to our per-program-space data. */
static const struct program_space_key<ada_pspace_data> ada_pspace_data_handle;
static const registry<program_space>::key<ada_pspace_data>
ada_pspace_data_handle;
/* Return this module's data for the given program space (PSPACE).
If not is found, add a zero'ed one now.

View File

@ -166,7 +166,7 @@ struct ada_tasks_pspace_data
};
/* Key to our per-program-space data. */
static const struct program_space_key<ada_tasks_pspace_data>
static const registry<program_space>::key<ada_tasks_pspace_data>
ada_tasks_pspace_data_handle;
/* The kind of data structure used by the runtime to store the list
@ -242,7 +242,7 @@ struct ada_tasks_inferior_data
};
/* Key to our per-inferior data. */
static const struct inferior_key<ada_tasks_inferior_data>
static const registry<inferior>::key<ada_tasks_inferior_data>
ada_tasks_inferior_data_handle;
/* Return a string with TASKNO followed by the task name if TASK_INFO

View File

@ -123,7 +123,7 @@ struct arm_per_bfd
};
/* Per-bfd data used for mapping symbols. */
static bfd_key<arm_per_bfd> arm_bfd_data_key;
static const registry<bfd>::key<arm_per_bfd> arm_bfd_data_key;
/* The list of available "set arm ..." and "show arm ..." commands. */
static struct cmd_list_element *setarmcmdlist = NULL;
@ -2407,7 +2407,7 @@ struct arm_exidx_data
};
/* Per-BFD key to store exception handling information. */
static const struct bfd_key<arm_exidx_data> arm_exidx_data_key;
static const registry<bfd>::key<arm_exidx_data> arm_exidx_data_key;
static struct obj_section *
arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)

View File

@ -536,8 +536,8 @@ struct loaded_script
};
/* Per-program-space data key. */
static const struct program_space_key<struct auto_load_pspace_info>
auto_load_pspace_data;
static const registry<program_space>::key<auto_load_pspace_info>
auto_load_pspace_data;
/* Get the current autoload data. If none is found yet, add it now. This
function always returns a valid object. */

View File

@ -332,7 +332,7 @@ struct auxv_info
};
/* Per-inferior data key for auxv. */
static const struct inferior_key<auxv_info> auxv_inferior_data;
static const registry<inferior>::key<auxv_info> auxv_inferior_data;
/* Invalidate INF's auxv cache. */

View File

@ -79,7 +79,7 @@ struct catch_syscall_inferior_data
int total_syscalls_count;
};
static const struct inferior_key<struct catch_syscall_inferior_data>
static const registry<inferior>::key<catch_syscall_inferior_data>
catch_syscall_inferior_data;
static struct catch_syscall_inferior_data *

View File

@ -3327,7 +3327,7 @@ struct breakpoint_objfile_data
std::vector<probe *> exception_probes;
};
static const struct objfile_key<breakpoint_objfile_data>
static const registry<objfile>::key<breakpoint_objfile_data>
breakpoint_objfile_key;
/* Minimal symbol not found sentinel. */

View File

@ -61,7 +61,7 @@ struct coff_symfile_info
/* Key for COFF-associated data. */
static const struct objfile_key<coff_symfile_info> coff_objfile_data_key;
static const registry<objfile>::key<coff_symfile_info> coff_objfile_data_key;
/* Translate an external name string into a user-visible name. */
#define EXTERNAL_NAME(string, abfd) \

View File

@ -87,7 +87,7 @@
#include "ctf.h"
#include "ctf-api.h"
static const struct objfile_key<htab, htab_deleter> ctf_tid_key;
static const registry<objfile>::key<htab, htab_deleter> ctf_tid_key;
struct ctf_fp_info
{
@ -107,7 +107,7 @@ ctf_fp_info::~ctf_fp_info ()
ctf_close (arc);
}
static const objfile_key<ctf_fp_info> ctf_dict_key;
static const registry<objfile>::key<ctf_fp_info> ctf_dict_key;
/* A CTF context consists of a file pointer and an objfile pointer. */
@ -243,7 +243,7 @@ set_tid_type (struct objfile *of, ctf_id_t tid, struct type *typ)
{
htab_t htab;
htab = (htab_t) ctf_tid_key.get (of);
htab = ctf_tid_key.get (of);
if (htab == NULL)
{
htab = htab_create_alloc (1, tid_and_type_hash,
@ -271,7 +271,7 @@ get_tid_type (struct objfile *of, ctf_id_t tid)
struct ctf_tid_and_type *slot, ids;
htab_t htab;
htab = (htab_t) ctf_tid_key.get (of);
htab = ctf_tid_key.get (of);
if (htab == NULL)
return nullptr;

View File

@ -57,7 +57,7 @@
/* Key for dbx-associated data. */
objfile_key<dbx_symfile_info> dbx_objfile_data_key;
const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
/* We put a pointer to this structure in the read_symtab_private field
of the psymtab. */

View File

@ -1370,12 +1370,12 @@ dwarf2_frame_cfa (struct frame_info *this_frame)
/* We store the frame data on the BFD. This is only done if it is
independent of the address space and so can be shared. */
static const struct bfd_key<comp_unit> dwarf2_frame_bfd_data;
static const registry<bfd>::key<comp_unit> dwarf2_frame_bfd_data;
/* If any BFD sections require relocations (note; really should be if
any debug info requires relocations), then we store the frame data
on the objfile instead, and do not share it. */
const struct objfile_key<comp_unit> dwarf2_frame_objfile_data;
static const registry<objfile>::key<comp_unit> dwarf2_frame_objfile_data;
/* Pointer encoding helper functions. */

View File

@ -124,7 +124,8 @@ static bool check_physname = false;
static bool use_deprecated_index_sections = false;
/* This is used to store the data that is always per objfile. */
static const objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key;
static const registry<objfile>::key<dwarf2_per_objfile>
dwarf2_objfile_data_key;
/* These are used to store the dwarf2_per_bfd objects.
@ -134,8 +135,9 @@ static const objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key;
Other objfiles are not going to share a dwarf2_per_bfd with any other
objfiles, so they'll have their own version kept in the _objfile_data_key
version. */
static const struct bfd_key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
static const struct objfile_key<dwarf2_per_bfd> dwarf2_per_bfd_objfile_data_key;
static const registry<bfd>::key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key;
static const registry<objfile>::key<dwarf2_per_bfd>
dwarf2_per_bfd_objfile_data_key;
/* The "aclass" indices for various kinds of computed DWARF symbols. */

View File

@ -69,7 +69,7 @@ typedef std::vector<std::unique_ptr<probe>> elfread_data;
/* Per-BFD data for probe info. */
static const struct bfd_key<elfread_data> probe_key;
static const registry<bfd>::key<elfread_data> probe_key;
/* Minimal symbols located at the GOT entries for .plt - that is the real
pointer where the given entry will jump to. It gets updated by the real
@ -646,7 +646,7 @@ elf_rel_plt_read (minimal_symbol_reader &reader,
/* The data pointer is htab_t for gnu_ifunc_record_cache_unchecked. */
static const struct objfile_key<htab, htab_deleter>
static const registry<objfile>::key<htab, htab_deleter>
elf_objfile_gnu_ifunc_cache_data;
/* Map function names to CORE_ADDR in elf_objfile_gnu_ifunc_cache_data. */

View File

@ -520,7 +520,7 @@ struct fbsd_pspace_data
};
/* Per-program-space data for FreeBSD architectures. */
static const struct program_space_key<fbsd_pspace_data>
static const registry<program_space>::key<fbsd_pspace_data>
fbsd_pspace_data_handle;
static struct fbsd_pspace_data *

View File

@ -60,7 +60,7 @@ struct dbx_symfile_info
/* The tag used to find the DBX info attached to an objfile. This is
global because it is referenced by several modules. */
extern objfile_key<dbx_symfile_info> dbx_objfile_data_key;
extern const registry<objfile>::key<dbx_symfile_info> dbx_objfile_data_key;
#define DBX_SYMFILE_INFO(o) (dbx_objfile_data_key.get (o))
#define DBX_TEXT_ADDR(o) (DBX_SYMFILE_INFO(o)->text_addr)

View File

@ -112,13 +112,15 @@ struct gdb_bfd_data
std::vector<gdb_bfd_ref_ptr> included_bfds;
/* The registry. */
REGISTRY_FIELDS = {};
registry<bfd> registry_fields;
};
#define GDB_BFD_DATA_ACCESSOR(ABFD) \
((struct gdb_bfd_data *) bfd_usrdata (ABFD))
DEFINE_REGISTRY (bfd, GDB_BFD_DATA_ACCESSOR)
registry<bfd> *
registry_accessor<bfd>::get (bfd *abfd)
{
struct gdb_bfd_data *gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
return &gdata->registry_fields;
}
/* A hash table storing all the BFDs maintained in the cache. */
@ -498,7 +500,6 @@ gdb_bfd_init_data (struct bfd *abfd, struct stat *st)
gdata = new gdb_bfd_data (abfd, st);
bfd_set_usrdata (abfd, gdata);
bfd_alloc_data (abfd);
/* This is the first we've seen it, so add it to the hash table. */
slot = htab_find_slot (all_bfds, abfd, INSERT);
@ -725,7 +726,6 @@ gdb_bfd_unref (struct bfd *abfd)
htab_clear_slot (gdb_bfd_cache, slot);
}
bfd_free_data (abfd);
delete gdata;
bfd_set_usrdata (abfd, NULL); /* Paranoia. */

View File

@ -26,7 +26,13 @@
#include "gdbsupport/iterator-range.h"
#include "gdbsupport/next-iterator.h"
DECLARE_REGISTRY (bfd);
/* A registry adaptor for BFD. This arranges to store the registry in
gdb's per-BFD data, which is stored as the bfd_usrdata. */
template<>
struct registry_accessor<bfd>
{
static registry<bfd> *get (bfd *abfd);
};
/* If supplied a path starting with this sequence, gdb_bfd_open will
open BFDs using target fileio operations. */

View File

@ -6078,7 +6078,7 @@ typedef std::vector<std::unique_ptr<fixed_point_type_info>>
fixed_point_type_storage;
/* Key used for managing the storage of fixed-point type info. */
static const struct objfile_key<fixed_point_type_storage>
static const struct registry<objfile>::key<fixed_point_type_storage>
fixed_point_objfile_key;
/* See gdbtypes.h. */
@ -6305,8 +6305,8 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
/* This set of objfile-based types is intended to be used by symbol
readers as basic types. */
static const struct objfile_key<struct objfile_type,
gdb::noop_deleter<struct objfile_type>>
static const registry<objfile>::key<struct objfile_type,
gdb::noop_deleter<struct objfile_type>>
objfile_type_data;
const struct objfile_type *

View File

@ -28,6 +28,7 @@
#include "extension-priv.h"
#include "symtab.h"
#include "libguile.h"
#include "objfiles.h"
struct block;
struct frame_info;
@ -272,7 +273,6 @@ struct eqable_gdb_smob
#undef GDB_SMOB_HEAD
struct objfile;
struct objfile_data;
/* A predicate that returns non-zero if an object is a particular kind
of gsmob. */

View File

@ -76,7 +76,37 @@ static scm_t_bits block_syms_progress_smob_tag;
/* The "next!" block syms iterator method. */
static SCM bkscm_next_symbol_x_proc;
static const struct objfile_data *bkscm_objfile_data_key;
/* This is called when an objfile is about to be freed.
Invalidate the block as further actions on the block would result
in bad data. All access to b_smob->block should be gated by
checks to ensure the block is (still) valid. */
struct bkscm_deleter
{
/* Helper function for bkscm_del_objfile_blocks to mark the block
as invalid. */
static int
bkscm_mark_block_invalid (void **slot, void *info)
{
block_smob *b_smob = (block_smob *) *slot;
b_smob->block = NULL;
b_smob->objfile = NULL;
return 1;
}
void operator() (htab_t htab)
{
if (htab != NULL)
{
htab_traverse_noresize (htab, bkscm_mark_block_invalid, NULL);
htab_delete (htab);
}
}
};
static const registry<objfile>::key<htab, bkscm_deleter>
bkscm_objfile_data_key;
/* Administrivia for block smobs. */
@ -108,13 +138,13 @@ bkscm_eq_block_smob (const void *ap, const void *bp)
static htab_t
bkscm_objfile_block_map (struct objfile *objfile)
{
htab_t htab = (htab_t) objfile_data (objfile, bkscm_objfile_data_key);
htab_t htab = bkscm_objfile_data_key.get (objfile);
if (htab == NULL)
{
htab = gdbscm_create_eqable_gsmob_ptr_map (bkscm_hash_block_smob,
bkscm_eq_block_smob);
set_objfile_data (objfile, bkscm_objfile_data_key, htab);
bkscm_objfile_data_key.set (objfile, htab);
}
return htab;
@ -326,35 +356,6 @@ bkscm_scm_to_block (SCM block_scm, int arg_pos, const char *func_name,
return NULL;
}
/* Helper function for bkscm_del_objfile_blocks to mark the block
as invalid. */
static int
bkscm_mark_block_invalid (void **slot, void *info)
{
block_smob *b_smob = (block_smob *) *slot;
b_smob->block = NULL;
b_smob->objfile = NULL;
return 1;
}
/* This function is called when an objfile is about to be freed.
Invalidate the block as further actions on the block would result
in bad data. All access to b_smob->block should be gated by
checks to ensure the block is (still) valid. */
static void
bkscm_del_objfile_blocks (struct objfile *objfile, void *datum)
{
htab_t htab = (htab_t) datum;
if (htab != NULL)
{
htab_traverse_noresize (htab, bkscm_mark_block_invalid, NULL);
htab_delete (htab);
}
}
/* Block methods. */
@ -800,13 +801,3 @@ gdbscm_initialize_blocks (void)
gdbscm_scm_from_c_string ("\
Internal function to assist the block symbols iterator."));
}
void _initialize_scm_block ();
void
_initialize_scm_block ()
{
/* Register an objfile "free" callback so we can properly
invalidate blocks when an object file is about to be deleted. */
bkscm_objfile_data_key
= register_objfile_data_with_cleanup (NULL, bkscm_del_objfile_blocks);
}

View File

@ -74,7 +74,37 @@ static scm_t_bits frame_smob_tag;
/* Keywords used in argument passing. */
static SCM block_keyword;
static const struct inferior_data *frscm_inferior_data_key;
/* This is called when an inferior is about to be freed.
Invalidate the frame as further actions on the frame could result
in bad data. All access to the frame should be gated by
frscm_get_frame_smob_arg_unsafe which will raise an exception on
invalid frames. */
struct frscm_deleter
{
/* Helper function for frscm_del_inferior_frames to mark the frame
as invalid. */
static int
frscm_mark_frame_invalid (void **slot, void *info)
{
frame_smob *f_smob = (frame_smob *) *slot;
f_smob->inferior = NULL;
return 1;
}
void operator() (htab_t htab)
{
if (htab != NULL)
{
htab_traverse_noresize (htab, frscm_mark_frame_invalid, NULL);
htab_delete (htab);
}
}
};
static const registry<inferior>::key<htab, frscm_deleter>
frscm_inferior_data_key;
/* Administrivia for frame smobs. */
@ -117,13 +147,13 @@ frscm_eq_frame_smob (const void *ap, const void *bp)
static htab_t
frscm_inferior_frame_map (struct inferior *inferior)
{
htab_t htab = (htab_t) inferior_data (inferior, frscm_inferior_data_key);
htab_t htab = frscm_inferior_data_key.get (inferior);
if (htab == NULL)
{
htab = gdbscm_create_eqable_gsmob_ptr_map (frscm_hash_frame_smob,
frscm_eq_frame_smob);
set_inferior_data (inferior, frscm_inferior_data_key, htab);
frscm_inferior_data_key.set (inferior, htab);
}
return htab;
@ -346,35 +376,6 @@ frscm_frame_smob_to_frame (frame_smob *f_smob)
return frame;
}
/* Helper function for frscm_del_inferior_frames to mark the frame
as invalid. */
static int
frscm_mark_frame_invalid (void **slot, void *info)
{
frame_smob *f_smob = (frame_smob *) *slot;
f_smob->inferior = NULL;
return 1;
}
/* This function is called when an inferior is about to be freed.
Invalidate the frame as further actions on the frame could result
in bad data. All access to the frame should be gated by
frscm_get_frame_smob_arg_unsafe which will raise an exception on
invalid frames. */
static void
frscm_del_inferior_frames (struct inferior *inferior, void *datum)
{
htab_t htab = (htab_t) datum;
if (htab != NULL)
{
htab_traverse_noresize (htab, frscm_mark_frame_invalid, NULL);
htab_delete (htab);
}
}
/* Frame methods. */
@ -1170,13 +1171,3 @@ gdbscm_initialize_frames (void)
block_keyword = scm_from_latin1_keyword ("block");
}
void _initialize_scm_frame ();
void
_initialize_scm_frame ()
{
/* Register an inferior "free" callback so we can properly
invalidate frames when an inferior file is about to be deleted. */
frscm_inferior_data_key
= register_inferior_data_with_cleanup (NULL, frscm_del_inferior_frames);
}

View File

@ -49,7 +49,18 @@ static const char objfile_smob_name[] = "gdb:objfile";
/* The tag Guile knows the objfile smob by. */
static scm_t_bits objfile_smob_tag;
static const struct objfile_data *ofscm_objfile_data_key;
/* Objfile registry cleanup handler for when an objfile is deleted. */
struct ofscm_deleter
{
void operator() (objfile_smob *o_smob)
{
o_smob->objfile = NULL;
scm_gc_unprotect_object (o_smob->containing_scm);
}
};
static const registry<objfile>::key<objfile_smob, ofscm_deleter>
ofscm_objfile_data_key;
/* Return the list of pretty-printers registered with O_SMOB. */
@ -101,27 +112,6 @@ ofscm_make_objfile_smob (void)
return o_scm;
}
/* Clear the OBJFILE pointer in O_SMOB and unprotect the object from GC. */
static void
ofscm_release_objfile (objfile_smob *o_smob)
{
o_smob->objfile = NULL;
scm_gc_unprotect_object (o_smob->containing_scm);
}
/* Objfile registry cleanup handler for when an objfile is deleted. */
static void
ofscm_handle_objfile_deleted (struct objfile *objfile, void *datum)
{
objfile_smob *o_smob = (objfile_smob *) datum;
gdb_assert (o_smob->objfile == objfile);
ofscm_release_objfile (o_smob);
}
/* Return non-zero if SCM is a <gdb:objfile> object. */
static int
@ -147,7 +137,7 @@ ofscm_objfile_smob_from_objfile (struct objfile *objfile)
{
objfile_smob *o_smob;
o_smob = (objfile_smob *) objfile_data (objfile, ofscm_objfile_data_key);
o_smob = ofscm_objfile_data_key.get (objfile);
if (o_smob == NULL)
{
SCM o_scm = ofscm_make_objfile_smob ();
@ -155,7 +145,7 @@ ofscm_objfile_smob_from_objfile (struct objfile *objfile)
o_smob = (objfile_smob *) SCM_SMOB_DATA (o_scm);
o_smob->objfile = objfile;
set_objfile_data (objfile, ofscm_objfile_data_key, o_smob);
ofscm_objfile_data_key.set (objfile, o_smob);
scm_gc_protect_object (o_smob->containing_scm);
}
@ -424,11 +414,3 @@ gdbscm_initialize_objfiles (void)
gdbscm_define_functions (objfile_functions, 1);
}
void _initialize_scm_objfile ();
void
_initialize_scm_objfile ()
{
ofscm_objfile_data_key
= register_objfile_data_with_cleanup (NULL, ofscm_handle_objfile_deleted);
}

View File

@ -52,7 +52,18 @@ static const char pspace_smob_name[] = "gdb:progspace";
/* The tag Guile knows the pspace smob by. */
static scm_t_bits pspace_smob_tag;
static const struct program_space_data *psscm_pspace_data_key;
/* Progspace registry cleanup handler for when a progspace is deleted. */
struct psscm_deleter
{
void operator() (pspace_smob *p_smob)
{
p_smob->pspace = NULL;
scm_gc_unprotect_object (p_smob->containing_scm);
}
};
static const registry<program_space>::key<pspace_smob, psscm_deleter>
psscm_pspace_data_key;
/* Return the list of pretty-printers registered with P_SMOB. */
@ -111,27 +122,6 @@ psscm_make_pspace_smob (void)
return p_scm;
}
/* Clear the progspace pointer in P_SMOB and unprotect the object from GC. */
static void
psscm_release_pspace (pspace_smob *p_smob)
{
p_smob->pspace = NULL;
scm_gc_unprotect_object (p_smob->containing_scm);
}
/* Progspace registry cleanup handler for when a progspace is deleted. */
static void
psscm_handle_pspace_deleted (struct program_space *pspace, void *datum)
{
pspace_smob *p_smob = (pspace_smob *) datum;
gdb_assert (p_smob->pspace == pspace);
psscm_release_pspace (p_smob);
}
/* Return non-zero if SCM is a <gdb:progspace> object. */
static int
@ -157,7 +147,7 @@ psscm_pspace_smob_from_pspace (struct program_space *pspace)
{
pspace_smob *p_smob;
p_smob = (pspace_smob *) program_space_data (pspace, psscm_pspace_data_key);
p_smob = psscm_pspace_data_key.get (pspace);
if (p_smob == NULL)
{
SCM p_scm = psscm_make_pspace_smob ();
@ -165,7 +155,7 @@ psscm_pspace_smob_from_pspace (struct program_space *pspace)
p_smob = (pspace_smob *) SCM_SMOB_DATA (p_scm);
p_smob->pspace = pspace;
set_program_space_data (pspace, psscm_pspace_data_key, p_smob);
psscm_pspace_data_key.set (pspace, p_smob);
scm_gc_protect_object (p_smob->containing_scm);
}
@ -418,12 +408,3 @@ gdbscm_initialize_pspaces (void)
gdbscm_define_functions (pspace_functions, 1);
}
void _initialize_scm_progspace ();
void
_initialize_scm_progspace ()
{
psscm_pspace_data_key
= register_program_space_data_with_cleanup (NULL,
psscm_handle_pspace_deleted);
}

View File

@ -49,7 +49,37 @@ static SCM block_keyword;
static SCM domain_keyword;
static SCM frame_keyword;
static const struct objfile_data *syscm_objfile_data_key;
/* This is called when an objfile is about to be freed.
Invalidate the symbol as further actions on the symbol would result
in bad data. All access to s_smob->symbol should be gated by
syscm_get_valid_symbol_smob_arg_unsafe which will raise an exception on
invalid symbols. */
struct syscm_deleter
{
/* Helper function for syscm_del_objfile_symbols to mark the symbol
as invalid. */
static int
syscm_mark_symbol_invalid (void **slot, void *info)
{
symbol_smob *s_smob = (symbol_smob *) *slot;
s_smob->symbol = NULL;
return 1;
}
void operator() (htab_t htab)
{
if (htab != NULL)
{
htab_traverse_noresize (htab, syscm_mark_symbol_invalid, NULL);
htab_delete (htab);
}
}
};
static const registry<objfile>::key<htab, syscm_deleter>
syscm_objfile_data_key;
static struct gdbarch_data *syscm_gdbarch_data_key;
struct syscm_gdbarch_data
@ -105,12 +135,12 @@ syscm_get_symbol_map (struct symbol *symbol)
{
struct objfile *objfile = symbol->objfile ();
htab = (htab_t) objfile_data (objfile, syscm_objfile_data_key);
htab = syscm_objfile_data_key.get (objfile);
if (htab == NULL)
{
htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
syscm_eq_symbol_smob);
set_objfile_data (objfile, syscm_objfile_data_key, htab);
syscm_objfile_data_key.set (objfile, htab);
}
}
else
@ -291,35 +321,6 @@ syscm_get_valid_symbol_arg_unsafe (SCM self, int arg_pos,
return s_smob->symbol;
}
/* Helper function for syscm_del_objfile_symbols to mark the symbol
as invalid. */
static int
syscm_mark_symbol_invalid (void **slot, void *info)
{
symbol_smob *s_smob = (symbol_smob *) *slot;
s_smob->symbol = NULL;
return 1;
}
/* This function is called when an objfile is about to be freed.
Invalidate the symbol as further actions on the symbol would result
in bad data. All access to s_smob->symbol should be gated by
syscm_get_valid_symbol_smob_arg_unsafe which will raise an exception on
invalid symbols. */
static void
syscm_del_objfile_symbols (struct objfile *objfile, void *datum)
{
htab_t htab = (htab_t) datum;
if (htab != NULL)
{
htab_traverse_noresize (htab, syscm_mark_symbol_invalid, NULL);
htab_delete (htab);
}
}
/* Symbol methods. */
@ -823,11 +824,6 @@ void _initialize_scm_symbol ();
void
_initialize_scm_symbol ()
{
/* Register an objfile "free" callback so we can properly
invalidate symbols when an object file is about to be deleted. */
syscm_objfile_data_key
= register_objfile_data_with_cleanup (NULL, syscm_del_objfile_symbols);
/* Arch-specific symbol data. */
syscm_gdbarch_data_key
= gdbarch_data_register_post_init (syscm_init_arch_symbols);

View File

@ -77,7 +77,37 @@ static const char sal_smob_name[] = "gdb:sal";
static scm_t_bits symtab_smob_tag;
static scm_t_bits sal_smob_tag;
static const struct objfile_data *stscm_objfile_data_key;
/* This is called when an objfile is about to be freed.
Invalidate the symbol table as further actions on the symbol table
would result in bad data. All access to st_smob->symtab should be
gated by stscm_get_valid_symtab_smob_arg_unsafe which will raise an
exception on invalid symbol tables. */
struct stscm_deleter
{
/* Helper function for stscm_del_objfile_symtabs to mark the symtab
as invalid. */
static int
stscm_mark_symtab_invalid (void **slot, void *info)
{
symtab_smob *st_smob = (symtab_smob *) *slot;
st_smob->symtab = NULL;
return 1;
}
void operator() (htab_t htab)
{
if (htab != NULL)
{
htab_traverse_noresize (htab, stscm_mark_symtab_invalid, NULL);
htab_delete (htab);
}
}
};
static const registry<objfile>::key<htab, stscm_deleter>
stscm_objfile_data_key;
/* Administrivia for symtab smobs. */
@ -110,13 +140,13 @@ static htab_t
stscm_objfile_symtab_map (struct symtab *symtab)
{
struct objfile *objfile = symtab->compunit ()->objfile ();
htab_t htab = (htab_t) objfile_data (objfile, stscm_objfile_data_key);
htab_t htab = stscm_objfile_data_key.get (objfile);
if (htab == NULL)
{
htab = gdbscm_create_eqable_gsmob_ptr_map (stscm_hash_symtab_smob,
stscm_eq_symtab_smob);
set_objfile_data (objfile, stscm_objfile_data_key, htab);
stscm_objfile_data_key.set (objfile, htab);
}
return htab;
@ -271,35 +301,6 @@ stscm_get_valid_symtab_smob_arg_unsafe (SCM self, int arg_pos,
return st_smob;
}
/* Helper function for stscm_del_objfile_symtabs to mark the symtab
as invalid. */
static int
stscm_mark_symtab_invalid (void **slot, void *info)
{
symtab_smob *st_smob = (symtab_smob *) *slot;
st_smob->symtab = NULL;
return 1;
}
/* This function is called when an objfile is about to be freed.
Invalidate the symbol table as further actions on the symbol table
would result in bad data. All access to st_smob->symtab should be
gated by stscm_get_valid_symtab_smob_arg_unsafe which will raise an
exception on invalid symbol tables. */
static void
stscm_del_objfile_symtabs (struct objfile *objfile, void *datum)
{
htab_t htab = (htab_t) datum;
if (htab != NULL)
{
htab_traverse_noresize (htab, stscm_mark_symtab_invalid, NULL);
htab_delete (htab);
}
}
/* Symbol table methods. */
@ -687,14 +688,3 @@ gdbscm_initialize_symtabs (void)
gdbscm_define_functions (symtab_functions, 1);
}
void _initialize_scm_symtab ();
void
_initialize_scm_symtab ()
{
/* Register an objfile "free" callback so we can properly
invalidate symbol tables, and symbol table and line data
structures when an object file that is about to be deleted. */
stscm_objfile_data_key
= register_objfile_data_with_cleanup (NULL, stscm_del_objfile_symtabs);
}

View File

@ -81,7 +81,30 @@ static SCM tyscm_next_field_x_proc;
/* Keywords used in argument passing. */
static SCM block_keyword;
static const struct objfile_data *tyscm_objfile_data_key;
static int tyscm_copy_type_recursive (void **slot, void *info);
/* Called when an objfile is about to be deleted.
Make a copy of all types associated with OBJFILE. */
struct tyscm_deleter
{
void operator() (htab_t htab)
{
if (!gdb_scheme_initialized)
return;
htab_up copied_types = create_copied_types_hash ();
if (htab != NULL)
{
htab_traverse_noresize (htab, tyscm_copy_type_recursive, copied_types.get ());
htab_delete (htab);
}
}
};
static const registry<objfile>::key<htab, tyscm_deleter>
tyscm_objfile_data_key;
/* Hash table to uniquify global (non-objfile-owned) types. */
static htab_t global_types_map;
@ -158,12 +181,12 @@ tyscm_type_map (struct type *type)
if (objfile == NULL)
return global_types_map;
htab = (htab_t) objfile_data (objfile, tyscm_objfile_data_key);
htab = tyscm_objfile_data_key.get (objfile);
if (htab == NULL)
{
htab = gdbscm_create_eqable_gsmob_ptr_map (tyscm_hash_type_smob,
tyscm_eq_type_smob);
set_objfile_data (objfile, tyscm_objfile_data_key, htab);
tyscm_objfile_data_key.set (objfile, htab);
}
return htab;
@ -345,20 +368,17 @@ tyscm_scm_to_type (SCM t_scm)
return t_smob->type;
}
/* Helper function for save_objfile_types to make a deep copy of the type. */
/* Helper function to make a deep copy of the type. */
static int
tyscm_copy_type_recursive (void **slot, void *info)
{
type_smob *t_smob = (type_smob *) *slot;
htab_t copied_types = (htab_t) info;
struct objfile *objfile = t_smob->type->objfile_owner ();
htab_t htab;
eqable_gdb_smob **new_slot;
type_smob t_smob_for_lookup;
gdb_assert (objfile != NULL);
htab_empty (copied_types);
t_smob->type = copy_type_recursive (t_smob->type, copied_types);
@ -380,25 +400,6 @@ tyscm_copy_type_recursive (void **slot, void *info)
return 1;
}
/* Called when OBJFILE is about to be deleted.
Make a copy of all types associated with OBJFILE. */
static void
save_objfile_types (struct objfile *objfile, void *datum)
{
htab_t htab = (htab_t) datum;
if (!gdb_scheme_initialized)
return;
htab_up copied_types = create_copied_types_hash ();
if (htab != NULL)
{
htab_traverse_noresize (htab, tyscm_copy_type_recursive, copied_types.get ());
htab_delete (htab);
}
}
/* Administrivia for field smobs. */
@ -1510,13 +1511,3 @@ Internal function to assist the type fields iterator."));
global_types_map = gdbscm_create_eqable_gsmob_ptr_map (tyscm_hash_type_smob,
tyscm_eq_type_smob);
}
void _initialize_scm_type ();
void
_initialize_scm_type ()
{
/* Register an objfile "free" callback so we can properly copy types
associated with the objfile when it's about to be deleted. */
tyscm_objfile_data_key
= register_objfile_data_with_cleanup (save_objfile_types, NULL);
}

View File

@ -84,7 +84,8 @@ struct hppa_objfile_private
that separately and make this static. The solib data is probably hpux-
specific, so we can create a separate extern objfile_data that is registered
by hppa-hpux-tdep.c and shared with pa64solib.c and somsolib.c. */
static const struct objfile_key<hppa_objfile_private> hppa_objfile_priv_data;
static const registry<objfile>::key<hppa_objfile_private>
hppa_objfile_priv_data;
/* Get at various relevant fields of an instruction word. */
#define MASK_5 0x1f

View File

@ -38,11 +38,6 @@
#include "gdbsupport/buildargv.h"
#include "cli/cli-style.h"
/* Keep a registry of per-inferior data-pointers required by other GDB
modules. */
DEFINE_REGISTRY (inferior, REGISTRY_ACCESS_FIELD)
intrusive_list<inferior> inferior_list;
static int highest_inferior_num;
@ -76,18 +71,14 @@ inferior::~inferior ()
inferior *inf = this;
m_continuations.clear ();
inferior_free_data (inf);
target_desc_info_free (inf->tdesc_info);
}
inferior::inferior (int pid_)
: num (++highest_inferior_num),
pid (pid_),
environment (gdb_environ::from_host_environ ()),
registry_data ()
environment (gdb_environ::from_host_environ ())
{
inferior_alloc_data (this);
m_target_stack.push (get_dummy_target ());
}

View File

@ -595,7 +595,7 @@ public:
displaced_step_inferior_state displaced_step_state;
/* Per inferior data-pointers required by other GDB modules. */
REGISTRY_FIELDS;
registry<inferior> registry_fields;
private:
/* The inferior's target stack. */
@ -615,11 +615,6 @@ private:
std::string m_cwd;
};
/* Keep a registry of per-inferior data-pointers required by other GDB
modules. */
DECLARE_REGISTRY (inferior);
/* Add an inferior to the inferior list, print a message that a new
inferior is found, and return the pointer to the new inferior.
Caller may use this pointer to initialize the private inferior

View File

@ -599,7 +599,7 @@ child_pass_ctrlc (struct target_ops *self)
}
/* Per-inferior data key. */
static const struct inferior_key<terminal_info> inflow_inferior_data;
static const registry<inferior>::key<terminal_info> inflow_inferior_data;
terminal_info::~terminal_info ()
{

View File

@ -236,7 +236,7 @@ struct linux_info
};
/* Per-inferior data key. */
static const struct inferior_key<linux_info> linux_inferior_data;
static const registry<inferior>::key<linux_info> linux_inferior_data;
/* Frees whatever allocated space there is to be freed and sets INF's
linux cache data pointer to NULL. */

View File

@ -1354,8 +1354,8 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
/* Basic types. */
static const struct objfile_key<struct type *,
gdb::noop_deleter<struct type *>>
static const registry<objfile>::key<struct type *,
gdb::noop_deleter<struct type *>>
basic_type_data;
static struct type *

View File

@ -28,7 +28,7 @@
/* We stash a reference to the .gnu_debugdata BFD on the enclosing
BFD. */
static const bfd_key<gdb_bfd_ref_ptr> gnu_debug_key;
static const registry<bfd>::key<gdb_bfd_ref_ptr> gnu_debug_key;
#include <lzma.h>

View File

@ -51,7 +51,7 @@ static char default_nto_target[] = "";
struct nto_target_ops current_nto_target;
static const struct inferior_key<struct nto_inferior_data>
static const registry<inferior>::key<struct nto_inferior_data>
nto_inferior_data_reg;
static char *

View File

@ -76,7 +76,7 @@ struct objc_method {
CORE_ADDR imp;
};
static const struct objfile_key<unsigned int> objc_objfile_data;
static const registry<objfile>::key<unsigned int> objc_objfile_data;
/* Lookup a structure type named "struct NAME", visible in lexical
block BLOCK. If NOERR is nonzero, return zero if NAME is not

View File

@ -57,11 +57,6 @@
#include <algorithm>
#include <vector>
/* Keep a registry of per-objfile data-pointers required by other GDB
modules. */
DEFINE_REGISTRY (objfile, REGISTRY_ACCESS_FIELD)
/* Externally visible variables that are owned by this module.
See declarations in objfile.h for more info. */
@ -85,7 +80,7 @@ struct objfile_pspace_info
};
/* Per-program-space data key. */
static const struct program_space_key<objfile_pspace_info>
static const registry<program_space>::key<objfile_pspace_info>
objfiles_pspace_data;
objfile_pspace_info::~objfile_pspace_info ()
@ -112,7 +107,7 @@ get_objfile_pspace_data (struct program_space *pspace)
/* Per-BFD data key. */
static const struct bfd_key<objfile_per_bfd_storage> objfiles_bfd_data;
static const registry<bfd>::key<objfile_per_bfd_storage> objfiles_bfd_data;
objfile_per_bfd_storage::~objfile_per_bfd_storage ()
{
@ -329,8 +324,6 @@ objfile::objfile (bfd *abfd, const char *name, objfile_flags flags_)
gdb_obstack.h specifies the alloc/dealloc functions. */
obstack_init (&objfile_obstack);
objfile_alloc_data (this);
std::string name_holder;
if (name == NULL)
{
@ -563,10 +556,6 @@ objfile::~objfile ()
if (sf != NULL)
(*sf->sym_finish) (this);
/* Discard any data modules have associated with the objfile. The function
still may reference obfd. */
objfile_free_data (this);
if (obfd)
gdb_bfd_unref (obfd);
else

View File

@ -682,7 +682,7 @@ public:
/* Per objfile data-pointers required by other GDB modules. */
REGISTRY_FIELDS {};
registry<objfile> registry_fields;
/* Set of relocation offsets to apply to each section.
The table is indexed by the_bfd_section->index, thus it is generally
@ -900,10 +900,6 @@ in_plt_section (CORE_ADDR pc)
|| pc_in_section (pc, ".plt.sec"));
}
/* Keep a registry of per-objfile data-pointers required by other GDB
modules. */
DECLARE_REGISTRY(objfile);
/* In normal use, the section map will be rebuilt by find_pc_section
if objfiles have been added, removed or relocated since it was last
called. Calling inhibit_section_map_updates will inhibit this

View File

@ -43,24 +43,11 @@ static int highest_address_space_num;
/* Keep a registry of per-program_space data-pointers required by other GDB
modules. */
DEFINE_REGISTRY (program_space, REGISTRY_ACCESS_FIELD)
/* Keep a registry of per-address_space data-pointers required by other GDB
modules. */
DEFINE_REGISTRY (address_space, REGISTRY_ACCESS_FIELD)
/* Create a new address space object, and add it to the list. */
address_space::address_space ()
: m_num (++highest_address_space_num)
{
address_space_alloc_data (this);
}
/* Maybe create a new address space object, and add it to the list, or
@ -81,11 +68,6 @@ maybe_new_address_space (void)
return new address_space ();
}
address_space::~address_space ()
{
address_space_free_data (this);
}
/* Start counting over from scratch. */
static void
@ -115,8 +97,6 @@ program_space::program_space (address_space *aspace_)
: num (++last_program_space_num),
aspace (aspace_)
{
program_space_alloc_data (this);
program_spaces.push_back (this);
}
@ -140,8 +120,6 @@ program_space::~program_space ()
clear_symtab_users (SYMFILE_DEFER_BP_RESET);
if (!gdbarch_has_shared_address_space (target_gdbarch ()))
delete this->aspace;
/* Discard any data modules have associated with the PSPACE. */
program_space_free_data (this);
}
/* See progspace.h. */

View File

@ -37,8 +37,7 @@ struct objfile;
struct inferior;
struct exec;
struct address_space;
struct program_space_data;
struct address_space_data;
struct program_space;
struct so_list;
typedef std::list<std::unique_ptr<objfile>> objfile_list;
@ -372,7 +371,7 @@ struct program_space
std::vector<std::string> deleted_solibs;
/* Per pspace data-pointers required by other GDB modules. */
REGISTRY_FIELDS {};
registry<program_space> registry_fields;
private:
/* The set of target sections matching the sections mapped into
@ -387,7 +386,6 @@ struct address_space
{
/* Create a new address space object, and add it to the list. */
address_space ();
~address_space ();
DISABLE_COPY_AND_ASSIGN (address_space);
/* Returns the integer address space id of this address space. */
@ -397,7 +395,7 @@ struct address_space
}
/* Per aspace data-pointers required by other GDB modules. */
REGISTRY_FIELDS {};
registry<address_space> registry_fields;
private:
int m_num;
@ -457,14 +455,4 @@ extern struct address_space *maybe_new_address_space (void);
mappings. */
extern void update_address_spaces (void);
/* Keep a registry of per-pspace data-pointers required by other GDB
modules. */
DECLARE_REGISTRY (program_space);
/* Keep a registry of per-aspace data-pointers required by other GDB
modules. */
DECLARE_REGISTRY (address_space);
#endif

View File

@ -77,9 +77,33 @@ struct block_syms_iterator_object {
} \
} while (0)
/* This is called when an objfile is about to be freed.
Invalidate the block as further actions on the block would result
in bad data. All access to obj->symbol should be gated by
BLPY_REQUIRE_VALID which will raise an exception on invalid
blocks. */
struct blpy_deleter
{
void operator() (block_object *obj)
{
while (obj)
{
block_object *next = obj->next;
obj->block = NULL;
obj->objfile = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
};
extern PyTypeObject block_syms_iterator_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("block_syms_iterator_object");
static const struct objfile_data *blpy_objfile_data_key;
static const registry<objfile>::key<block_object, blpy_deleter>
blpy_objfile_data_key;
static PyObject *
blpy_iter (PyObject *self)
@ -269,10 +293,7 @@ blpy_dealloc (PyObject *obj)
if (block->prev)
block->prev->next = block->next;
else if (block->objfile)
{
set_objfile_data (block->objfile, blpy_objfile_data_key,
block->next);
}
blpy_objfile_data_key.set (block->objfile, block->next);
if (block->next)
block->next->prev = block->prev;
block->block = NULL;
@ -293,11 +314,10 @@ set_block (block_object *obj, const struct block *block,
if (objfile)
{
obj->objfile = objfile;
obj->next = ((block_object *)
objfile_data (objfile, blpy_objfile_data_key));
obj->next = blpy_objfile_data_key.get (objfile);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (objfile, blpy_objfile_data_key, obj);
blpy_objfile_data_key.set (objfile, obj);
}
else
obj->next = NULL;
@ -404,40 +424,6 @@ blpy_iter_is_valid (PyObject *self, PyObject *args)
Py_RETURN_TRUE;
}
/* This function is called when an objfile is about to be freed.
Invalidate the block as further actions on the block would result
in bad data. All access to obj->symbol should be gated by
BLPY_REQUIRE_VALID which will raise an exception on invalid
blocks. */
static void
del_objfile_blocks (struct objfile *objfile, void *datum)
{
block_object *obj = (block_object *) datum;
while (obj)
{
block_object *next = obj->next;
obj->block = NULL;
obj->objfile = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
void _initialize_py_block ();
void
_initialize_py_block ()
{
/* Register an objfile "free" callback so we can properly
invalidate blocks when an object file is about to be
deleted. */
blpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_blocks);
}
int
gdbpy_initialize_blocks (void)
{

View File

@ -60,7 +60,35 @@ struct inferior_object
extern PyTypeObject inferior_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
static const struct inferior_data *infpy_inf_data_key;
/* Deleter to clean up when an inferior is removed. */
struct infpy_deleter
{
void operator() (inferior_object *obj)
{
struct threadlist_entry *th_entry, *th_tmp;
if (!gdb_python_initialized)
return;
gdbpy_enter enter_py;
gdbpy_ref<inferior_object> inf_obj (obj);
inf_obj->inferior = NULL;
/* Deallocate threads list. */
for (th_entry = inf_obj->threads; th_entry != NULL;)
{
th_tmp = th_entry;
th_entry = th_entry->next;
delete th_tmp;
}
inf_obj->nthreads = 0;
}
};
static const registry<inferior>::key<inferior_object, infpy_deleter>
infpy_inf_data_key;
/* Require that INFERIOR be a valid inferior ID. */
#define INFPY_REQUIRE_VALID(Inferior) \
@ -221,7 +249,7 @@ inferior_to_inferior_object (struct inferior *inferior)
{
inferior_object *inf_obj;
inf_obj = (inferior_object *) inferior_data (inferior, infpy_inf_data_key);
inf_obj = infpy_inf_data_key.get (inferior);
if (!inf_obj)
{
inf_obj = PyObject_New (inferior_object, &inferior_object_type);
@ -234,7 +262,7 @@ inferior_to_inferior_object (struct inferior *inferior)
/* PyObject_New initializes the new object with a refcount of 1. This
counts for the reference we are keeping in the inferior data. */
set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
infpy_inf_data_key.set (inferior, inf_obj);
}
/* We are returning a new reference. */
@ -795,32 +823,6 @@ infpy_dealloc (PyObject *obj)
Py_TYPE (obj)->tp_free (obj);
}
/* Clear the INFERIOR pointer in an Inferior object and clear the
thread list. */
static void
py_free_inferior (struct inferior *inf, void *datum)
{
struct threadlist_entry *th_entry, *th_tmp;
if (!gdb_python_initialized)
return;
gdbpy_enter enter_py;
gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
inf_obj->inferior = NULL;
/* Deallocate threads list. */
for (th_entry = inf_obj->threads; th_entry != NULL;)
{
th_tmp = th_entry;
th_entry = th_entry->next;
delete th_tmp;
}
inf_obj->nthreads = 0;
}
/* Implementation of gdb.selected_inferior() -> gdb.Inferior.
Returns the current inferior object. */
@ -831,14 +833,6 @@ gdbpy_selected_inferior (PyObject *self, PyObject *args)
inferior_to_inferior_object (current_inferior ()).release ());
}
void _initialize_py_inferior ();
void
_initialize_py_inferior ()
{
infpy_inf_data_key =
register_inferior_data_with_cleanup (NULL, py_free_inferior);
}
int
gdbpy_initialize_inferior (void)
{

View File

@ -55,7 +55,20 @@ struct objfile_object
extern PyTypeObject objfile_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("objfile_object");
static const struct objfile_data *objfpy_objfile_data_key;
/* Clear the OBJFILE pointer in an Objfile object and remove the
reference. */
struct objfpy_deleter
{
void operator() (objfile_object *obj)
{
gdbpy_enter enter_py;
gdbpy_ref<objfile_object> object (obj);
object->objfile = nullptr;
}
};
static const registry<objfile>::key<objfile_object, objfpy_deleter>
objfpy_objfile_data_key;
/* Require that OBJF be a valid objfile. */
#define OBJFPY_REQUIRE_VALID(obj) \
@ -668,16 +681,6 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
/* Clear the OBJFILE pointer in an Objfile object and remove the
reference. */
static void
py_free_objfile (struct objfile *objfile, void *datum)
{
gdbpy_enter enter_py (objfile->arch ());
gdbpy_ref<objfile_object> object ((objfile_object *) datum);
object->objfile = NULL;
}
/* Return a new reference to the Python object of type Objfile
representing OBJFILE. If the object has already been created,
return it. Otherwise, create it. Return NULL and set the Python
@ -687,7 +690,7 @@ gdbpy_ref<>
objfile_to_objfile_object (struct objfile *objfile)
{
PyObject *result
= ((PyObject *) objfile_data (objfile, objfpy_objfile_data_key));
= (PyObject *) objfpy_objfile_data_key.get (objfile);
if (result == NULL)
{
gdbpy_ref<objfile_object> object
@ -698,21 +701,13 @@ objfile_to_objfile_object (struct objfile *objfile)
return NULL;
object->objfile = objfile;
set_objfile_data (objfile, objfpy_objfile_data_key, object.get ());
objfpy_objfile_data_key.set (objfile, object.get ());
result = (PyObject *) object.release ();
}
return gdbpy_ref<>::new_reference (result);
}
void _initialize_py_objfile ();
void
_initialize_py_objfile ()
{
objfpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, py_free_objfile);
}
int
gdbpy_initialize_objfile (void)
{

View File

@ -57,7 +57,30 @@ struct pspace_object
extern PyTypeObject pspace_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pspace_object");
static const struct program_space_data *pspy_pspace_data_key;
/* Clear the PSPACE pointer in a Pspace object and remove the reference. */
struct pspace_deleter
{
void operator() (pspace_object *obj)
{
/* This is a fiction, but we're in a nasty spot: The pspace is in the
process of being deleted, we can't rely on anything in it. Plus
this is one time when the current program space and current inferior
are not in sync: All inferiors that use PSPACE may no longer exist.
We don't need to do much here, and since "there is always an inferior"
using target_gdbarch suffices.
Note: We cannot call get_current_arch because it may try to access
the target, which may involve accessing data in the pspace currently
being deleted. */
struct gdbarch *arch = target_gdbarch ();
gdbpy_enter enter_py (arch);
gdbpy_ref<pspace_object> object (obj);
object->pspace = NULL;
}
};
static const registry<program_space>::key<pspace_object, pspace_deleter>
pspy_pspace_data_key;
/* Require that PSPACE_OBJ be a valid program space ID. */
#define PSPY_REQUIRE_VALID(pspace_obj) \
@ -463,27 +486,6 @@ pspy_is_valid (PyObject *o, PyObject *args)
/* Clear the PSPACE pointer in a Pspace object and remove the reference. */
static void
py_free_pspace (struct program_space *pspace, void *datum)
{
/* This is a fiction, but we're in a nasty spot: The pspace is in the
process of being deleted, we can't rely on anything in it. Plus
this is one time when the current program space and current inferior
are not in sync: All inferiors that use PSPACE may no longer exist.
We don't need to do much here, and since "there is always an inferior"
using target_gdbarch suffices.
Note: We cannot call get_current_arch because it may try to access
the target, which may involve accessing data in the pspace currently
being deleted. */
struct gdbarch *arch = target_gdbarch ();
gdbpy_enter enter_py (arch);
gdbpy_ref<pspace_object> object ((pspace_object *) datum);
object->pspace = NULL;
}
/* Return a new reference to the Python object of type Pspace
representing PSPACE. If the object has already been created,
return it. Otherwise, create it. Return NULL and set the Python
@ -492,8 +494,7 @@ py_free_pspace (struct program_space *pspace, void *datum)
gdbpy_ref<>
pspace_to_pspace_object (struct program_space *pspace)
{
PyObject *result
((PyObject *) program_space_data (pspace, pspy_pspace_data_key));
PyObject *result = (PyObject *) pspy_pspace_data_key.get (pspace);
if (result == NULL)
{
gdbpy_ref<pspace_object> object
@ -504,7 +505,7 @@ pspace_to_pspace_object (struct program_space *pspace)
return NULL;
object->pspace = pspace;
set_program_space_data (pspace, pspy_pspace_data_key, object.get ());
pspy_pspace_data_key.set (pspace, object.get ());
result = (PyObject *) object.release ();
}
@ -528,14 +529,6 @@ gdbpy_is_progspace (PyObject *obj)
return PyObject_TypeCheck (obj, &pspace_object_type);
}
void _initialize_py_progspace ();
void
_initialize_py_progspace ()
{
pspy_pspace_data_key
= register_program_space_data_with_cleanup (NULL, py_free_pspace);
}
int
gdbpy_initialize_pspace (void)
{

View File

@ -50,7 +50,26 @@ struct symbol_object {
} \
} while (0)
static const struct objfile_data *sympy_objfile_data_key;
/* A deleter that is used when an objfile is about to be freed. */
struct symbol_object_deleter
{
void operator() (symbol_object *obj)
{
while (obj)
{
symbol_object *next = obj->next;
obj->symbol = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
};
static const registry<objfile>::key<symbol_object, symbol_object_deleter>
sympy_objfile_data_key;
static PyObject *
sympy_str (PyObject *self)
@ -307,11 +326,10 @@ set_symbol (symbol_object *obj, struct symbol *symbol)
{
struct objfile *objfile = symbol->objfile ();
obj->next = ((symbol_object *)
objfile_data (objfile, sympy_objfile_data_key));
obj->next = sympy_objfile_data_key.get (objfile);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (objfile, sympy_objfile_data_key, obj);
sympy_objfile_data_key.set (objfile, obj);
}
else
obj->next = NULL;
@ -350,10 +368,7 @@ sympy_dealloc (PyObject *obj)
else if (sym_obj->symbol != NULL
&& sym_obj->symbol->is_objfile_owned ()
&& sym_obj->symbol->symtab () != NULL)
{
set_objfile_data (sym_obj->symbol->objfile (),
sympy_objfile_data_key, sym_obj->next);
}
sympy_objfile_data_key.set (sym_obj->symbol->objfile (), sym_obj->next);
if (sym_obj->next)
sym_obj->next->prev = sym_obj->prev;
sym_obj->symbol = NULL;
@ -596,38 +611,6 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
return return_list.release ();
}
/* This function is called when an objfile is about to be freed.
Invalidate the symbol as further actions on the symbol would result
in bad data. All access to obj->symbol should be gated by
SYMPY_REQUIRE_VALID which will raise an exception on invalid
symbols. */
static void
del_objfile_symbols (struct objfile *objfile, void *datum)
{
symbol_object *obj = (symbol_object *) datum;
while (obj)
{
symbol_object *next = obj->next;
obj->symbol = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
void _initialize_py_symbol ();
void
_initialize_py_symbol ()
{
/* Register an objfile "free" callback so we can properly
invalidate symbol when an object file that is about to be
deleted. */
sympy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_symbols);
}
int
gdbpy_initialize_symbols (void)
{

View File

@ -37,9 +37,31 @@ struct symtab_object {
symtab_object *next;
};
/* This function is called when an objfile is about to be freed.
Invalidate the symbol table as further actions on the symbol table
would result in bad data. All access to obj->symtab should be
gated by STPY_REQUIRE_VALID which will raise an exception on
invalid symbol tables. */
struct stpy_deleter
{
void operator() (symtab_object *obj)
{
while (obj)
{
symtab_object *next = obj->next;
obj->symtab = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
};
extern PyTypeObject symtab_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("symtab_object");
static const struct objfile_data *stpy_objfile_data_key;
static const registry<objfile>::key<symtab_object, stpy_deleter>
stpy_objfile_data_key;
/* Require a valid symbol table. All access to symtab_object->symtab
should be gated by this call. */
@ -68,9 +90,39 @@ struct sal_object {
sal_object *next;
};
/* This is called when an objfile is about to be freed. Invalidate
the sal object as further actions on the sal would result in bad
data. All access to obj->sal should be gated by
SALPY_REQUIRE_VALID which will raise an exception on invalid symbol
table and line objects. */
struct salpy_deleter
{
void operator() (sal_object *obj)
{
gdbpy_enter enter_py;
while (obj)
{
sal_object *next = obj->next;
gdbpy_ref<> tmp (obj->symtab);
obj->symtab = Py_None;
Py_INCREF (Py_None);
obj->next = NULL;
obj->prev = NULL;
xfree (obj->sal);
obj->sal = NULL;
obj = next;
}
}
};
extern PyTypeObject sal_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("sal_object");
static const struct objfile_data *salpy_objfile_data_key;
static const registry<objfile>::key<sal_object, salpy_deleter>
salpy_objfile_data_key;
/* Require a valid symbol table and line object. All access to
sal_object->sal should be gated by this call. */
@ -246,10 +298,8 @@ stpy_dealloc (PyObject *obj)
if (symtab->prev)
symtab->prev->next = symtab->next;
else if (symtab->symtab)
{
set_objfile_data (symtab->symtab->compunit ()->objfile (),
stpy_objfile_data_key, symtab->next);
}
stpy_objfile_data_key.set (symtab->symtab->compunit ()->objfile (),
symtab->next);
if (symtab->next)
symtab->next->prev = symtab->prev;
symtab->symtab = NULL;
@ -329,9 +379,9 @@ salpy_dealloc (PyObject *self)
if (self_sal->prev)
self_sal->prev->next = self_sal->next;
else if (self_sal->symtab != Py_None)
set_objfile_data
salpy_objfile_data_key.set
(symtab_object_to_symtab (self_sal->symtab)->compunit ()->objfile (),
salpy_objfile_data_key, self_sal->next);
self_sal->next);
if (self_sal->next)
self_sal->next->prev = self_sal->prev;
@ -378,13 +428,11 @@ set_sal (sal_object *sal_obj, struct symtab_and_line sal)
symtab *symtab = symtab_object_to_symtab (sal_obj->symtab);
sal_obj->next
= ((sal_object *) objfile_data (symtab->compunit ()->objfile (),
salpy_objfile_data_key));
= salpy_objfile_data_key.get (symtab->compunit ()->objfile ());
if (sal_obj->next)
sal_obj->next->prev = sal_obj;
set_objfile_data (symtab->compunit ()->objfile (),
salpy_objfile_data_key, sal_obj);
salpy_objfile_data_key.set (symtab->compunit ()->objfile (), sal_obj);
}
else
sal_obj->next = NULL;
@ -404,14 +452,10 @@ set_symtab (symtab_object *obj, struct symtab *symtab)
obj->prev = NULL;
if (symtab)
{
obj->next
= ((symtab_object *)
objfile_data (symtab->compunit ()->objfile (),
stpy_objfile_data_key));
obj->next = stpy_objfile_data_key.get (symtab->compunit ()->objfile ());
if (obj->next)
obj->next->prev = obj;
set_objfile_data (symtab->compunit ()->objfile (),
stpy_objfile_data_key, obj);
stpy_objfile_data_key.set (symtab->compunit ()->objfile (), obj);
}
else
obj->next = NULL;
@ -465,68 +509,6 @@ symtab_object_to_symtab (PyObject *obj)
return ((symtab_object *) obj)->symtab;
}
/* This function is called when an objfile is about to be freed.
Invalidate the symbol table as further actions on the symbol table
would result in bad data. All access to obj->symtab should be
gated by STPY_REQUIRE_VALID which will raise an exception on
invalid symbol tables. */
static void
del_objfile_symtab (struct objfile *objfile, void *datum)
{
symtab_object *obj = (symtab_object *) datum;
while (obj)
{
symtab_object *next = obj->next;
obj->symtab = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
/* This function is called when an objfile is about to be freed.
Invalidate the sal object as further actions on the sal
would result in bad data. All access to obj->sal should be
gated by SALPY_REQUIRE_VALID which will raise an exception on
invalid symbol table and line objects. */
static void
del_objfile_sal (struct objfile *objfile, void *datum)
{
sal_object *obj = (sal_object *) datum;
while (obj)
{
sal_object *next = obj->next;
gdbpy_ref<> tmp (obj->symtab);
obj->symtab = Py_None;
Py_INCREF (Py_None);
obj->next = NULL;
obj->prev = NULL;
xfree (obj->sal);
obj->sal = NULL;
obj = next;
}
}
void _initialize_py_symtab ();
void
_initialize_py_symtab ()
{
/* Register an objfile "free" callback so we can properly
invalidate symbol tables, and symbol table and line data
structures when an object file that is about to be
deleted. */
stpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_symtab);
salpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_sal);
}
int
gdbpy_initialize_symtabs (void)
{

View File

@ -1109,36 +1109,38 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
static const struct objfile_data *typy_objfile_data_key;
static void
save_objfile_types (struct objfile *objfile, void *datum)
/* Deleter that saves types when an objfile is being destroyed. */
struct typy_deleter
{
type_object *obj = (type_object *) datum;
void operator() (type_object *obj)
{
if (!gdb_python_initialized)
return;
if (!gdb_python_initialized)
return;
/* This prevents another thread from freeing the objects we're
operating on. */
gdbpy_enter enter_py;
/* This prevents another thread from freeing the objects we're
operating on. */
gdbpy_enter enter_py (objfile->arch ());
htab_up copied_types = create_copied_types_hash ();
htab_up copied_types = create_copied_types_hash ();
while (obj)
{
type_object *next = obj->next;
while (obj)
{
type_object *next = obj->next;
htab_empty (copied_types.get ());
htab_empty (copied_types.get ());
obj->type = copy_type_recursive (obj->type, copied_types.get ());
obj->type = copy_type_recursive (obj->type, copied_types.get ());
obj->next = NULL;
obj->prev = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
};
obj = next;
}
}
static const registry<objfile>::key<type_object, typy_deleter>
typy_objfile_data_key;
static void
set_type (type_object *obj, struct type *type)
@ -1149,11 +1151,10 @@ set_type (type_object *obj, struct type *type)
{
struct objfile *objfile = type->objfile_owner ();
obj->next = ((type_object *)
objfile_data (objfile, typy_objfile_data_key));
obj->next = typy_objfile_data_key.get (objfile);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (objfile, typy_objfile_data_key, obj);
typy_objfile_data_key.set (objfile, obj);
}
else
obj->next = NULL;
@ -1172,7 +1173,7 @@ typy_dealloc (PyObject *obj)
struct objfile *objfile = type->type->objfile_owner ();
if (objfile)
set_objfile_data (objfile, typy_objfile_data_key, type->next);
typy_objfile_data_key.set (objfile, type->next);
}
if (type->next)
type->next->prev = type->prev;
@ -1464,14 +1465,6 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
return type_to_type_object (type);
}
void _initialize_py_type ();
void
_initialize_py_type ()
{
typy_objfile_data_key
= register_objfile_data_with_cleanup (save_objfile_types, NULL);
}
int
gdbpy_initialize_types (void)
{

View File

@ -1,112 +0,0 @@
/* Support functions for general registry objects.
Copyright (C) 2011-2022 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "registry.h"
const struct registry_data *
register_data_with_cleanup (struct registry_data_registry *registry,
registry_data_callback save,
registry_data_callback free)
{
struct registry_data_registration **curr;
/* Append new registration. */
for (curr = &registry->registrations;
*curr != NULL;
curr = &(*curr)->next)
;
*curr = XNEW (struct registry_data_registration);
(*curr)->next = NULL;
(*curr)->data = XNEW (struct registry_data);
(*curr)->data->index = registry->num_registrations++;
(*curr)->data->save = save;
(*curr)->data->free = free;
return (*curr)->data;
}
void
registry_alloc_data (struct registry_data_registry *registry,
struct registry_fields *fields)
{
gdb_assert (fields->data == NULL);
fields->num_data = registry->num_registrations;
fields->data = XCNEWVEC (void *, fields->num_data);
}
void
registry_clear_data (struct registry_data_registry *data_registry,
registry_callback_adaptor adaptor,
struct registry_container *container,
struct registry_fields *fields)
{
struct registry_data_registration *registration;
int i;
gdb_assert (fields->data != NULL);
/* Process all the save handlers. */
for (registration = data_registry->registrations, i = 0;
i < fields->num_data;
registration = registration->next, i++)
if (fields->data[i] != NULL && registration->data->save != NULL)
adaptor (registration->data->save, container, fields->data[i]);
/* Now process all the free handlers. */
for (registration = data_registry->registrations, i = 0;
i < fields->num_data;
registration = registration->next, i++)
if (fields->data[i] != NULL && registration->data->free != NULL)
adaptor (registration->data->free, container, fields->data[i]);
memset (fields->data, 0, fields->num_data * sizeof (void *));
}
void
registry_container_free_data (struct registry_data_registry *data_registry,
registry_callback_adaptor adaptor,
struct registry_container *container,
struct registry_fields *fields)
{
void ***rdata = &fields->data;
gdb_assert (*rdata != NULL);
registry_clear_data (data_registry, adaptor, container, fields);
xfree (*rdata);
*rdata = NULL;
}
void
registry_set_data (struct registry_fields *fields,
const struct registry_data *data,
void *value)
{
gdb_assert (data->index < fields->num_data);
fields->data[data->index] = value;
}
void *
registry_data (struct registry_fields *fields,
const struct registry_data *data)
{
gdb_assert (data->index < fields->num_data);
return fields->data[data->index];
}

View File

@ -22,288 +22,214 @@
#include <type_traits>
/* The macros here implement a template type and functions for
associating some user data with a container object.
template<typename T> class registry;
A registry is associated with a struct tag name. To attach a
registry to a structure, use DEFINE_REGISTRY. This takes the
structure tag and an access method as arguments. In the usual
case, where the registry fields appear directly in the struct, you
can use the 'REGISTRY_FIELDS' macro to declare the fields in the
struct definition, and you can pass 'REGISTRY_ACCESS_FIELD' as the
access argument to DEFINE_REGISTRY. In other cases, use
REGISTRY_FIELDS to define the fields in the appropriate spot, and
then define your own accessor to find the registry field structure
given an instance of your type.
/* An accessor class that is used by registry_key.
The API user requests a key from a registry during gdb
initialization. Later this key can be used to associate some
module-specific data with a specific container object.
Normally, a container class has a registry<> field named
"registry_fields". In this case, the default accessor is used, as
it simply returns the object.
The exported API is best used via the wrapper macros:
- register_TAG_data(TAG)
Get a new key for the container type TAG.
- register_TAG_data_with_cleanup(TAG, SAVE, FREE)
Get a new key for the container type TAG.
SAVE and FREE are defined as void (*) (struct TAG *object, void *data)
When the container object OBJECT is destroyed, first all registered SAVE
functions are called.
Then all FREE functions are called.
Either or both may be NULL. DATA is the data associated with the
container object OBJECT.
- clear_TAG_data(TAG, OBJECT)
Clear all the data associated with OBJECT. Should be called by the
container implementation when a container object is destroyed.
- set_TAG_data(TAG, OBJECT, KEY, DATA)
Set the data on an object.
- TAG_data(TAG, OBJECT, KEY)
Fetch the data for an object; returns NULL if it has not been set.
*/
However, a container may sometimes need to store the registry
elsewhere. In this case, registry_accessor can be specialized to
perform the needed indirection. */
/* This structure is used in a container to hold the data that the
registry uses. */
struct registry_fields
template<typename T>
struct registry_accessor
{
void **data;
unsigned num_data;
/* Given a container of type T, return its registry. */
static registry<T> *get (T *obj)
{
return &obj->registry_fields;
}
};
/* This macro is used in a container struct definition to define the
fields used by the registry code. */
/* In gdb, sometimes there is a need for one module (e.g., the Python
Type code) to attach some data to another object (e.g., an
objfile); but it's also desirable that this be done such that the
base object (the objfile in this example) not need to know anything
about the attaching module (the Python code).
#define REGISTRY_FIELDS \
struct registry_fields registry_data
This is handled using the registry system.
/* A convenience macro for the typical case where the registry data is
kept as fields of the object. This can be passed as the ACCESS
method to DEFINE_REGISTRY. */
A class needing to allow this sort registration can add a registry
field. For example, you would write:
#define REGISTRY_ACCESS_FIELD(CONTAINER) \
(CONTAINER)
class some_container { registry<some_container> registry_fields; };
/* Opaque type representing a container type with a registry. This
type is never defined. This is used to factor out common
functionality of all struct tag names into common code. IOW,
"struct tag name" pointers are cast to and from "struct
registry_container" pointers when calling the common registry
"backend" functions. */
struct registry_container;
The name of the field matters by default, see registry_accessor.
/* Registry callbacks have this type. */
typedef void (*registry_data_callback) (struct registry_container *, void *);
A module wanting to attach data to instances of some_container uses
the "key" class to register a key. This key can then be passed to
the "get" and "set" methods to handle this module's data. */
struct registry_data
template<typename T>
class registry
{
unsigned index;
registry_data_callback save;
registry_data_callback free;
};
public:
struct registry_data_registration
{
struct registry_data *data;
struct registry_data_registration *next;
};
registry ()
: m_fields (get_registrations ().size ())
{
}
struct registry_data_registry
{
struct registry_data_registration *registrations;
unsigned num_registrations;
};
~registry ()
{
clear_registry ();
}
/* Registry backend functions. Client code uses the frontend
functions defined by DEFINE_REGISTRY below instead. */
DISABLE_COPY_AND_ASSIGN (registry);
const struct registry_data *register_data_with_cleanup
(struct registry_data_registry *registry,
registry_data_callback save,
registry_data_callback free);
/* A type-safe registry key.
void registry_alloc_data (struct registry_data_registry *registry,
struct registry_fields *registry_fields);
The registry itself holds just a "void *". This is not always
convenient to manage, so this template class can be used instead,
to provide a type-safe interface, that also helps manage the
lifetime of the stored objects.
/* Cast FUNC and CONTAINER to the real types, and call FUNC, also
passing DATA. */
typedef void (*registry_callback_adaptor) (registry_data_callback func,
struct registry_container *container,
void *data);
When the container is destroyed, this key arranges to destroy the
underlying data using Deleter. This defaults to
std::default_delete. */
void registry_clear_data (struct registry_data_registry *data_registry,
registry_callback_adaptor adaptor,
struct registry_container *container,
struct registry_fields *fields);
template<typename DATA, typename Deleter = std::default_delete<DATA>>
class key
{
public:
void registry_container_free_data (struct registry_data_registry *data_registry,
registry_callback_adaptor adaptor,
struct registry_container *container,
struct registry_fields *fields);
key ()
: m_key (registry<T>::new_key (cleanup))
{
}
void registry_set_data (struct registry_fields *fields,
const struct registry_data *data,
void *value);
DISABLE_COPY_AND_ASSIGN (key);
void *registry_data (struct registry_fields *fields,
const struct registry_data *data);
/* Fetch the data attached to OBJ that is associated with this key.
If no such data has been attached, nullptr is returned. */
DATA *get (T *obj) const
{
registry<T> *reg_obj = registry_accessor<T>::get (obj);
return (DATA *) reg_obj->get (m_key);
}
/* Define a new registry implementation. */
/* Attach DATA to OBJ, associated with this key. Note that any
previous data is simply dropped -- if destruction is needed,
'clear' should be called. */
void set (T *obj, DATA *data) const
{
registry<T> *reg_obj = registry_accessor<T>::get (obj);
reg_obj->set (m_key, data);
}
#define DEFINE_REGISTRY(TAG, ACCESS) \
static struct registry_data_registry TAG ## _data_registry = { NULL, 0 }; \
\
const struct TAG ## _data * \
register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \
void (*free) (struct TAG *, void *)) \
{ \
return (struct TAG ## _data *) \
register_data_with_cleanup (&TAG ## _data_registry, \
(registry_data_callback) save, \
(registry_data_callback) free); \
} \
\
const struct TAG ## _data * \
register_ ## TAG ## _data (void) \
{ \
return register_ ## TAG ## _data_with_cleanup (NULL, NULL); \
} \
\
static void \
TAG ## _alloc_data (struct TAG *container) \
{ \
struct registry_fields *rdata = &ACCESS (container)->registry_data; \
\
registry_alloc_data (&TAG ## _data_registry, rdata); \
} \
\
static void \
TAG ## registry_callback_adaptor (registry_data_callback func, \
struct registry_container *container, \
void *data) \
{ \
struct TAG *tagged_container = (struct TAG *) container; \
\
registry_ ## TAG ## _callback tagged_func \
= (registry_ ## TAG ## _callback) func; \
\
tagged_func (tagged_container, data); \
} \
\
void \
clear_ ## TAG ## _data (struct TAG *container) \
{ \
struct registry_fields *rdata = &ACCESS (container)->registry_data; \
\
registry_clear_data (&TAG ## _data_registry, \
TAG ## registry_callback_adaptor, \
(struct registry_container *) container, \
rdata); \
} \
\
static void \
TAG ## _free_data (struct TAG *container) \
{ \
struct registry_fields *rdata = &ACCESS (container)->registry_data; \
\
registry_container_free_data (&TAG ## _data_registry, \
TAG ## registry_callback_adaptor, \
(struct registry_container *) container, \
rdata); \
} \
\
void \
set_ ## TAG ## _data (struct TAG *container, \
const struct TAG ## _data *data, \
void *value) \
{ \
struct registry_fields *rdata = &ACCESS (container)->registry_data; \
\
registry_set_data (rdata, \
(struct registry_data *) data, \
value); \
} \
\
void * \
TAG ## _data (struct TAG *container, const struct TAG ## _data *data) \
{ \
struct registry_fields *rdata = &ACCESS (container)->registry_data; \
\
return registry_data (rdata, \
(struct registry_data *) data); \
}
/* If this key uses the default deleter, then this method is
available. It emplaces a new instance of the associated data
type and attaches it to OBJ using this key. The arguments, if
any, are forwarded to the constructor. */
template<typename Dummy = DATA *, typename... Args>
typename std::enable_if<std::is_same<Deleter,
std::default_delete<DATA>>::value,
Dummy>::type
emplace (T *obj, Args &&...args) const
{
DATA *result = new DATA (std::forward<Args> (args)...);
set (obj, result);
return result;
}
/* Clear the data attached to OBJ that is associated with this KEY.
Any existing data is destroyed using the deleter, and the data is
reset to nullptr. */
void clear (T *obj) const
{
DATA *datum = get (obj);
if (datum != nullptr)
{
cleanup (datum);
set (obj, nullptr);
}
}
/* External declarations for the registry functions. */
private:
#define DECLARE_REGISTRY(TAG) \
struct TAG ## _data; \
typedef void (*registry_ ## TAG ## _callback) (struct TAG *, void *); \
extern const struct TAG ## _data *register_ ## TAG ## _data (void); \
extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \
(registry_ ## TAG ## _callback save, registry_ ## TAG ## _callback free); \
extern void clear_ ## TAG ## _data (struct TAG *); \
extern void set_ ## TAG ## _data (struct TAG *, \
const struct TAG ## _data *data, \
void *value); \
extern void *TAG ## _data (struct TAG *, \
const struct TAG ## _data *data); \
\
template<typename DATA, typename Deleter = std::default_delete<DATA>> \
class TAG ## _key \
{ \
public: \
\
TAG ## _key () \
: m_key (register_ ## TAG ## _data_with_cleanup (nullptr, \
cleanup)) \
{ \
} \
\
DATA *get (struct TAG *obj) const \
{ \
return (DATA *) TAG ## _data (obj, m_key); \
} \
\
void set (struct TAG *obj, DATA *data) const \
{ \
set_ ## TAG ## _data (obj, m_key, data); \
} \
\
template<typename Dummy = DATA *, typename... Args> \
typename std::enable_if<std::is_same<Deleter, \
std::default_delete<DATA>>::value, \
Dummy>::type \
emplace (struct TAG *obj, Args &&...args) const \
{ \
DATA *result = new DATA (std::forward<Args> (args)...); \
set (obj, result); \
return result; \
} \
\
void clear (struct TAG *obj) const \
{ \
DATA *datum = get (obj); \
if (datum != nullptr) \
{ \
cleanup (obj, datum); \
set (obj, nullptr); \
} \
} \
\
private: \
\
static void cleanup (struct TAG *obj, void *arg) \
{ \
DATA *datum = (DATA *) arg; \
Deleter d; \
d (datum); \
} \
\
const struct TAG ## _data *m_key; \
/* A helper function that is called by the registry to delete the
contained object. */
static void cleanup (void *arg)
{
DATA *datum = (DATA *) arg;
Deleter d;
d (datum);
}
/* The underlying key. */
const typename registry<T>::registry_data *m_key;
};
/* Clear all the data associated with this container. This is
dangerous and should not normally be done. */
void clear_registry ()
{
/* Call all the free functions. */
for (const auto &datum : get_registrations ())
{
void *elt = m_fields[datum->index];
if (elt != nullptr)
{
datum->free (elt);
m_fields[datum->index] = nullptr;
}
}
}
private:
/* Registry callbacks have this type. */
typedef void (*registry_data_callback) (void *);
/* The type of a key. */
struct registry_data
{
unsigned index;
registry_data_callback free;
};
/* Get a new key for this particular registry. FREE is a callback.
When the container object is destroyed, all FREE functions are
called. The data associated with the container object is passed
to the callback. */
static const registry_data *new_key (registry_data_callback free)
{
std::unique_ptr<registry_data> result (new registry_data);
std::vector<std::unique_ptr<registry_data>> &registrations
= get_registrations ();
result->index = registrations.size ();
result->free = free;
registrations.emplace_back (std::move (result));
return registrations.back ().get ();
}
/* Set the datum associated with KEY in this container. */
void set (const registry_data *key, void *datum)
{
m_fields[key->index] = datum;
}
/* Fetch the datum associated with KEY in this container. If 'set'
has not been called for this key, nullptr is returned. */
void *get (const registry_data *key)
{
return m_fields[key->index];
}
/* The data stored in this instance. */
std::vector<void *> m_fields;
/* Return a reference to the vector of all the registrations that
have been made. We do separate allocations here so that the
addresses are stable and can be used as keys. */
static std::vector<std::unique_ptr<registry_data>> &get_registrations ()
{
static std::vector<std::unique_ptr<registry_data>> registrations;
return registrations;
}
};
#endif /* REGISTRY_H */

View File

@ -178,7 +178,7 @@ private:
static struct gdbsim_target gdbsim_ops;
static inferior_key<sim_inferior_data> sim_inferior_data_key;
static const registry<inferior>::key<sim_inferior_data> sim_inferior_data_key;
/* Flag indicating the "open" status of this module. It's set to 1
in gdbsim_open() and 0 in gdbsim_close(). */

View File

@ -1033,7 +1033,7 @@ is_remote_target (process_stratum_target *target)
}
/* Per-program-space data key. */
static const struct program_space_key<char, gdb::xfree_deleter<char>>
static const registry<program_space>::key<char, gdb::xfree_deleter<char>>
remote_pspace_data;
/* The variable registered as the control variable used by the

View File

@ -155,7 +155,7 @@ static const char *powerpc_vector_abi_string = "auto";
/* PowerPC-related per-inferior data. */
static inferior_key<ppc_inferior_data> ppc_inferior_data_key;
static registry<inferior>::key<ppc_inferior_data> ppc_inferior_data_key;
/* Get the per-inferior PowerPC data for INF. */

View File

@ -80,7 +80,8 @@ struct solib_aix_inferior_data
};
/* Key to our per-inferior data. */
static inferior_key<solib_aix_inferior_data> solib_aix_inferior_data_handle;
static const registry<inferior>::key<solib_aix_inferior_data>
solib_aix_inferior_data_handle;
/* Return this module's data for the given inferior.
If none is found, add a zero'ed one now. */

View File

@ -80,7 +80,8 @@ struct darwin_info
};
/* Per-program-space data key. */
static program_space_key<darwin_info> solib_darwin_pspace_data;
static const registry<program_space>::key<darwin_info>
solib_darwin_pspace_data;
/* Get the current darwin data. If none is found yet, add it now. This
function always returns a valid object. */

View File

@ -164,7 +164,7 @@ struct dsbt_info
};
/* Per-program-space data key. */
static program_space_key<dsbt_info> solib_dsbt_pspace_data;
static const registry<program_space>::key<dsbt_info> solib_dsbt_pspace_data;
/* Get the current dsbt data. If none is found yet, add it now. This
function always returns a valid object. */

View File

@ -365,7 +365,7 @@ struct svr4_info
};
/* Per-program-space data key. */
static const struct program_space_key<svr4_info> solib_svr4_pspace_data;
static const registry<program_space>::key<svr4_info> solib_svr4_pspace_data;
/* Free the probes table. */

View File

@ -529,7 +529,8 @@ typedef std::unordered_map<std::string, std::string> soname_build_id_map;
/* Key used to associate a soname_build_id_map to a core file bfd. */
static const struct bfd_key<soname_build_id_map> cbfd_soname_build_id_data_key;
static const struct registry<bfd>::key<soname_build_id_map>
cbfd_soname_build_id_data_key;
/* See solib.h. */

View File

@ -115,7 +115,8 @@ private:
int m_line = 0;
};
static program_space_key<current_source_location> current_source_key;
static const registry<program_space>::key<current_source_location>
current_source_key;
/* Default number of lines to print with commands like "list".
This is based on guessing how many long (i.e. more than chars_per_line

View File

@ -2016,8 +2016,8 @@ again:
/* RS/6000 xlc/dbx combination uses a set of builtin types, starting from -1.
Return the proper type node for a given builtin type number. */
static const struct objfile_key<struct type *,
gdb::noop_deleter<struct type *>>
static const registry<objfile>::key<struct type *,
gdb::noop_deleter<struct type *>>
rs6000_builtin_type_data;
static struct type *

View File

@ -47,7 +47,7 @@ struct debug_sym_fns_data
/* We need to record a pointer to the real set of functions for each
objfile. */
static const struct objfile_key<debug_sym_fns_data>
static const registry<objfile>::key<debug_sym_fns_data>
symfile_debug_objfile_data_key;
/* If true all calls to the symfile functions are logged. */

View File

@ -2500,7 +2500,7 @@ reread_symbols (int from_tty)
(*objfile->sf->sym_finish) (objfile);
}
clear_objfile_data (objfile);
objfile->registry_fields.clear_registry ();
/* Clean up any state BFD has sitting around. */
{
@ -2638,7 +2638,7 @@ reread_symbols (int from_tty)
{
clear_symtab_users (0);
/* clear_objfile_data for each objfile was called before freeing it and
/* The registry for each objfile was cleared and
gdb::observers::new_objfile.notify (NULL) has been called by
clear_symtab_users above. Notify the new files now. */
for (auto iter : new_objfiles)

View File

@ -121,7 +121,7 @@ struct main_info
/* Program space key for finding name and language of "main". */
static const program_space_key<main_info> main_progspace_key;
static const registry<program_space>::key<main_info> main_progspace_key;
/* The default symbol cache size.
There is no extra cpu cost for large N (except when flushing the cache,
@ -251,7 +251,7 @@ struct symbol_cache
/* Program space key for finding its symbol cache. */
static const program_space_key<symbol_cache> symbol_cache_key;
static const registry<program_space>::key<symbol_cache> symbol_cache_key;
/* When non-zero, print debugging messages related to symtab creation. */
unsigned int symtab_create_debug = 0;

View File

@ -24,7 +24,7 @@
/* The target dcache is kept per-address-space. This key lets us
associate the cache with the address space. */
static const struct address_space_key<DCACHE, dcache_deleter>
static const registry<address_space>::key<DCACHE, dcache_deleter>
target_dcache_aspace_key;
/* Target dcache is initialized or not. */

View File

@ -147,7 +147,7 @@ struct xcoff_symfile_info
/* Key for XCOFF-associated data. */
static const struct objfile_key<xcoff_symfile_info> xcoff_objfile_data_key;
static const registry<objfile>::key<xcoff_symfile_info> xcoff_objfile_data_key;
/* Convenience macro to access the per-objfile XCOFF data. */