From: Lancelot SIX via Gdb-patches <gdb-patches@sourceware.org>
To: Tom Tromey <tom@tromey.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH 4/6] Rewrite registry.h
Date: Tue, 7 Jun 2022 10:55:32 +0000 [thread overview]
Message-ID: <20220607105532.tymzjyvngpdy6l6s@ubuntu.lan> (raw)
In-Reply-To: <20220530175934.3872892-5-tom@tromey.com>
Hi Tom,
After this patch, if I build GDB with address sanitizer, I end up having
many regressions related to heap-use-after-free in the testsuite.
You can see this by using the gdb.base/cached-source-file.exp for
example.
==901008==ERROR: AddressSanitizer: heap-use-after-free on address 0x61a000080f88 at pc 0x56310c94a9b1 bp 0x7ffc6ec5de70 sp 0x7ffc6ec5de60
READ of size 1 at 0x61a000080f88 thread T0
#0 0x56310c94a9b0 in gdb::optional<std::queue<dwarf2_queue_item, std::__debug::deque<dwarf2_queue_item, std::allocator<dwarf2_queue_item> > > >::has_value() const ../../gdb/../gdbsupport/gdb_optional.h:183
#1 0x56310c88b638 in dwarf2_per_objfile::remove_all_cus() ../../gdb/dwarf2/read.c:1479
#2 0x56310c91db2f in dwarf2_per_objfile::~dwarf2_per_objfile() ../../gdb/dwarf2/read.c:23606
#3 0x56310c989241 in std::default_delete<dwarf2_per_objfile>::operator()(dwarf2_per_objfile*) const /usr/include/c++/9/bits/unique_ptr.h:81
#4 0x56310c962fc2 in registry<objfile>::key<dwarf2_per_objfile, std::default_delete<dwarf2_per_objfile> >::cleanup(void*) ../../gdb/registry.h:158
#5 0x56310cf60fa3 in registry<objfile>::clear_registry() ../../gdb/registry.h:175
#6 0x56310cf5f833 in registry<objfile>::~registry() ../../gdb/registry.h:77
#7 0x56310cf56499 in objfile::~objfile() ../../gdb/objfiles.c:501
#8 0x56310cf6ae22 in std::_Sp_counted_ptr<objfile*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/9/bits/shared_ptr_base.h:377
#9 0x56310c3c17cc in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/9/bits/shared_ptr_base.h:155
#10 0x56310c3b3f5b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/9/bits/shared_ptr_base.h:730
#11 0x56310cf5ed9f in std::__shared_ptr<objfile, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/9/bits/shared_ptr_base.h:1169
#12 0x56310cf5edbf in std::shared_ptr<objfile>::~shared_ptr() /usr/include/c++/9/bits/shared_ptr.h:103
#13 0x56310d00c0c9 in void __gnu_cxx::new_allocator<std::__cxx1998::_List_node<std::shared_ptr<objfile> > >::destroy<std::shared_ptr<objfile> >(std::shared_ptr<objfile>*) /usr/include/c++/9/ext/new_allocator.h:152
#14 0x56310d0084ee in void std::allocator_traits<std::allocator<std::__cxx1998::_List_node<std::shared_ptr<objfile> > > >::destroy<std::shared_ptr<objfile> >(std::allocator<std::__cxx1998::_List_node<std::shared_ptr<objfile> > >&, std::shared_ptr<objfile>*) /usr/include/c++/9/bits/alloc_traits.h:496
#15 0x56310d00e85d in std::__cxx1998::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase(std::__cxx1998::_List_iterator<std::shared_ptr<objfile> >) /usr/include/c++/9/bits/stl_list.h:1921
#16 0x56310d00a468 in std::__cxx1998::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase(std::__cxx1998::_List_const_iterator<std::shared_ptr<objfile> >) /usr/include/c++/9/bits/list.tcc:158
#17 0x56310d005ad7 in std::__debug::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase(std::__cxx1998::_List_const_iterator<std::shared_ptr<objfile> >) /usr/include/c++/9/debug/list:499
#18 0x56310d001dda in std::__debug::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase(__gnu_debug::_Safe_iterator<std::__cxx1998::_List_const_iterator<std::shared_ptr<objfile> >, std::__debug::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >, std::bidirectional_iterator_tag>) /usr/include/c++/9/debug/list:511
#19 0x56310cffb808 in program_space::remove_objfile(objfile*) ../../gdb/progspace.c:175
#20 0x56310cf55cd3 in objfile::unlink() ../../gdb/objfiles.c:480
[...]
0x61a000080f88 is located 1288 bytes inside of 1304-byte region [0x61a000080a80,0x61a000080f98)
freed by thread T0 here:
#0 0x7f937d886c65 in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:177
#1 0x56310c98928a in std::default_delete<dwarf2_per_bfd>::operator()(dwarf2_per_bfd*) const /usr/include/c++/9/bits/unique_ptr.h:81
#2 0x56310c9630cb in registry<bfd>::key<dwarf2_per_bfd, std::default_delete<dwarf2_per_bfd> >::cleanup(void*) ../../gdb/registry.h:158
#3 0x56310cafb85f in registry<bfd>::clear_registry() (/home/lancesix/src/worktrees/gdb/upstream-master/_build/gdb/gdb+0x1c2985f)
#4 0x56310cafb175 in registry<bfd>::~registry() (/home/lancesix/src/worktrees/gdb/upstream-master/_build/gdb/gdb+0x1c29175)
#5 0x56310cafadc1 in gdb_bfd_data::~gdb_bfd_data() ../../gdb/gdb_bfd.c:76
#6 0x56310caf80ff in gdb_bfd_unref(bfd*) ../../gdb/gdb_bfd.c:729
#7 0x56310cf5615d in objfile::~objfile() ../../gdb/objfiles.c:562
#8 0x56310cf6ae22 in std::_Sp_counted_ptr<objfile*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/9/bits/shared_ptr_base.h:377
#9 0x56310c3c17cc in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/9/bits/shared_ptr_base.h:155
#10 0x56310c3b3f5b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/9/bits/shared_ptr_base.h:730
#11 0x56310cf5ed9f in std::__shared_ptr<objfile, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/9/bits/shared_ptr_base.h:1169
#12 0x56310cf5edbf in std::shared_ptr<objfile>::~shared_ptr() /usr/include/c++/9/bits/shared_ptr.h:103
#13 0x56310d00c0c9 in void __gnu_cxx::new_allocator<std::__cxx1998::_List_node<std::shared_ptr<objfile> > >::destroy<std::shared_ptr<objfile> >(std::shared_ptr<objfile>*) /usr/include/c++/9/ext/new_allocator.h:152
#14 0x56310d0084ee in void std::allocator_traits<std::allocator<std::__cxx1998::_List_node<std::shared_ptr<objfile> > > >::destroy<std::shared_ptr<objfile> >(std::allocator<std::__cxx1998::_List_node<std::shared_ptr<objfile> > >&, std::shared_ptr<objfile>*) /usr/include/c++/9/bits/alloc_traits.h:496
#15 0x56310d00e85d in std::__cxx1998::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase(std::__cxx1998::_List_iterator<std::shared_ptr<objfile> >) /usr/include/c++/9/bits/stl_list.h:1921
#16 0x56310d00a468 in std::__cxx1998::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase(std::__cxx1998::_List_const_iterator<std::shared_ptr<objfile> >) /usr/include/c++/9/bits/list.tcc:158
#17 0x56310d005ad7 in std::__debug::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase(std::__cxx1998::_List_const_iterator<std::shared_ptr<objfile> >) /usr/include/c++/9/debug/list:499
#18 0x56310d001dda in std::__debug::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase(__gnu_debug::_Safe_iterator<std::__cxx1998::_List_const_iterator<std::shared_ptr<objfile> >, std::__debug::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >, std::bidirectional_iterator_tag>) /usr/include/c++/9/debug/list:511
#19 0x56310cffb808 in program_space::remove_objfile(objfile*) ../../gdb/progspace.c:175
#20 0x56310cf55cd3 in objfile::unlink() ../../gdb/objfiles.c:480
[...]
previously allocated by thread T0 here:
#0 0x7f937d885587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
#1 0x56310c88bfff in dwarf2_has_info(objfile*, dwarf2_debug_sections const*, bool) ../../gdb/dwarf2/read.c:1579
#2 0x56310ca3ab84 in elf_symfile_read ../../gdb/elfread.c:1255
#3 0x56310d38538d in read_symbols ../../gdb/symfile.c:772
[...]
I have not really looked into things much, but looks like the order in
which things are destructed/deallocated changed slightly, leading to
this issue.
Best,
Lancelot
On Mon, May 30, 2022 at 11:59:32AM -0600, Tom Tromey wrote:
> 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.
> ---
> gdb/Makefile.in | 1 -
> gdb/ada-lang.c | 5 +-
> gdb/ada-tasks.c | 4 +-
> gdb/arm-tdep.c | 4 +-
> gdb/auto-load.c | 4 +-
> gdb/auxv.c | 2 +-
> gdb/break-catch-syscall.c | 2 +-
> gdb/breakpoint.c | 2 +-
> gdb/coffread.c | 2 +-
> gdb/ctfread.c | 8 +-
> gdb/dbxread.c | 2 +-
> gdb/dwarf2/frame.c | 4 +-
> gdb/dwarf2/read.c | 8 +-
> gdb/elfread.c | 4 +-
> gdb/fbsd-tdep.c | 2 +-
> gdb/gdb-stabs.h | 2 +-
> gdb/gdb_bfd.c | 14 +-
> gdb/gdb_bfd.h | 10 +-
> gdb/gdbtypes.c | 6 +-
> gdb/guile/guile-internal.h | 2 +-
> gdb/guile/scm-block.c | 75 +++---
> gdb/guile/scm-frame.c | 75 +++---
> gdb/guile/scm-objfile.c | 46 ++--
> gdb/guile/scm-progspace.c | 47 ++--
> gdb/guile/scm-symbol.c | 70 +++---
> gdb/guile/scm-symtab.c | 76 +++---
> gdb/guile/scm-type.c | 63 +++--
> gdb/hppa-tdep.c | 3 +-
> gdb/inferior.c | 11 +-
> gdb/inferior.h | 7 +-
> gdb/inflow.c | 2 +-
> gdb/linux-tdep.c | 2 +-
> gdb/mdebugread.c | 4 +-
> gdb/minidebug.c | 2 +-
> gdb/nto-tdep.c | 2 +-
> gdb/objc-lang.c | 2 +-
> gdb/objfiles.c | 15 +-
> gdb/objfiles.h | 6 +-
> gdb/progspace.c | 22 --
> gdb/progspace.h | 18 +-
> gdb/python/py-block.c | 70 +++---
> gdb/python/py-inferior.c | 68 +++---
> gdb/python/py-objfile.c | 37 ++-
> gdb/python/py-progspace.c | 59 ++---
> gdb/python/py-symbol.c | 63 ++---
> gdb/python/py-symtab.c | 142 +++++------
> gdb/python/py-type.c | 59 ++---
> gdb/registry.c | 112 ---------
> gdb/registry.h | 469 ++++++++++++++++---------------------
> gdb/remote-sim.c | 2 +-
> gdb/remote.c | 2 +-
> gdb/rs6000-tdep.c | 2 +-
> gdb/solib-aix.c | 3 +-
> gdb/solib-darwin.c | 3 +-
> gdb/solib-dsbt.c | 2 +-
> gdb/solib-svr4.c | 2 +-
> gdb/solib.c | 3 +-
> gdb/source.c | 3 +-
> gdb/stabsread.c | 4 +-
> gdb/symfile-debug.c | 2 +-
> gdb/symfile.c | 4 +-
> gdb/symtab.c | 4 +-
> gdb/target-dcache.c | 2 +-
> gdb/xcoffread.c | 2 +-
> 64 files changed, 684 insertions(+), 1071 deletions(-)
> delete mode 100644 gdb/registry.c
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index d80087749de..94e8da1dbbd 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -1149,7 +1149,6 @@ COMMON_SFILES = \
> regcache.c \
> regcache-dump.c \
> reggroups.c \
> - registry.c \
> remote.c \
> remote-fileio.c \
> remote-notif.c \
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 6ab01fd27d4..77616476617 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -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.
> diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
> index 0043f2999d9..fda49557a4f 100644
> --- a/gdb/ada-tasks.c
> +++ b/gdb/ada-tasks.c
> @@ -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
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 49664093f00..dbcf4d286ab 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -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;
> @@ -2368,7 +2368,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)
> diff --git a/gdb/auto-load.c b/gdb/auto-load.c
> index b6056f5d60a..54ed73d1bf3 100644
> --- a/gdb/auto-load.c
> +++ b/gdb/auto-load.c
> @@ -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. */
> diff --git a/gdb/auxv.c b/gdb/auxv.c
> index 8e175138f5d..6154988f6dd 100644
> --- a/gdb/auxv.c
> +++ b/gdb/auxv.c
> @@ -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. */
>
> diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
> index 06d48466de7..805bb86cee6 100644
> --- a/gdb/break-catch-syscall.c
> +++ b/gdb/break-catch-syscall.c
> @@ -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 *
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index ed932a19ed7..8bc7cef9f86 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -3326,7 +3326,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. */
> diff --git a/gdb/coffread.c b/gdb/coffread.c
> index 75cf646c980..47828ac6090 100644
> --- a/gdb/coffread.c
> +++ b/gdb/coffread.c
> @@ -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) \
> diff --git a/gdb/ctfread.c b/gdb/ctfread.c
> index 828f300d29d..0da4f0d0720 100644
> --- a/gdb/ctfread.c
> +++ b/gdb/ctfread.c
> @@ -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;
>
> diff --git a/gdb/dbxread.c b/gdb/dbxread.c
> index bcf519000bc..e1bf9a01e30 100644
> --- a/gdb/dbxread.c
> +++ b/gdb/dbxread.c
> @@ -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. */
> diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
> index 5878d72f922..d7a06395acb 100644
> --- a/gdb/dwarf2/frame.c
> +++ b/gdb/dwarf2/frame.c
> @@ -1370,12 +1370,12 @@ dwarf2_frame_cfa (struct frame_info *this_frame)
> \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. */
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index c4578c687d2..470e92a6c48 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -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. */
>
> diff --git a/gdb/elfread.c b/gdb/elfread.c
> index 32cb27c8967..ec0deb5fd93 100644
> --- a/gdb/elfread.c
> +++ b/gdb/elfread.c
> @@ -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. */
> diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
> index b241e855bd6..f2f961b5486 100644
> --- a/gdb/fbsd-tdep.c
> +++ b/gdb/fbsd-tdep.c
> @@ -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 *
> diff --git a/gdb/gdb-stabs.h b/gdb/gdb-stabs.h
> index fef988524f2..5c697906cab 100644
> --- a/gdb/gdb-stabs.h
> +++ b/gdb/gdb-stabs.h
> @@ -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)
> diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
> index 22828482d5b..6c03ae5ef05 100644
> --- a/gdb/gdb_bfd.c
> +++ b/gdb/gdb_bfd.c
> @@ -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. */
>
> diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
> index 6845d6ccef5..edd38f5c34d 100644
> --- a/gdb/gdb_bfd.h
> +++ b/gdb/gdb_bfd.h
> @@ -26,7 +26,15 @@
> #include "gdbsupport/iterator-range.h"
> #include "gdbsupport/next-iterator.h"
>
> -DECLARE_REGISTRY (bfd);
> +struct gdb_bfd_data;
> +
> +/* 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. */
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 9f49c15862f..6a732fe3586 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -6081,7 +6081,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. */
> @@ -6308,8 +6308,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 *
> diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
> index 4cdb7e355d7..30cc5c307ae 100644
> --- a/gdb/guile/guile-internal.h
> +++ b/gdb/guile/guile-internal.h
> @@ -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. */
> diff --git a/gdb/guile/scm-block.c b/gdb/guile/scm-block.c
> index 41954c70519..a29c2db58f1 100644
> --- a/gdb/guile/scm-block.c
> +++ b/gdb/guile/scm-block.c
> @@ -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;
> \f
> /* 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);
> - }
> -}
> \f
> /* 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);
> -}
> diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c
> index 6bbb6f81d68..4132bb246d8 100644
> --- a/gdb/guile/scm-frame.c
> +++ b/gdb/guile/scm-frame.c
> @@ -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;
> \f
> /* 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);
> - }
> -}
> \f
> /* 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);
> -}
> diff --git a/gdb/guile/scm-objfile.c b/gdb/guile/scm-objfile.c
> index 760d5aa1f4b..1a87dcf74fa 100644
> --- a/gdb/guile/scm-objfile.c
> +++ b/gdb/guile/scm-objfile.c
> @@ -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);
> -}
> diff --git a/gdb/guile/scm-progspace.c b/gdb/guile/scm-progspace.c
> index c48da761945..7a197d76543 100644
> --- a/gdb/guile/scm-progspace.c
> +++ b/gdb/guile/scm-progspace.c
> @@ -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);
> -}
> diff --git a/gdb/guile/scm-symbol.c b/gdb/guile/scm-symbol.c
> index 55eac3cfff6..0b96e5a02c1 100644
> --- a/gdb/guile/scm-symbol.c
> +++ b/gdb/guile/scm-symbol.c
> @@ -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);
> - }
> -}
> \f
> /* 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);
> diff --git a/gdb/guile/scm-symtab.c b/gdb/guile/scm-symtab.c
> index 518ceeaa15d..940823147bf 100644
> --- a/gdb/guile/scm-symtab.c
> +++ b/gdb/guile/scm-symtab.c
> @@ -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;
> \f
> /* 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);
> - }
> -}
> \f
> /* 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);
> -}
> diff --git a/gdb/guile/scm-type.c b/gdb/guile/scm-type.c
> index dd7eace8d40..2dadbefb3a4 100644
> --- a/gdb/guile/scm-type.c
> +++ b/gdb/guile/scm-type.c
> @@ -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);
> - }
> -}
> \f
> /* 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);
> -}
> diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
> index f9ececbb04f..80a1c0bbd4d 100644
> --- a/gdb/hppa-tdep.c
> +++ b/gdb/hppa-tdep.c
> @@ -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
> diff --git a/gdb/inferior.c b/gdb/inferior.c
> index 606b4189181..7eb2bd97907 100644
> --- a/gdb/inferior.c
> +++ b/gdb/inferior.c
> @@ -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 ());
> }
>
> diff --git a/gdb/inferior.h b/gdb/inferior.h
> index f6e26a32feb..f6a7e7fd239 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -588,7 +588,7 @@ class inferior : public refcounted_object,
> 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. */
> @@ -608,11 +608,6 @@ class inferior : public refcounted_object,
> 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
> diff --git a/gdb/inflow.c b/gdb/inflow.c
> index 9c7e2907625..5477624bcd5 100644
> --- a/gdb/inflow.c
> +++ b/gdb/inflow.c
> @@ -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 ()
> {
> diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
> index 4e728a06e7e..714825d96c1 100644
> --- a/gdb/linux-tdep.c
> +++ b/gdb/linux-tdep.c
> @@ -235,7 +235,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. */
> diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
> index ca7c15ee63f..bf90471da63 100644
> --- a/gdb/mdebugread.c
> +++ b/gdb/mdebugread.c
> @@ -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 *
> diff --git a/gdb/minidebug.c b/gdb/minidebug.c
> index e94768ac69c..dbbdf85e08c 100644
> --- a/gdb/minidebug.c
> +++ b/gdb/minidebug.c
> @@ -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>
>
> diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
> index 9b08adfa18c..301d403eb13 100644
> --- a/gdb/nto-tdep.c
> +++ b/gdb/nto-tdep.c
> @@ -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 *
> diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
> index 37008da529a..4429d4a7d44 100644
> --- a/gdb/objc-lang.c
> +++ b/gdb/objc-lang.c
> @@ -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
> diff --git a/gdb/objfiles.c b/gdb/objfiles.c
> index 80f68fda1c1..b9a59b4d96c 100644
> --- a/gdb/objfiles.c
> +++ b/gdb/objfiles.c
> @@ -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)
> {
> @@ -565,10 +558,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
> diff --git a/gdb/objfiles.h b/gdb/objfiles.h
> index 9da12ff12e0..aee9b324b17 100644
> --- a/gdb/objfiles.h
> +++ b/gdb/objfiles.h
> @@ -682,7 +682,7 @@ struct objfile
>
> /* 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
> diff --git a/gdb/progspace.c b/gdb/progspace.c
> index 3232ea9ab01..7c801d2d960 100644
> --- a/gdb/progspace.c
> +++ b/gdb/progspace.c
> @@ -43,24 +43,11 @@ static int highest_address_space_num;
>
> \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
> @@ -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. */
> diff --git a/gdb/progspace.h b/gdb/progspace.h
> index eff157b0dd3..44836ff37aa 100644
> --- a/gdb/progspace.h
> +++ b/gdb/progspace.h
> @@ -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::shared_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
> diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
> index 872fb89ba83..b9aea3aca69 100644
> --- a/gdb/python/py-block.c
> +++ b/gdb/python/py-block.c
> @@ -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)
> {
> diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
> index ebcd5b0a70f..ac94d1322cc 100644
> --- a/gdb/python/py-inferior.c
> +++ b/gdb/python/py-inferior.c
> @@ -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) \
> @@ -207,7 +235,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);
> @@ -220,7 +248,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. */
> @@ -781,32 +809,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. */
>
> @@ -817,14 +819,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)
> {
> diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
> index 3e3270e7cd3..8954c2e5abb 100644
> --- a/gdb/python/py-objfile.c
> +++ b/gdb/python/py-objfile.c
> @@ -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) \
> @@ -656,16 +669,6 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
>
> \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
> @@ -675,7 +678,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
> @@ -686,21 +689,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)
> {
> diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
> index 5657ef7756c..64a172dcdd3 100644
> --- a/gdb/python/py-progspace.c
> +++ b/gdb/python/py-progspace.c
> @@ -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) \
> @@ -456,27 +479,6 @@ pspy_is_valid (PyObject *o, PyObject *args)
>
> \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
> @@ -485,8 +487,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
> @@ -497,7 +498,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 ();
> }
>
> @@ -521,14 +522,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)
> {
> diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
> index 02c35acd1e9..b5b8056f321 100644
> --- a/gdb/python/py-symbol.c
> +++ b/gdb/python/py-symbol.c
> @@ -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;
> @@ -597,38 +612,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)
> {
> diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
> index 7ed62716b67..03c274dfff6 100644
> --- a/gdb/python/py-symtab.c
> +++ b/gdb/python/py-symtab.c
> @@ -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)
> {
> diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
> index 6cbf5f2eb6a..068a212b77b 100644
> --- a/gdb/python/py-type.c
> +++ b/gdb/python/py-type.c
> @@ -1111,36 +1111,38 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
>
> \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)
> @@ -1151,11 +1153,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;
> @@ -1174,7 +1175,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;
> @@ -1466,14 +1467,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)
> {
> diff --git a/gdb/registry.c b/gdb/registry.c
> deleted file mode 100644
> index 2e977e2528f..00000000000
> --- a/gdb/registry.c
> +++ /dev/null
> @@ -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 = ®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];
> -}
> diff --git a/gdb/registry.h b/gdb/registry.h
> index 1475fd2ec26..27592ff6e2a 100644
> --- a/gdb/registry.h
> +++ b/gdb/registry.h
> @@ -22,288 +22,213 @@
>
> #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 derives from registry<>. 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 */
> diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
> index 4b8afd27688..01f88fc9da2 100644
> --- a/gdb/remote-sim.c
> +++ b/gdb/remote-sim.c
> @@ -178,7 +178,7 @@ struct gdbsim_target final
>
> 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(). */
> diff --git a/gdb/remote.c b/gdb/remote.c
> index f41e6ce82c2..b57c55e8580 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -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
> diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
> index 6815dfaa820..0386bfb6223 100644
> --- a/gdb/rs6000-tdep.c
> +++ b/gdb/rs6000-tdep.c
> @@ -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. */
>
> diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
> index 3a8debf2c5a..33b15a9d8ad 100644
> --- a/gdb/solib-aix.c
> +++ b/gdb/solib-aix.c
> @@ -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. */
> diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
> index d7789f68dfe..e61ec0d4bf3 100644
> --- a/gdb/solib-darwin.c
> +++ b/gdb/solib-darwin.c
> @@ -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. */
> diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
> index 0b03f944608..fe6b6e122d9 100644
> --- a/gdb/solib-dsbt.c
> +++ b/gdb/solib-dsbt.c
> @@ -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. */
> diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
> index 5c046d3fab5..f9a43e23969 100644
> --- a/gdb/solib-svr4.c
> +++ b/gdb/solib-svr4.c
> @@ -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. */
>
> diff --git a/gdb/solib.c b/gdb/solib.c
> index 0fbf5bc988d..d4a7c092da8 100644
> --- a/gdb/solib.c
> +++ b/gdb/solib.c
> @@ -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. */
>
> diff --git a/gdb/source.c b/gdb/source.c
> index 8691113c729..425b02fc3a0 100644
> --- a/gdb/source.c
> +++ b/gdb/source.c
> @@ -115,7 +115,8 @@ struct current_source_location
> 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
> diff --git a/gdb/stabsread.c b/gdb/stabsread.c
> index 4fe2110a47f..aedbca2d0eb 100644
> --- a/gdb/stabsread.c
> +++ b/gdb/stabsread.c
> @@ -2016,8 +2016,8 @@ read_type (const char **pp, struct objfile *objfile)
> /* 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 *
> diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
> index 2af04433444..59726290011 100644
> --- a/gdb/symfile-debug.c
> +++ b/gdb/symfile-debug.c
> @@ -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. */
> diff --git a/gdb/symfile.c b/gdb/symfile.c
> index 6f546f5b059..ec3244269b1 100644
> --- a/gdb/symfile.c
> +++ b/gdb/symfile.c
> @@ -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)
> diff --git a/gdb/symtab.c b/gdb/symtab.c
> index 8564986f66d..8d3be357ded 100644
> --- a/gdb/symtab.c
> +++ b/gdb/symtab.c
> @@ -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;
> diff --git a/gdb/target-dcache.c b/gdb/target-dcache.c
> index 0aa53302cea..3e3c0c6ee4d 100644
> --- a/gdb/target-dcache.c
> +++ b/gdb/target-dcache.c
> @@ -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. */
> diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
> index d8735d29ede..0be7991d5c2 100644
> --- a/gdb/xcoffread.c
> +++ b/gdb/xcoffread.c
> @@ -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. */
>
> --
> 2.34.1
>
next prev parent reply other threads:[~2022-06-07 10:56 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-30 17:59 [PATCH 0/6] " Tom Tromey
2022-05-30 17:59 ` [PATCH 1/6] Change address_space to use new and delete Tom Tromey
2022-05-30 17:59 ` [PATCH 2/6] Change allocation of type-copying hash table Tom Tromey
2022-05-30 17:59 ` [PATCH 3/6] Remove some unused functions from guile code Tom Tromey
2022-05-30 17:59 ` [PATCH 4/6] Rewrite registry.h Tom Tromey
2022-06-07 10:55 ` Lancelot SIX via Gdb-patches [this message]
2022-06-08 1:33 ` Tom Tromey
2022-06-08 18:51 ` Tom Tromey
2022-05-30 17:59 ` [PATCH 5/6] Change registry to use less memory Tom Tromey
2022-05-30 17:59 ` [PATCH 6/6] Remove some unneeded checks in Guile code Tom Tromey
2022-07-28 20:13 ` [PATCH 0/6] Rewrite registry.h Tom Tromey
2022-07-29 2:33 ` Simon Marchi via Gdb-patches
2022-08-02 2:46 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220607105532.tymzjyvngpdy6l6s@ubuntu.lan \
--to=gdb-patches@sourceware.org \
--cc=lsix@lancelotsix.com \
--cc=tom@tromey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox