regcache.c \
regcache-dump.c \
reggroups.c \
- registry.c \
remote.c \
remote-fileio.c \
remote-notif.c \
};
/* 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).
};
/* 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.
};
/* 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
};
/* 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
};
/* 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;
};
/* 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)
};
/* 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. */
};
/* 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. */
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 *
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. */
/* 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) \
#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
{
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. */
{
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,
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;
/* 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. */
\f
/* 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;
\f
/* Pointer encoding helper functions. */
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.
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. */
/* 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
/* 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. */
};
/* 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 *
/* 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)
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. */
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);
htab_clear_slot (gdb_bfd_cache, slot);
}
- bfd_free_data (abfd);
delete gdata;
bfd_set_usrdata (abfd, NULL); /* Paranoia. */
#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. */
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. */
/* 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 *
#include "extension-priv.h"
#include "symtab.h"
#include "libguile.h"
+#include "objfiles.h"
struct block;
struct frame_info;
#undef GDB_SMOB_HEAD
struct objfile;
-struct objfile_data;
/* A predicate that returns non-zero if an object is a particular kind
of gsmob. */
/* 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;
\f
/* Administrivia for block smobs. */
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;
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);
- }
-}
\f
/* Block methods. */
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);
-}
/* 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;
\f
/* Administrivia for frame smobs. */
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;
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);
- }
-}
\f
/* Frame methods. */
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);
-}
/* 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. */
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
{
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 ();
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);
}
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);
-}
/* 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. */
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
{
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 ();
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);
}
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);
-}
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
{
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
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);
- }
-}
\f
/* Symbol methods. */
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);
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;
\f
/* Administrivia for symtab smobs. */
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;
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);
- }
-}
\f
/* Symbol table methods. */
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);
-}
/* 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;
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;
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);
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);
- }
-}
\f
/* Administrivia for field smobs. */
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);
-}
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
#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;
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 ());
}
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. */
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
}
/* 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 ()
{
};
/* 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. */
/* 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 *
/* 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>
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 *
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
#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. */
};
/* 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 ()
/* 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 ()
{
gdb_obstack.h specifies the alloc/dealloc functions. */
obstack_init (&objfile_obstack);
- objfile_alloc_data (this);
-
std::string name_holder;
if (name == NULL)
{
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
/* 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
|| 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
\f
-/* 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)
-
-\f
-
/* 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
return new address_space ();
}
-address_space::~address_space ()
-{
- address_space_free_data (this);
-}
-
/* Start counting over from scratch. */
static void
: num (++last_program_space_num),
aspace (aspace_)
{
- program_space_alloc_data (this);
-
program_spaces.push_back (this);
}
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. */
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;
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
{
/* 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. */
}
/* Per aspace data-pointers required by other GDB modules. */
- REGISTRY_FIELDS {};
+ registry<address_space> registry_fields;
private:
int m_num;
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
} \
} 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)
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;
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;
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)
{
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) \
{
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);
/* 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. */
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. */
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)
{
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) \
\f
-/* 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
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
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)
{
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) \
\f
-/* 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
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
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 ();
}
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)
{
} \
} 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)
{
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;
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;
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)
{
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. */
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. */
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;
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;
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;
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;
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)
{
\f
-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)
{
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;
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;
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)
{
+++ /dev/null
-/* 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 = ®istry->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];
-}
#include <type_traits>
-/* The macros here implement a template type and functions for
- associating some user data with a container object.
-
- 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.
-
- 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.
-
- 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.
-*/
-
-/* This structure is used in a container to hold the data that the
- registry uses. */
-
-struct registry_fields
-{
- void **data;
- unsigned num_data;
-};
+template<typename T> class registry;
-/* This macro is used in a container struct definition to define the
- fields used by the registry code. */
+/* An accessor class that is used by registry_key.
-#define REGISTRY_FIELDS \
- struct registry_fields registry_data
+ 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.
-/* 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. */
+ However, a container may sometimes need to store the registry
+ elsewhere. In this case, registry_accessor can be specialized to
+ perform the needed indirection. */
-#define REGISTRY_ACCESS_FIELD(CONTAINER) \
- (CONTAINER)
+template<typename T>
+struct registry_accessor
+{
+ /* Given a container of type T, return its registry. */
+ static registry<T> *get (T *obj)
+ {
+ return &obj->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;
+/* 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).
-/* Registry callbacks have this type. */
-typedef void (*registry_data_callback) (struct registry_container *, void *);
+ This is handled using the registry system.
-struct registry_data
-{
- unsigned index;
- registry_data_callback save;
- registry_data_callback free;
-};
+ A class needing to allow this sort registration can add a registry
+ field. For example, you would write:
-struct registry_data_registration
-{
- struct registry_data *data;
- struct registry_data_registration *next;
-};
+ class some_container { registry<some_container> registry_fields; };
-struct registry_data_registry
-{
- struct registry_data_registration *registrations;
- unsigned num_registrations;
-};
+ The name of the field matters by default, see registry_accessor.
+
+ 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. */
-/* Registry backend functions. Client code uses the frontend
- functions defined by DEFINE_REGISTRY below instead. */
-
-const struct registry_data *register_data_with_cleanup
- (struct registry_data_registry *registry,
- registry_data_callback save,
- registry_data_callback free);
-
-void registry_alloc_data (struct registry_data_registry *registry,
- struct registry_fields *registry_fields);
-
-/* 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);
-
-void registry_clear_data (struct registry_data_registry *data_registry,
- registry_callback_adaptor adaptor,
- struct registry_container *container,
- struct registry_fields *fields);
-
-void registry_container_free_data (struct registry_data_registry *data_registry,
- registry_callback_adaptor adaptor,
- struct registry_container *container,
- struct registry_fields *fields);
-
-void registry_set_data (struct registry_fields *fields,
- const struct registry_data *data,
- void *value);
-
-void *registry_data (struct registry_fields *fields,
- const struct registry_data *data);
-
-/* Define a new registry implementation. */
-
-#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); \
-}
-
-
-/* External declarations for the registry functions. */
-
-#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; \
+template<typename T>
+class registry
+{
+public:
+
+ registry ()
+ : m_fields (get_registrations ().size ())
+ {
+ }
+
+ ~registry ()
+ {
+ clear_registry ();
+ }
+
+ DISABLE_COPY_AND_ASSIGN (registry);
+
+ /* A type-safe registry key.
+
+ 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.
+
+ When the container is destroyed, this key arranges to destroy the
+ underlying data using Deleter. This defaults to
+ std::default_delete. */
+
+ template<typename DATA, typename Deleter = std::default_delete<DATA>>
+ class key
+ {
+ public:
+
+ key ()
+ : m_key (registry<T>::new_key (cleanup))
+ {
+ }
+
+ DISABLE_COPY_AND_ASSIGN (key);
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+ }
+
+ private:
+
+ /* 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>> ®istrations
+ = 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 */
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(). */
}
/* 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
/* 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. */
};
/* 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. */
};
/* 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. */
};
/* 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. */
};
/* 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. */
/* 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. */
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
/* 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 *
/* 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. */
(*objfile->sf->sym_finish) (objfile);
}
- clear_objfile_data (objfile);
+ objfile->registry_fields.clear_registry ();
/* Clean up any state BFD has sitting around. */
{
{
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)
/* 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,
/* 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;
/* 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. */
/* 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. */