From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id a4GXJtIun2IlMQsAWB0awg (envelope-from ) for ; Tue, 07 Jun 2022 06:56:18 -0400 Received: by simark.ca (Postfix, from userid 112) id 8E8741E222; Tue, 7 Jun 2022 06:56:18 -0400 (EDT) Authentication-Results: simark.ca; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=hHdIRCPx; dkim-atps=neutral X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RDNS_DYNAMIC,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 871291E143 for ; Tue, 7 Jun 2022 06:56:15 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DFB2E382BD27 for ; Tue, 7 Jun 2022 10:56:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DFB2E382BD27 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1654599375; bh=qpYLgAaSL6ecPxE68jueZWLWPlqjm0DAMp+ff1DN9SM=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=hHdIRCPxU1vfqbHwjo6L5yYsQSbKAr8JIJzmh6Xh/KWcAvAiF7q+PqzyUyvTFQma3 QtAz3ib2enUI92ln+1x1/LBsIn8rSLbs8RyROfmLGtBihvsFQUkOZOmc+/zfmXrOzv 7UsUFmTyM4quUTXhDxBFPtp8LEWMmEHxZSo39UbA= Received: from lndn.lancelotsix.com (vps-42846194.vps.ovh.net [IPv6:2001:41d0:801:2000::2400]) by sourceware.org (Postfix) with ESMTPS id 8B7EA3857366 for ; Tue, 7 Jun 2022 10:55:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8B7EA3857366 Received: from ubuntu.lan (unknown [IPv6:2a02:390:9086::635]) by lndn.lancelotsix.com (Postfix) with ESMTPSA id 43E0D88B5A; Tue, 7 Jun 2022 10:55:38 +0000 (UTC) Date: Tue, 7 Jun 2022 10:55:32 +0000 To: Tom Tromey Subject: Re: [PATCH 4/6] Rewrite registry.h Message-ID: <20220607105532.tymzjyvngpdy6l6s@ubuntu.lan> References: <20220530175934.3872892-1-tom@tromey.com> <20220530175934.3872892-5-tom@tromey.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20220530175934.3872892-5-tom@tromey.com> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.5.11 (lndn.lancelotsix.com [0.0.0.0]); Tue, 07 Jun 2022 10:55:38 +0000 (UTC) X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Lancelot SIX via Gdb-patches Reply-To: Lancelot SIX Cc: gdb-patches@sourceware.org Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" 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 > > >::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::operator()(dwarf2_per_objfile*) const /usr/include/c++/9/bits/unique_ptr.h:81 #4 0x56310c962fc2 in registry::key >::cleanup(void*) ../../gdb/registry.h:158 #5 0x56310cf60fa3 in registry::clear_registry() ../../gdb/registry.h:175 #6 0x56310cf5f833 in registry::~registry() ../../gdb/registry.h:77 #7 0x56310cf56499 in objfile::~objfile() ../../gdb/objfiles.c:501 #8 0x56310cf6ae22 in std::_Sp_counted_ptr::_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::~__shared_ptr() /usr/include/c++/9/bits/shared_ptr_base.h:1169 #12 0x56310cf5edbf in std::shared_ptr::~shared_ptr() /usr/include/c++/9/bits/shared_ptr.h:103 #13 0x56310d00c0c9 in void __gnu_cxx::new_allocator > >::destroy >(std::shared_ptr*) /usr/include/c++/9/ext/new_allocator.h:152 #14 0x56310d0084ee in void std::allocator_traits > > >::destroy >(std::allocator > >&, std::shared_ptr*) /usr/include/c++/9/bits/alloc_traits.h:496 #15 0x56310d00e85d in std::__cxx1998::__cxx11::list, std::allocator > >::_M_erase(std::__cxx1998::_List_iterator >) /usr/include/c++/9/bits/stl_list.h:1921 #16 0x56310d00a468 in std::__cxx1998::__cxx11::list, std::allocator > >::erase(std::__cxx1998::_List_const_iterator >) /usr/include/c++/9/bits/list.tcc:158 #17 0x56310d005ad7 in std::__debug::list, std::allocator > >::_M_erase(std::__cxx1998::_List_const_iterator >) /usr/include/c++/9/debug/list:499 #18 0x56310d001dda in std::__debug::list, std::allocator > >::erase(__gnu_debug::_Safe_iterator >, std::__debug::list, std::allocator > >, 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::operator()(dwarf2_per_bfd*) const /usr/include/c++/9/bits/unique_ptr.h:81 #2 0x56310c9630cb in registry::key >::cleanup(void*) ../../gdb/registry.h:158 #3 0x56310cafb85f in registry::clear_registry() (/home/lancesix/src/worktrees/gdb/upstream-master/_build/gdb/gdb+0x1c2985f) #4 0x56310cafb175 in registry::~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::_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::~__shared_ptr() /usr/include/c++/9/bits/shared_ptr_base.h:1169 #12 0x56310cf5edbf in std::shared_ptr::~shared_ptr() /usr/include/c++/9/bits/shared_ptr.h:103 #13 0x56310d00c0c9 in void __gnu_cxx::new_allocator > >::destroy >(std::shared_ptr*) /usr/include/c++/9/ext/new_allocator.h:152 #14 0x56310d0084ee in void std::allocator_traits > > >::destroy >(std::allocator > >&, std::shared_ptr*) /usr/include/c++/9/bits/alloc_traits.h:496 #15 0x56310d00e85d in std::__cxx1998::__cxx11::list, std::allocator > >::_M_erase(std::__cxx1998::_List_iterator >) /usr/include/c++/9/bits/stl_list.h:1921 #16 0x56310d00a468 in std::__cxx1998::__cxx11::list, std::allocator > >::erase(std::__cxx1998::_List_const_iterator >) /usr/include/c++/9/bits/list.tcc:158 #17 0x56310d005ad7 in std::__debug::list, std::allocator > >::_M_erase(std::__cxx1998::_List_const_iterator >) /usr/include/c++/9/debug/list:499 #18 0x56310d001dda in std::__debug::list, std::allocator > >::erase(__gnu_debug::_Safe_iterator >, std::__debug::list, std::allocator > >, 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; > +static const registry::key 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_handle; > +static const registry::key > + 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 > +static const registry::key > 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 > +static const registry::key > 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_bfd_data_key; > +static const registry::key 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_key; > +static const registry::key 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 > - auto_load_pspace_data; > +static const registry::key > + 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_inferior_data; > +static const registry::key 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 > +static const registry::key > 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 exception_probes; > }; > > -static const struct objfile_key > +static const registry::key > 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_objfile_data_key; > +static const registry::key 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 ctf_tid_key; > +static const registry::key 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_dict_key; > +static const registry::key 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_objfile_data_key; > +const registry::key 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) > > /* 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 dwarf2_frame_bfd_data; > +static const registry::key 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 dwarf2_frame_objfile_data; > +static const registry::key dwarf2_frame_objfile_data; > > > /* 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_objfile_data_key; > +static const registry::key > + dwarf2_objfile_data_key; > > /* These are used to store the dwarf2_per_bfd objects. > > @@ -134,8 +135,9 @@ static const objfile_key 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_bfd_data_key; > -static const struct objfile_key dwarf2_per_bfd_objfile_data_key; > +static const registry::key dwarf2_per_bfd_bfd_data_key; > +static const registry::key > + 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> elfread_data; > > /* Per-BFD data for probe info. */ > > -static const struct bfd_key probe_key; > +static const registry::key 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 > +static const registry::key > 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 > +static const registry::key > 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_objfile_data_key; > +extern const registry::key 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 included_bfds; > > /* The registry. */ > - REGISTRY_FIELDS = {}; > + registry registry_fields; > }; > > -#define GDB_BFD_DATA_ACCESSOR(ABFD) \ > - ((struct gdb_bfd_data *) bfd_usrdata (ABFD)) > - > -DEFINE_REGISTRY (bfd, GDB_BFD_DATA_ACCESSOR) > +registry * > +registry_accessor::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 > +{ > + static registry *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> > fixed_point_type_storage; > > /* Key used for managing the storage of fixed-point type info. */ > -static const struct objfile_key > +static const struct registry::key > 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 - gdb::noop_deleter> > +static const registry::key + gdb::noop_deleter> > 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::key > + bkscm_objfile_data_key; > > /* Administrivia for block smobs. */ > > @@ -108,13 +138,13 @@ bkscm_eq_block_smob (const void *ap, const void *bp) > static htab_t > bkscm_objfile_block_map (struct objfile *objfile) > { > - htab_t htab = (htab_t) objfile_data (objfile, bkscm_objfile_data_key); > + htab_t htab = bkscm_objfile_data_key.get (objfile); > > if (htab == NULL) > { > htab = gdbscm_create_eqable_gsmob_ptr_map (bkscm_hash_block_smob, > bkscm_eq_block_smob); > - set_objfile_data (objfile, bkscm_objfile_data_key, htab); > + bkscm_objfile_data_key.set (objfile, htab); > } > > return htab; > @@ -326,35 +356,6 @@ bkscm_scm_to_block (SCM block_scm, int arg_pos, const char *func_name, > return NULL; > } > > -/* Helper function for bkscm_del_objfile_blocks to mark the block > - as invalid. */ > - > -static int > -bkscm_mark_block_invalid (void **slot, void *info) > -{ > - block_smob *b_smob = (block_smob *) *slot; > - > - b_smob->block = NULL; > - b_smob->objfile = NULL; > - return 1; > -} > - > -/* This function is called when an objfile is about to be freed. > - Invalidate the block as further actions on the block would result > - in bad data. All access to b_smob->block should be gated by > - checks to ensure the block is (still) valid. */ > - > -static void > -bkscm_del_objfile_blocks (struct objfile *objfile, void *datum) > -{ > - htab_t htab = (htab_t) datum; > - > - if (htab != NULL) > - { > - htab_traverse_noresize (htab, bkscm_mark_block_invalid, NULL); > - htab_delete (htab); > - } > -} > > /* Block methods. */ > > @@ -800,13 +801,3 @@ gdbscm_initialize_blocks (void) > gdbscm_scm_from_c_string ("\ > Internal function to assist the block symbols iterator.")); > } > - > -void _initialize_scm_block (); > -void > -_initialize_scm_block () > -{ > - /* Register an objfile "free" callback so we can properly > - invalidate blocks when an object file is about to be deleted. */ > - bkscm_objfile_data_key > - = register_objfile_data_with_cleanup (NULL, bkscm_del_objfile_blocks); > -} > 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::key > + frscm_inferior_data_key; > > /* Administrivia for frame smobs. */ > > @@ -117,13 +147,13 @@ frscm_eq_frame_smob (const void *ap, const void *bp) > static htab_t > frscm_inferior_frame_map (struct inferior *inferior) > { > - htab_t htab = (htab_t) inferior_data (inferior, frscm_inferior_data_key); > + htab_t htab = frscm_inferior_data_key.get (inferior); > > if (htab == NULL) > { > htab = gdbscm_create_eqable_gsmob_ptr_map (frscm_hash_frame_smob, > frscm_eq_frame_smob); > - set_inferior_data (inferior, frscm_inferior_data_key, htab); > + frscm_inferior_data_key.set (inferior, htab); > } > > return htab; > @@ -346,35 +376,6 @@ frscm_frame_smob_to_frame (frame_smob *f_smob) > return frame; > } > > -/* Helper function for frscm_del_inferior_frames to mark the frame > - as invalid. */ > - > -static int > -frscm_mark_frame_invalid (void **slot, void *info) > -{ > - frame_smob *f_smob = (frame_smob *) *slot; > - > - f_smob->inferior = NULL; > - return 1; > -} > - > -/* This function is called when an inferior is about to be freed. > - Invalidate the frame as further actions on the frame could result > - in bad data. All access to the frame should be gated by > - frscm_get_frame_smob_arg_unsafe which will raise an exception on > - invalid frames. */ > - > -static void > -frscm_del_inferior_frames (struct inferior *inferior, void *datum) > -{ > - htab_t htab = (htab_t) datum; > - > - if (htab != NULL) > - { > - htab_traverse_noresize (htab, frscm_mark_frame_invalid, NULL); > - htab_delete (htab); > - } > -} > > /* Frame methods. */ > > @@ -1170,13 +1171,3 @@ gdbscm_initialize_frames (void) > > block_keyword = scm_from_latin1_keyword ("block"); > } > - > -void _initialize_scm_frame (); > -void > -_initialize_scm_frame () > -{ > - /* Register an inferior "free" callback so we can properly > - invalidate frames when an inferior file is about to be deleted. */ > - frscm_inferior_data_key > - = register_inferior_data_with_cleanup (NULL, frscm_del_inferior_frames); > -} > 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::key > + 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 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::key > + 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 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::key > + syscm_objfile_data_key; > static struct gdbarch_data *syscm_gdbarch_data_key; > > struct syscm_gdbarch_data > @@ -105,12 +135,12 @@ syscm_get_symbol_map (struct symbol *symbol) > { > struct objfile *objfile = symbol->objfile (); > > - htab = (htab_t) objfile_data (objfile, syscm_objfile_data_key); > + htab = syscm_objfile_data_key.get (objfile); > if (htab == NULL) > { > htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob, > syscm_eq_symbol_smob); > - set_objfile_data (objfile, syscm_objfile_data_key, htab); > + syscm_objfile_data_key.set (objfile, htab); > } > } > else > @@ -291,35 +321,6 @@ syscm_get_valid_symbol_arg_unsafe (SCM self, int arg_pos, > return s_smob->symbol; > } > > -/* Helper function for syscm_del_objfile_symbols to mark the symbol > - as invalid. */ > - > -static int > -syscm_mark_symbol_invalid (void **slot, void *info) > -{ > - symbol_smob *s_smob = (symbol_smob *) *slot; > - > - s_smob->symbol = NULL; > - return 1; > -} > - > -/* This function is called when an objfile is about to be freed. > - Invalidate the symbol as further actions on the symbol would result > - in bad data. All access to s_smob->symbol should be gated by > - syscm_get_valid_symbol_smob_arg_unsafe which will raise an exception on > - invalid symbols. */ > - > -static void > -syscm_del_objfile_symbols (struct objfile *objfile, void *datum) > -{ > - htab_t htab = (htab_t) datum; > - > - if (htab != NULL) > - { > - htab_traverse_noresize (htab, syscm_mark_symbol_invalid, NULL); > - htab_delete (htab); > - } > -} > > /* Symbol methods. */ > > @@ -823,11 +824,6 @@ void _initialize_scm_symbol (); > void > _initialize_scm_symbol () > { > - /* Register an objfile "free" callback so we can properly > - invalidate symbols when an object file is about to be deleted. */ > - syscm_objfile_data_key > - = register_objfile_data_with_cleanup (NULL, syscm_del_objfile_symbols); > - > /* Arch-specific symbol data. */ > syscm_gdbarch_data_key > = gdbarch_data_register_post_init (syscm_init_arch_symbols); > 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::key > + stscm_objfile_data_key; > > /* Administrivia for symtab smobs. */ > > @@ -110,13 +140,13 @@ static htab_t > stscm_objfile_symtab_map (struct symtab *symtab) > { > struct objfile *objfile = symtab->compunit ()->objfile (); > - htab_t htab = (htab_t) objfile_data (objfile, stscm_objfile_data_key); > + htab_t htab = stscm_objfile_data_key.get (objfile); > > if (htab == NULL) > { > htab = gdbscm_create_eqable_gsmob_ptr_map (stscm_hash_symtab_smob, > stscm_eq_symtab_smob); > - set_objfile_data (objfile, stscm_objfile_data_key, htab); > + stscm_objfile_data_key.set (objfile, htab); > } > > return htab; > @@ -271,35 +301,6 @@ stscm_get_valid_symtab_smob_arg_unsafe (SCM self, int arg_pos, > return st_smob; > } > > -/* Helper function for stscm_del_objfile_symtabs to mark the symtab > - as invalid. */ > - > -static int > -stscm_mark_symtab_invalid (void **slot, void *info) > -{ > - symtab_smob *st_smob = (symtab_smob *) *slot; > - > - st_smob->symtab = NULL; > - return 1; > -} > - > -/* This function is called when an objfile is about to be freed. > - Invalidate the symbol table as further actions on the symbol table > - would result in bad data. All access to st_smob->symtab should be > - gated by stscm_get_valid_symtab_smob_arg_unsafe which will raise an > - exception on invalid symbol tables. */ > - > -static void > -stscm_del_objfile_symtabs (struct objfile *objfile, void *datum) > -{ > - htab_t htab = (htab_t) datum; > - > - if (htab != NULL) > - { > - htab_traverse_noresize (htab, stscm_mark_symtab_invalid, NULL); > - htab_delete (htab); > - } > -} > > /* Symbol table methods. */ > > @@ -687,14 +688,3 @@ gdbscm_initialize_symtabs (void) > > gdbscm_define_functions (symtab_functions, 1); > } > - > -void _initialize_scm_symtab (); > -void > -_initialize_scm_symtab () > -{ > - /* Register an objfile "free" callback so we can properly > - invalidate symbol tables, and symbol table and line data > - structures when an object file that is about to be deleted. */ > - stscm_objfile_data_key > - = register_objfile_data_with_cleanup (NULL, stscm_del_objfile_symtabs); > -} > 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::key > + tyscm_objfile_data_key; > > /* Hash table to uniquify global (non-objfile-owned) types. */ > static htab_t global_types_map; > @@ -158,12 +181,12 @@ tyscm_type_map (struct type *type) > if (objfile == NULL) > return global_types_map; > > - htab = (htab_t) objfile_data (objfile, tyscm_objfile_data_key); > + htab = tyscm_objfile_data_key.get (objfile); > if (htab == NULL) > { > htab = gdbscm_create_eqable_gsmob_ptr_map (tyscm_hash_type_smob, > tyscm_eq_type_smob); > - set_objfile_data (objfile, tyscm_objfile_data_key, htab); > + tyscm_objfile_data_key.set (objfile, htab); > } > > return htab; > @@ -345,20 +368,17 @@ tyscm_scm_to_type (SCM t_scm) > return t_smob->type; > } > > -/* Helper function for save_objfile_types to make a deep copy of the type. */ > +/* Helper function to make a deep copy of the type. */ > > static int > tyscm_copy_type_recursive (void **slot, void *info) > { > type_smob *t_smob = (type_smob *) *slot; > htab_t copied_types = (htab_t) info; > - struct objfile *objfile = t_smob->type->objfile_owner (); > htab_t htab; > eqable_gdb_smob **new_slot; > type_smob t_smob_for_lookup; > > - gdb_assert (objfile != NULL); > - > htab_empty (copied_types); > t_smob->type = copy_type_recursive (t_smob->type, copied_types); > > @@ -380,25 +400,6 @@ tyscm_copy_type_recursive (void **slot, void *info) > return 1; > } > > -/* Called when OBJFILE is about to be deleted. > - Make a copy of all types associated with OBJFILE. */ > - > -static void > -save_objfile_types (struct objfile *objfile, void *datum) > -{ > - htab_t htab = (htab_t) datum; > - > - if (!gdb_scheme_initialized) > - return; > - > - htab_up copied_types = create_copied_types_hash (); > - > - if (htab != NULL) > - { > - htab_traverse_noresize (htab, tyscm_copy_type_recursive, copied_types.get ()); > - htab_delete (htab); > - } > -} > > /* Administrivia for field smobs. */ > > @@ -1510,13 +1511,3 @@ Internal function to assist the type fields iterator.")); > global_types_map = gdbscm_create_eqable_gsmob_ptr_map (tyscm_hash_type_smob, > tyscm_eq_type_smob); > } > - > -void _initialize_scm_type (); > -void > -_initialize_scm_type () > -{ > - /* Register an objfile "free" callback so we can properly copy types > - associated with the objfile when it's about to be deleted. */ > - tyscm_objfile_data_key > - = register_objfile_data_with_cleanup (save_objfile_types, NULL); > -} > 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_priv_data; > +static const registry::key > + 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_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 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 inflow_inferior_data; > +static const registry::key 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_inferior_data; > +static const registry::key 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 - gdb::noop_deleter> > +static const registry::key + gdb::noop_deleter> > 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 gnu_debug_key; > +static const registry::key gnu_debug_key; > > #include > > 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 > +static const registry::key > 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 objc_objfile_data; > +static const registry::key 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 > #include > > -/* 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 > +static const registry::key > 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 objfiles_bfd_data; > +static const registry::key 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 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; > > > > -/* Keep a registry of per-program_space data-pointers required by other GDB > - modules. */ > - > -DEFINE_REGISTRY (program_space, REGISTRY_ACCESS_FIELD) > - > -/* Keep a registry of per-address_space data-pointers required by other GDB > - modules. */ > - > -DEFINE_REGISTRY (address_space, REGISTRY_ACCESS_FIELD) > - > - > - > /* Create a new address space object, and add it to the list. */ > > address_space::address_space () > : m_num (++highest_address_space_num) > { > - address_space_alloc_data (this); > } > > /* Maybe create a new address space object, and add it to the list, or > @@ -81,11 +68,6 @@ maybe_new_address_space (void) > return new address_space (); > } > > -address_space::~address_space () > -{ > - address_space_free_data (this); > -} > - > /* Start counting over from scratch. */ > > static void > @@ -115,8 +97,6 @@ program_space::program_space (address_space *aspace_) > : num (++last_program_space_num), > aspace (aspace_) > { > - program_space_alloc_data (this); > - > program_spaces.push_back (this); > } > > @@ -140,8 +120,6 @@ program_space::~program_space () > clear_symtab_users (SYMFILE_DEFER_BP_RESET); > if (!gdbarch_has_shared_address_space (target_gdbarch ())) > delete this->aspace; > - /* Discard any data modules have associated with the PSPACE. */ > - program_space_free_data (this); > } > > /* See progspace.h. */ > 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> objfile_list; > @@ -372,7 +371,7 @@ struct program_space > std::vector deleted_solibs; > > /* Per pspace data-pointers required by other GDB modules. */ > - REGISTRY_FIELDS {}; > + registry 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 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::key > + 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 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::key > + 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 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 object (obj); > + object->objfile = nullptr; > + } > +}; > + > +static const registry::key > + 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) > > > > -/* 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 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 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 object (obj); > + object->pspace = NULL; > + } > +}; > + > +static const registry::key > + 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) > > > > -/* 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 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 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::key > + 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::key > + 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::key > + 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) > > > > -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::key > + 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 . */ > - > -#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 > > -/* 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 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 > +struct registry_accessor > +{ > + /* Given a container of type T, return its registry. */ > + static registry *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 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> \ > -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 std::enable_if - std::default_delete>::value, \ > - Dummy>::type \ > - emplace (struct TAG *obj, Args &&...args) const \ > - { \ > - DATA *result = new DATA (std::forward (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 > +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> > + class key > + { > + public: > + > + key () > + : m_key (registry::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 *reg_obj = registry_accessor::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 *reg_obj = registry_accessor::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 std::enable_if + std::default_delete>::value, > + Dummy>::type > + emplace (T *obj, Args &&...args) const > + { > + DATA *result = new DATA (std::forward (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::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 result (new registry_data); > + std::vector> ®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 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> &get_registrations () > + { > + static std::vector> 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_key; > +static const registry::key 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> > +static const registry::key> > 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_key; > +static registry::key 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_handle; > +static const registry::key > + 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 solib_darwin_pspace_data; > +static const registry::key > + 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 solib_dsbt_pspace_data; > +static const registry::key 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 solib_svr4_pspace_data; > +static const registry::key 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 soname_build_id_map; > > /* Key used to associate a soname_build_id_map to a core file bfd. */ > > -static const struct bfd_key cbfd_soname_build_id_data_key; > +static const struct registry::key > + 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_key; > +static const registry::key > + 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 - gdb::noop_deleter> > +static const registry::key + gdb::noop_deleter> > 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 > +static const registry::key > 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_progspace_key; > +static const registry::key 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_key; > +static const registry::key 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 > +static const registry::key > 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_objfile_data_key; > +static const registry::key xcoff_objfile_data_key; > > /* Convenience macro to access the per-objfile XCOFF data. */ > > -- > 2.34.1 >