From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-yw1-x1134.google.com (mail-yw1-x1134.google.com [IPv6:2607:f8b0:4864:20::1134]) by sourceware.org (Postfix) with ESMTPS id A6C9E3858D32 for ; Tue, 27 Jun 2023 03:54:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A6C9E3858D32 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-yw1-x1134.google.com with SMTP id 00721157ae682-57040e313c5so62864637b3.0 for ; Mon, 26 Jun 2023 20:54:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687838048; x=1690430048; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=9CFGeSGgD/IpijCfkD3zHwHQ9u09Ba4z0/+iKeWhvO4=; b=jJ00xVf0aMKzhUNpvAqJDPOJmyvFyNVIE7xBToAdB+LFOQ2nHdb2tW3XfRc/egNA+k iaw72AKuwm91H7TiiV4tCeP3/Re/RKyI/TT78pinnWe9VpxId7kVBku13eiSZLUIyE5G Snq8uiaATOAEP1a9CCLGpgWVQ167agPDdLlrgMqTALvR93MYn9nEZwdK+BeFFmLBQsne Xsucr/25PaR06ZoPrQqxWVCn67Da30jSknK6kJhiYKamMnWu1/7DRUJGsrwU0/2JhKK7 SSyTTVpysvTdO/hu+yr9Rz5Vn9kBqCnFfv5Zo0og0OSY4RzaRcC8aKWNDik44b6w7/ic Iz8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687838048; x=1690430048; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9CFGeSGgD/IpijCfkD3zHwHQ9u09Ba4z0/+iKeWhvO4=; b=BOMKAUVJ1hnSiwUlt3yJr00gHryqm1JXEfCDP0ilquB+MB7m5nuq8ySkLpGz7bnTe2 6NiQztim9fSUchlToCV59bjiA9gaGY0BLOwKtUaAwTVHR34PcFlqNgb1ojq8oN9s22p4 T8pr+j/LgG3wh+R23QSAutTAzOSjJjeChMaTheVc307Y0vSrqv2Ssep1hI4PRJTKhlXD GrADNSlMgc3duNjtrCvHgh7RIaX7zpX0wubV/mqdJb3xnOp6ZJHzH5njbjjInyyMBevi /hiUMhS2qFXqHRyvuM9XXB5VO/bjgum3WodBci8pUMqWAm3UwahWU8Dg1XUpzGlk6AEd AYuw== X-Gm-Message-State: AC+VfDwfAdXKg2eKAtuxlzcsifpucwegsdNwelU+ELH1//A1vhcw0+6l jeJlVUmvV+Mmn0Ol0pUNGhQkkLvgY579WQ+IIaqP5w5tEQo= X-Google-Smtp-Source: ACHHUZ4zH3I91s7yxvEHKRaIb7xNnVip2esDvZ/BF1nDRXRW7HHWG3feYpnXLakGk7AbHzpbNnLL5caMcWGuwxJo4c0= X-Received: by 2002:a81:5283:0:b0:56d:2a15:e275 with SMTP id g125-20020a815283000000b0056d2a15e275mr39334137ywb.6.1687838047434; Mon, 26 Jun 2023 20:54:07 -0700 (PDT) MIME-Version: 1.0 References: <20230527012435.96999-1-dark.ryu.550@gmail.com> In-Reply-To: <20230527012435.96999-1-dark.ryu.550@gmail.com> From: Matheus Branco Borella Date: Tue, 27 Jun 2023 00:53:56 -0300 Message-ID: Subject: [PING] Re: [PATCH] Add support for symbol addition to the Python API To: gdb-patches@sourceware.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-8.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Bump on this too, as instructed by the contribution checklist. On Fri, May 26, 2023 at 10:24=E2=80=AFPM Matheus Branco Borella wrote: > > Disclaimer: > > This patch is a rework of a six-month old patch I submitted to the mailin= g list > that considerably reduces the hackyness of the original solution to the p= roblem, > now that I've had more time to read through and understand how symbols ar= e > handled and searched for inside GDB. So, I'd like to please ask for comme= nts on > things I can still improve in this patch, before I resubmit it. I also pl= an to > add tests to it once I'm more secure about the approach I'm taking to sol= ve the > problem now. > > The interfaces in this patch can be tested like so: > ``` > (gdb) pi > >>> builder =3D gdb.ObjfileBuilder(name =3D "some_name") > >>> builder.add_static_symbol(name =3D "some_sym", address =3D 0x41414141= , > language =3D "c") > >>> objfile =3D builder.build() > ``` > > --- > > This patch adds support for symbol creation and registration. It currentl= y > supports adding type symbols (VAR_DOMAIN/LOC_TYPEDEF), static symbols > (VAR_DOMAIN/LOC_STATIC) and goto target labels (LABEL_DOMAIN/LOC_LABEL). = It > adds a new `gdb.ObjfileBuilder` type, with `add_type_symbol`, > `add_static_symbol` and `add_label_symbol` functions, allowing for the ad= dition > of the aforementioned types of symbols. > > Symbol addition is achieved by constructing a new objfile with msyms and = full > symbols reflecting the symbols that were previously added to the builder = through > its methods. This approach lets us get most of the way to full symbol add= ition > support, but due to not being backed up by BFD, it does have a few limita= tions, > which I will go over them here. > > PC-based minsym lookup does not work, because those would require a more > complete set of BFD structures than I think would be good practice to pre= tend to > have them all and crash GDB later on when it expects things to be there t= hat > aren't. > > In the same vein, PC-based function name lookup also does not work, altho= ugh > there may be a way to have the feature work using overlays. However, this= patch > does not make an attempt to do so > > For now, though, this implementation lets us add symbols that can be used= to, > for instance, query registered types through `gdb.lookup_type`, and allow= s > reverse engineering GDB plugins (such as Pwndbg [0] or decomp2gdb [1]) to= add > symbols directly through the Python API instead of having to compile an o= bject > file for the target architecture that they later load through the add-sym= bol- > file command. [2] > > [0] https://github.com/pwndbg/pwndbg/ > [1] https://github.com/mahaloz/decomp2dbg > [2] https://github.com/mahaloz/decomp2dbg/blob/055be6b2001954d00db2d683f2= 0e9b714af75880/decomp2dbg/clients/gdb/symbol_mapper.py#L235-L243] > --- > gdb/Makefile.in | 1 + > gdb/python/py-objfile-builder.c | 648 ++++++++++++++++++++++++++++++++ > gdb/python/py-objfile.c | 1 + > gdb/python/python-internal.h | 1 + > 4 files changed, 651 insertions(+) > create mode 100644 gdb/python/py-objfile-builder.c > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index 14b5dd0bad..c0eecb81b6 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -417,6 +417,7 @@ SUBDIR_PYTHON_SRCS =3D \ > python/py-micmd.c \ > python/py-newobjfileevent.c \ > python/py-objfile.c \ > + python/py-objfile-builder.c \ > python/py-param.c \ > python/py-prettyprint.c \ > python/py-progspace.c \ > diff --git a/gdb/python/py-objfile-builder.c b/gdb/python/py-objfile-buil= der.c > new file mode 100644 > index 0000000000..1e3110c613 > --- /dev/null > +++ b/gdb/python/py-objfile-builder.c > @@ -0,0 +1,648 @@ > +/* Python class allowing users to build and install objfiles. > + > + Copyright (C) 2013-2023 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 "python-internal.h" > +#include "quick-symbol.h" > +#include "objfiles.h" > +#include "minsyms.h" > +#include "buildsym.h" > +#include "observable.h" > +#include > +#include > +#include > +#include > + > +/* This module relies on symbols being trivially copyable. */ > +static_assert (std::is_trivially_copyable_v); > + > +/* Interface to be implemented for symbol types supported by this interf= ace. */ > +class symbol_def > +{ > +public: > + virtual ~symbol_def () =3D default; > + > + virtual void register_msymbol (const std::string& name, > + struct objfile* objfile, > + minimal_symbol_reader& reader) const = =3D 0; > + virtual void register_symbol (const std::string& name, > + struct objfile* objfile, > + buildsym_compunit& builder) const =3D 0; > +}; > + > +/* Shorthand for a unique_ptr to a symbol. */ > +typedef std::unique_ptr symbol_def_up; > + > +/* Data being held by the gdb.ObjfileBuilder. > + * > + * This structure needs to have its constructor run in order for its lif= etime > + * to begin. Because of how Python handles its objects, we can't just re= construct > + * the object structure as a whole, as that would overwrite things the r= untime > + * cares about, so these fields had to be broken off into their own stru= cture. */ > +struct objfile_builder_data > +{ > + /* Indicates whether the objfile has already been built and added to t= he > + * current context. We enforce that objfiles can't be installed twice.= */ > + bool installed =3D false; > + > + /* The symbols that will be added to new newly built objfile. */ > + std::unordered_map symbols; > + > + /* The name given to this objfile. */ > + std::string name; > + > + /* Adds a symbol definition with the given name. */ > + bool add_symbol_def (std::string name, symbol_def_up&& symbol_def) > + { > + return std::get<1> (symbols.insert ({name, std::move (symbol_def)}))= ; > + } > +}; > + > +/* Structure backing the gdb.ObjfileBuilder type. */ > + > +struct objfile_builder_object > +{ > + PyObject_HEAD > + > + /* See objfile_builder_data. */ > + objfile_builder_data inner; > +}; > + > +extern PyTypeObject objfile_builder_object_type > + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("objfile_builder_object_type"); > + > +/* Constructs a new objfile from an objfile_builder. */ > +static struct objfile * > +build_new_objfile (const objfile_builder_object& builder) > +{ > + gdb_assert (!builder.inner.installed); > + > + auto of =3D objfile::make (nullptr, builder.inner.name.c_str (), > + OBJF_READNOW | OBJF_NOT_FILENAME, > + nullptr); > + > + /* Setup object file sections. */ > + of->sections_start =3D OBSTACK_CALLOC (&of->objfile_obstack, > + 4, > + struct obj_section); > + of->sections_end =3D of->sections_start + 4; > + > + const auto init_section =3D [&](struct obj_section* sec) > + { > + sec->objfile =3D of; > + sec->ovly_mapped =3D false; > + > + /* We're not being backed by BFD. So we have no real section data = to speak > + * of, but, because specifying sections requires BFD structures, w= e have to > + * play a little game of predend. */ > + auto bfd =3D obstack_new (&of->objfile_obstack); > + bfd->vma =3D 0; > + bfd->size =3D 0; > + bfd->lma =3D 0; /* Prevents insert_section_p in objfiles.c from tr= ying to > + * dereference the bfd structure we don't have. */ > + sec->the_bfd_section =3D bfd; > + }; > + init_section (&of->sections_start[0]); > + init_section (&of->sections_start[1]); > + init_section (&of->sections_start[2]); > + init_section (&of->sections_start[4]); > + > + of->sect_index_text =3D 0; > + of->sect_index_data =3D 1; > + of->sect_index_rodata =3D 2; > + of->sect_index_bss =3D 3; > + > + /* While buildsym_compunit expects the symbol function pointer structu= re to be > + * present, it also gracefully handles the case where all of the point= ers in > + * it are set to null. So, make sure we have a valid structure, but th= ere's > + * no need to do more than that. */ > + of->sf =3D obstack_new (&of->objfile_obstack); > + > + /* We need to tell GDB what architecture the objfile uses. */ > + if (has_stack_frames ()) > + of->per_bfd->gdbarch =3D get_frame_arch (get_selected_frame (nullptr= )); > + else > + of->per_bfd->gdbarch =3D target_gdbarch (); > + > + /* Construct the minimal symbols. */ > + minimal_symbol_reader msym (of); > + for (const auto& [name, symbol] : builder.inner.symbols) > + symbol->register_msymbol (name, of, msym); > + msym.install (); > + > + /* Construct the full symbols. */ > + buildsym_compunit fsym (of, builder.inner.name.c_str (), "", language_= c, 0); > + for (const auto& [name, symbol] : builder.inner.symbols) > + symbol->register_symbol (name, of, fsym); > + fsym.end_compunit_symtab (0); > + > + /* Notify the rest of GDB this objfile has been created. Requires > + * OBJF_NOT_FILENAME to be used, to prevent any of the functions attat= ched to > + * the observable from trying to dereference of->bfd. */ > + gdb::observers::new_objfile.notify (of); > + > + return of; > +} > + > +/* Implementation of the quick symbol functions used by the objfiles cre= ated > + * using this interface. Turns out we have our work cut out for us here,= as we > + * can get something that works by effectively just using no-ops, and th= e rest > + * of the code will fall back to using just the minimal and full symbol = data. It > + * is important to note, though, that this only works because we're mark= ing our > + * objfile with `OBJF_READNOW`. */ > +class runtime_objfile : public quick_symbol_functions > +{ > + virtual bool has_symbols (struct objfile*) override > + { > + return false; > + } > + > + virtual void dump (struct objfile *objfile) override > + { > + } > + > + virtual void expand_matching_symbols > + (struct objfile *, > + const lookup_name_info &lookup_name, > + domain_enum domain, > + int global, > + symbol_compare_ftype *ordered_compare) override > + { > + } > + > + virtual bool expand_symtabs_matching > + (struct objfile *objfile, > + gdb::function_view file_matcher, > + const lookup_name_info *lookup_name, > + gdb::function_view symbol_matc= her, > + gdb::function_view expansion_notif= y, > + block_search_flags search_flags, > + domain_enum domain, > + enum search_domain kind) override > + { > + return true; > + } > +}; > + > + > +/* Create a new symbol alocated in the given objfile. */ > + > +static struct symbol * > +new_symbol > + (struct objfile *objfile, > + const char *name, > + enum language language, > + enum domain_enum domain, > + enum address_class aclass, > + short section_index) > +{ > + auto symbol =3D new (&objfile->objfile_obstack) struct symbol (); > + OBJSTAT (objfile, n_syms++); > + > + symbol->set_language (language, &objfile->objfile_obstack); > + symbol->compute_and_set_names (gdb::string_view (name), true, > + objfile->per_bfd); > + > + symbol->set_is_objfile_owned (true); > + symbol->set_section_index (section_index); > + symbol->set_domain (domain); > + symbol->set_aclass_index (aclass); > + > + return symbol; > +} > + > +/* Parses a language from a string (coming from Python) into a language > + * variant. */ > + > +static enum language > +parse_language (const char *language) > +{ > + if (strcmp (language, "c") =3D=3D 0) > + return language_c; > + else if (strcmp (language, "objc") =3D=3D 0) > + return language_objc; > + else if (strcmp (language, "cplus") =3D=3D 0) > + return language_cplus; > + else if (strcmp (language, "d") =3D=3D 0) > + return language_d; > + else if (strcmp (language, "go") =3D=3D 0) > + return language_go; > + else if (strcmp (language, "fortran") =3D=3D 0) > + return language_fortran; > + else if (strcmp (language, "m2") =3D=3D 0) > + return language_m2; > + else if (strcmp (language, "asm") =3D=3D 0) > + return language_asm; > + else if (strcmp (language, "pascal") =3D=3D 0) > + return language_pascal; > + else if (strcmp (language, "opencl") =3D=3D 0) > + return language_opencl; > + else if (strcmp (language, "rust") =3D=3D 0) > + return language_rust; > + else if (strcmp (language, "ada") =3D=3D 0) > + return language_ada; > + else > + return language_unknown; > +} > + > +/* Convenience function that performs a checked coversion from a PyObjec= t to > + * a objfile_builder_object structure pointer. */ > +inline static struct objfile_builder_object * > +validate_objfile_builder_object (PyObject *self) > +{ > + if (!PyObject_TypeCheck (self, &objfile_builder_object_type)) > + return nullptr; > + return (struct objfile_builder_object*) self; > +} > + > +/* Registers symbols added with add_label_symbol. */ > +class typedef_symbol_def : public symbol_def > +{ > +public: > + struct type* type; > + enum language language; > + > + virtual void register_msymbol (const std::string& name, > + struct objfile *objfile, > + minimal_symbol_reader& reader) const ov= erride > + { > + } > + > + virtual void register_symbol (const std::string& name, > + struct objfile *objfile, > + buildsym_compunit& builder) const overri= de > + { > + auto symbol =3D new_symbol (objfile, name.c_str (), language, LABEL_= DOMAIN, > + LOC_TYPEDEF, objfile->sect_index_text); > + > + symbol->set_type (type); > + > + add_symbol_to_list (symbol, builder.get_file_symbols ()); > + } > +}; > + > +/* Adds a type (LOC_TYPEDEF) symbol to a given objfile. */ > +static PyObject * > +objbdpy_add_type_symbol (PyObject *self, PyObject *args, PyObject *kw) > +{ > + static const char *format =3D "sOs"; > + static const char *keywords[] =3D > + { > + "name", "type", "language", NULL > + }; > + > + PyObject *type_object; > + const char *name; > + const char *language_name =3D nullptr; > + > + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, format, keywords, &nam= e, > + &type_object, &language_name)) > + return nullptr; > + > + auto builder =3D validate_objfile_builder_object (self); > + if (builder =3D=3D nullptr) > + return nullptr; > + > + struct type *type =3D type_object_to_type (type_object); > + if (type =3D=3D nullptr) > + return nullptr; > + > + if (language_name =3D=3D nullptr) > + language_name =3D "auto"; > + enum language language =3D parse_language (language_name); > + if (language =3D=3D language_unknown) > + { > + PyErr_SetString (PyExc_ValueError, "invalid language name"); > + return nullptr; > + } > + > + auto def =3D std::make_unique (); > + def->type =3D type; > + def->language =3D language; > + > + builder->inner.add_symbol_def (name, std::move (def)); > + > + Py_RETURN_NONE; > +} > + > + > +/* Registers symbols added with add_label_symbol. */ > +class label_symbol_def : public symbol_def > +{ > +public: > + CORE_ADDR address; > + enum language language; > + > + virtual void register_msymbol (const std::string& name, > + struct objfile *objfile, > + minimal_symbol_reader& reader) const ov= erride > + { > + reader.record (name.c_str (), > + unrelocated_addr (address), > + minimal_symbol_type::mst_text); > + } > + > + virtual void register_symbol (const std::string& name, > + struct objfile *objfile, > + buildsym_compunit& builder) const overri= de > + { > + printf("Adding label %s\n", name.c_str ()); > + auto symbol =3D new_symbol (objfile, name.c_str (), language, LABEL_= DOMAIN, > + LOC_LABEL, objfile->sect_index_text); > + > + symbol->set_value_address (address); > + > + add_symbol_to_list (symbol, builder.get_file_symbols ()); > + } > +}; > + > +/* Adds a label (LOC_LABEL) symbol to a given objfile. */ > +static PyObject * > +objbdpy_add_label_symbol (PyObject *self, PyObject *args, PyObject *kw) > +{ > + static const char *format =3D "sks"; > + static const char *keywords[] =3D > + { > + "name", "address", "language", NULL > + }; > + > + const char *name; > + CORE_ADDR address; > + const char *language_name =3D nullptr; > + > + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, format, keywords, &nam= e, > + &address, &language_name)) > + return nullptr; > + > + auto builder =3D validate_objfile_builder_object (self); > + if (builder =3D=3D nullptr) > + return nullptr; > + > + if (language_name =3D=3D nullptr) > + language_name =3D "auto"; > + enum language language =3D parse_language (language_name); > + if (language =3D=3D language_unknown) > + { > + PyErr_SetString (PyExc_ValueError, "invalid language name"); > + return nullptr; > + } > + > + auto def =3D std::make_unique (); > + def->address =3D address; > + def->language =3D language; > + > + builder->inner.add_symbol_def (name, std::move (def)); > + > + Py_RETURN_NONE; > +} > + > +/* Registers symbols added with add_static_symbol. */ > +class static_symbol_def : public symbol_def > +{ > +public: > + CORE_ADDR address; > + enum language language; > + > + virtual void register_msymbol (const std::string& name, > + struct objfile *objfile, > + minimal_symbol_reader& reader) const ov= erride > + { > + reader.record (name.c_str (), > + unrelocated_addr (address), > + minimal_symbol_type::mst_bss); > + } > + > + virtual void register_symbol (const std::string& name, > + struct objfile *objfile, > + buildsym_compunit& builder) const overri= de > + { > + auto symbol =3D new_symbol (objfile, name.c_str (), language, VAR_DO= MAIN, > + LOC_STATIC, objfile->sect_index_bss); > + > + symbol->set_value_address (address); > + > + add_symbol_to_list (symbol, builder.get_file_symbols ()); > + } > +}; > + > +/* Adds a static (LOC_STATIC) symbol to a given objfile. */ > +static PyObject * > +objbdpy_add_static_symbol (PyObject *self, PyObject *args, PyObject *kw) > +{ > + static const char *format =3D "sks"; > + static const char *keywords[] =3D > + { > + "name", "address", "language", NULL > + }; > + > + const char *name; > + CORE_ADDR address; > + const char *language_name =3D nullptr; > + > + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, format, keywords, &nam= e, > + &address, &language_name)) > + return nullptr; > + > + auto builder =3D validate_objfile_builder_object (self); > + if (builder =3D=3D nullptr) > + return nullptr; > + > + if (language_name =3D=3D nullptr) > + language_name =3D "auto"; > + enum language language =3D parse_language (language_name); > + if (language =3D=3D language_unknown) > + { > + PyErr_SetString (PyExc_ValueError, "invalid language name"); > + return nullptr; > + } > + > + auto def =3D std::make_unique (); > + def->address =3D address; > + def->language =3D language; > + > + builder->inner.add_symbol_def (name, std::move (def)); > + > + Py_RETURN_NONE; > +} > + > +/* Builds the object file. */ > +static PyObject * > +objbdpy_build (PyObject *self, PyObject *args) > +{ > + auto builder =3D validate_objfile_builder_object (self); > + if (builder =3D=3D nullptr) > + return nullptr; > + > + if (builder->inner.installed) > + { > + PyErr_SetString (PyExc_ValueError, "build() cannot be run twice on= the \ > + same object"); > + return nullptr; > + } > + auto of =3D build_new_objfile (*builder); > + builder->inner.installed =3D true; > + > + > + auto objpy =3D objfile_to_objfile_object (of).get (); > + Py_INCREF(objpy); > + return objpy; > +} > + > +/* Implements the __init__() function. */ > +static int > +objbdpy_init (PyObject *self0, PyObject *args, PyObject *kw) > +{ > + static const char *format =3D "s"; > + static const char *keywords[] =3D > + { > + "name", NULL > + }; > + > + const char *name; > + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, format, keywords, &nam= e)) > + return -1; > + > + auto self =3D (objfile_builder_object *)self0; > + self->inner.name =3D name; > + self->inner.symbols.clear (); > + > + return 0; > +} > + > +/* The function handling construction of the ObjfileBuilder object. > + * > + * We need to have a custom function here as, even though Python manages= the > + * memory backing the object up, it assumes clearing the memory is enoug= h to > + * begin its lifetime, which is not the case here, and would lead to und= efined > + * behavior as soon as we try to use it in any meaningful way. > + * > + * So, what we have to do here is manually begin the lifecycle of our ne= w object > + * by constructing it in place, using the memory region Python just allo= cated > + * for us. This ensures the object will have already started its lifetim= e by > + * the time we start using it. */ > +static PyObject * > +objbdpy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwds) > +{ > + objfile_builder_object *region =3D > + (objfile_builder_object *) subtype->tp_alloc(subtype, 1); > + gdb_assert ((size_t)region % alignof (objfile_builder_object) =3D=3D 0= ); > + gdb_assert (region !=3D nullptr); > + > + new (®ion->inner) objfile_builder_data (); > + > + return (PyObject *)region; > +} > + > +/* The function handling destruction of the ObjfileBuilder object. > + * > + * While running the destructor of our object isn't _strictly_ necessary= , we > + * would very much like for the memory it owns to be freed, but, because= it was > + * constructed in place, we have to call its destructor manually here. *= / > +static void > +objbdpy_dealloc (PyObject *self0) > +{ > + > + auto self =3D (objfile_builder_object *)self0; > + PyTypeObject *tp =3D Py_TYPE(self); > + > + self->inner.~objfile_builder_data (); > + > + tp->tp_free(self); > + Py_DECREF(tp); > +} > + > +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION > +gdbpy_initialize_objfile_builder (void) > +{ > + if (PyType_Ready (&objfile_builder_object_type) < 0) > + return -1; > + > + return gdb_pymodule_addobject (gdb_module, "ObjfileBuilder", > + (PyObject *) &objfile_builder_object_typ= e); > +} > + > +GDBPY_INITIALIZE_FILE (gdbpy_initialize_objfile_builder); > + > +static PyMethodDef objfile_builder_object_methods[] =3D > +{ > + { "build", (PyCFunction) objbdpy_build, METH_NOARGS, > + "build ().\n\ > +Build a new objfile containing the symbols added to builder." }, > + { "add_type_symbol", (PyCFunction) objbdpy_add_type_symbol, > + METH_VARARGS | METH_KEYWORDS, > + "add_type_symbol (name [str], type [gdb.Type], language [str]).\n\ > +Add a new type symbol in the given language, associated with the given t= ype." }, > + { "add_label_symbol", (PyCFunction) objbdpy_add_label_symbol, > + METH_VARARGS | METH_KEYWORDS, > + "add_label_symbol (name [str], address [int], language [str]).\n\ > +Add a new label symbol in the given language, at the given address." }, > + { "add_static_symbol", (PyCFunction) objbdpy_add_static_symbol, > + METH_VARARGS | METH_KEYWORDS, > + "add_static_symbol (name [str], address [int], language [str]).\n\ > +Add a new static symbol in the given language, at the given address." }, > + { NULL } > +}; > + > +PyTypeObject objfile_builder_object_type =3D { > + PyVarObject_HEAD_INIT (NULL, 0) > + "gdb.ObjfileBuilder", /* tp_name */ > + sizeof (objfile_builder_object), /* tp_basicsize */ > + 0, /* tp_itemsize */ > + objbdpy_dealloc, /* tp_dealloc */ > + 0, /* tp_vectorcall_offset */ > + nullptr, /* tp_getattr */ > + nullptr, /* tp_setattr */ > + nullptr, /* tp_compare */ > + nullptr, /* tp_repr */ > + nullptr, /* tp_as_number */ > + nullptr, /* tp_as_sequence */ > + nullptr, /* tp_as_mapping */ > + nullptr, /* tp_hash */ > + nullptr, /* tp_call */ > + nullptr, /* tp_str */ > + nullptr, /* tp_getattro */ > + nullptr, /* tp_setattro */ > + nullptr, /* tp_as_buffer */ > + Py_TPFLAGS_DEFAULT, /* tp_flags */ > + "GDB object file builder", /* tp_doc */ > + nullptr, /* tp_traverse */ > + nullptr, /* tp_clear */ > + nullptr, /* tp_richcompare */ > + 0, /* tp_weaklistoffset */ > + nullptr, /* tp_iter */ > + nullptr, /* tp_iternext */ > + objfile_builder_object_methods, /* tp_methods */ > + nullptr, /* tp_members */ > + nullptr, /* tp_getset */ > + nullptr, /* tp_base */ > + nullptr, /* tp_dict */ > + nullptr, /* tp_descr_get */ > + nullptr, /* tp_descr_set */ > + 0, /* tp_dictoffset */ > + objbdpy_init, /* tp_init */ > + PyType_GenericAlloc, /* tp_alloc */ > + objbdpy_new, /* tp_new */ > +}; > + > + > diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c > index ad72f3f042..be21011ce6 100644 > --- a/gdb/python/py-objfile.c > +++ b/gdb/python/py-objfile.c > @@ -25,6 +25,7 @@ > #include "build-id.h" > #include "symtab.h" > #include "python.h" > +#include "buildsym.h" > > struct objfile_object > { > diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h > index dbd33570a7..fbf9b06af5 100644 > --- a/gdb/python/python-internal.h > +++ b/gdb/python/python-internal.h > @@ -480,6 +480,7 @@ struct symtab *symtab_object_to_symtab (PyObject *obj= ); > struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); > frame_info_ptr frame_object_to_frame_info (PyObject *frame_obj); > struct gdbarch *arch_object_to_gdbarch (PyObject *obj); > +struct floatformat *float_format_object_as_float_format (PyObject *self)= ; > > /* Convert Python object OBJ to a program_space pointer. OBJ must be a > gdb.Progspace reference. Return nullptr if the gdb.Progspace is not > -- > 2.40.1 >