From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 46313 invoked by alias); 31 Oct 2018 16:59:09 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 46299 invoked by uid 89); 31 Oct 2018 16:59:07 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.4 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,KAM_STOCKGEN,SEM_URIRED,SPF_PASS autolearn=ham version=3.3.2 spammy=som, typical, @value, cite X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 31 Oct 2018 16:59:01 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id F2F68B03B; Wed, 31 Oct 2018 16:58:58 +0000 (UTC) Subject: Re: [PATCH][gdb/python] Add interface to access minimal_symbols To: Simon Marchi , gdb-patches@sourceware.org, Phil Muldoon , Tom Tromey References: <20181004211115.GA31056@delia> <39c4336d-c749-6f79-5a29-0b764fc4935e@ericsson.com> From: Tom de Vries Message-ID: <211c4746-389a-93b7-faf9-c8f9b6245541@suse.de> Date: Wed, 31 Oct 2018 16:59:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 In-Reply-To: <39c4336d-c749-6f79-5a29-0b764fc4935e@ericsson.com> Content-Type: multipart/mixed; boundary="------------1461ED06460D45853EBA08CC" X-IsSubscribed: yes X-SW-Source: 2018-10/txt/msg00756.txt.bz2 This is a multi-part message in MIME format. --------------1461ED06460D45853EBA08CC Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 14622 On 10/5/18 6:43 AM, Simon Marchi wrote: > On 2018-10-04 05:11 PM, Tom de Vries wrote: >> Hi, >> >> [ Submitted earlier here ( >> https://sourceware.org/ml/gdb-patches/2016-02/msg00124.html ). ] >> >> This patch adds a new gdb.MinSymbol object to export the minimal_symbol >> interface. >> >> Build and reg-tested on x86_64-linux. >> >> OK for trunk? >> >> Thanks, >> - Tom > > Hi Tom, > > I think I have read (probably from Phil or Tom Tromey) that the intention was to > expose minsyms and full symbols using the same Symbol class, to avoid exposing > the fact that GDB represents symbols in different ways internally. I don't know > if there was some concrete plans for that or if it was just at the idea stage. > > Otherwise, I'd be fine with exposing gdb.MinSyms and documenting that they map to > the binary file format symbols (ELF, PE, mach-O, etc) while gdb.Symbols map to > debug info symbols. I think it's a reality that will not change any time soon, > and it could be useful for users of the Python API to make the distinction > between the two. > > Maybe I'm missing something that has already been discussed that makes exposing > minsyms a bad idea, in that case Phil and Tom are probably going to be able to > shed som light on that. In the mean time here are a bunch of random > comments/suggestions. > > * A general GDB-specific code style comment, every time you compare a pointer > to know if it's NULL or not, it should be explicitly "ptr == NULL" or "ptr != NULL". Done. > * Please make sure that all functions are documented (with an introductory comment). > Done. >> >> [gdb/python] Add interface to access minimal_symbols >> >> 2018-09-27 Jeff Mahoney >> Tom de Vries >> >> * Makefile.in (SUBDIR_PYTHON_SRCS): Add python/py-minsymbol.c. >> * python/py-minsymbol.c: New file. >> * python/py-objfile.c (objfpy_object_to_objfile): New function. >> * python/python-internal.h (minsym_object_type) >> (gdbpy_lookup_minimal_symbol, objfpy_object_to_objfile): >> (gdbpy_initialize_minsymbols): Declare. >> * python/python.c (do_start_initialization): Call >> gdbpy_initialize_minsymbols. >> (python_GdbMethods): Add lookup_minimal_symbol entry. >> >> * python.texi (@node Python API): Add "Minimal Symbols In Python" menu >> entry. >> (@node Minimal Symbols In Python): New node. >> >> * gdb.python/py-minsymbol.c: New test. >> * gdb.python/py-minsymbol.exp: New file. >> >> --- >> gdb/Makefile.in | 1 + >> gdb/doc/python.texi | 140 +++++++++ >> gdb/python/py-minsymbol.c | 492 ++++++++++++++++++++++++++++++ >> gdb/python/py-objfile.c | 9 + >> gdb/python/python-internal.h | 7 + >> gdb/python/python.c | 5 + >> gdb/testsuite/gdb.python/py-minsymbol.c | 38 +++ >> gdb/testsuite/gdb.python/py-minsymbol.exp | 67 ++++ >> 8 files changed, 759 insertions(+) >> >> diff --git a/gdb/Makefile.in b/gdb/Makefile.in >> index 8d780ac758..489dab5ca1 100644 >> --- a/gdb/Makefile.in >> +++ b/gdb/Makefile.in >> @@ -377,6 +377,7 @@ SUBDIR_PYTHON_SRCS = \ >> python/py-instruction.c \ >> python/py-lazy-string.c \ >> python/py-linetable.c \ >> + python/py-minsymbol.c \ >> python/py-newobjfileevent.c \ >> python/py-objfile.c \ >> python/py-param.c \ >> diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi >> index 1035be33f0..d91f6e35c5 100644 >> --- a/gdb/doc/python.texi >> +++ b/gdb/doc/python.texi >> @@ -158,6 +158,7 @@ optional arguments while skipping others. Example: >> * Frames In Python:: Accessing inferior stack frames from Python. >> * Blocks In Python:: Accessing blocks from Python. >> * Symbols In Python:: Python representation of symbols. >> +* Minimal Symbols In Python:: Python representation of minimal symbols. >> * Symbol Tables In Python:: Python representation of symbol tables. >> * Line Tables In Python:: Python representation of line tables. >> * Breakpoints In Python:: Manipulating breakpoints using Python. >> @@ -4878,6 +4879,145 @@ The value does not actually exist in the program. >> The value's address is a computed location. >> @end vtable >> >> +@node Minimal Symbols In Python >> +@subsubsection Python representation of Minimal Symbols. >> + >> +@cindex minsymbols in python >> +@tindex gdb.MinSymbol >> + >> +@value{GDBN} represents every variable, function and type as an >> +entry in a symbol table. @xref{Symbols, ,Examining the Symbol Table}. >> +Typical symbols like functions, variables, etc are represented by >> +gdb.Symbol objects in Python. Some symbols are defined with less >> +information associated with them, like linker script variables >> +or assembly labels. Python represents these minimal symbols in @value{GDBN} >> +with the @code{gdb.MinSymbol} object. > > Here for example, I would make it clear that a MinSym == a symbol provided by the > binary file format, and would cite ELF, PE and mach-O as examples. I think that > would make it more obvious to the reader. > Done. >> + >> +The following minimal symbol-related functions are available in the @code{gdb} >> +module: >> + >> +@findex gdb.lookup_minimal_symbol >> +@defun gdb.lookup_minimal_symbol (name @r{[}, sfile@r{]}, objfile@r{[}) > > The square bracket look wrong. Since sfile and objfile are keyword arguments, > I guess you want them to look like this? > > gdb.lookup_minimal_symbol (name [, sfile][, objfile]) > > ? > Done. > Not in this patch, but I think we should document the default value for keyword > arguments, like the official Python doc does, which would mean something like: > > gdb.lookup_minimal_symbol (name, sfile=None, objfile=None) > > >> +This function searches for a minimal symbol by name. >> +The search scope can be restricted by the sfile and objfile arguments. >> + >> +@var{name} is the name of the minimal symbol. It must be a string. >> +The optional @var{sfile} argument restricts the search to the source file >> +in which the minimal symbol was defined. >> +The @var{sfile} argument must be a string. The optional @var{objfile} >> +restricts the search to the objfile that contains the minimal symbol. >> +The @var{objfile} argument must be a @code{gdb.Objfile} object. > > Can you try to split these in some kind of bullet, or at least one parameter > per paragraph? I think we have a tendency to document parameters in a big > paragraph, which does not make it easy to look up an individual parameter. > > I think a format like this makes it really easy to read: > > https://nodejs.org/dist/latest-v10.x/docs/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length > Done. > Also, would it be possible to precise how the search is made, especially > when multiple symbols match a search? If I have a C++ program with this: > > void allo(int x) > { > } > > void allo(float f) > { > } > > then doing gdb.lookup_minimal_symbol('allo') will only return one of them. > Done. > It would also be good to mention how the sfile argument is used, does it have > to be an exact match, just the base name, any substring? > Done. >> +The result is a @code{gdb.MinSymbol} object or @code{None} if the symbol >> +is not found. >> +@end defun >> + >> +A @code{gdb.MinSymbol} object has the following attributes: >> + >> +@defvar MinSymbol.name >> +The name of the symbol as a string. This attribute is not writable. >> +@end defvar >> + >> +@defvar MinSymbol.linkage_name >> +The name of the symbol, as used by the linker (i.e., may be mangled). >> +This attribute is not writable. >> +@end defvar >> + >> +@defvar MinSymbol.print_name >> +The name of the symbol in a form suitable for output. This is either >> +@code{name} or @code{linkage_name}, depending on whether the user >> +asked @value{GDBN} to display demangled or mangled names. >> +@end defvar >> + >> +@defvar MinSymbol.filename >> +The file name of the source file where the minimal symbol is defined. This >> +value may represent filenames used internally by the compiler rather >> +than a viewable/editable source file. >> +@end defvar >> + >> +@defvar MinSymbol.section >> +The name of the binary section containing this minimal symbol. >> +@end defvar >> + >> +@defvar MinSymbol.is_code >> +@code{True} if the minimal symbol is a function or a method. >> +@end defvar >> + >> +@defvar MinSymbol.is_data >> +@code{True} if the symbol is a variable or other data. >> +@end defvar >> + >> +A @code{gdb.MinSymbol} object has the following methods: >> + >> +@defun MinSymbol.is_valid () >> +Returns @code{True} if the @code{gdb.MinSymbol} object is valid, >> +@code{False} if not. A @code{gdb.MinSymbol} object can become invalid if >> +the symbol it refers to does not exist in @value{GDBN} any longer. >> +All other @code{gdb.MinSymbol} methods will throw an exception if it is >> +invalid at the time the method is called. >> +@end defun >> + >> +@defun MinSymbol.value () >> +Compute the value of the minimal symbol, as a @code{gdb.Value}. The value >> +returned represents the address of the minimal symbol. Since minimal symbols >> +represent objects without rich type information, the @code{gdb.Type} >> +associated with the @code{gdb.Value} objects will be limited to whether >> +the minimal symbol describes executable code or data. >> +@end defun >> + >> +The available types for @code{gdb.MinSymbol} are represented >> +as constants in the @code{gdb} module. They are distinctly separate from the >> +types represented by the @code{gdb.Type} object. > > I think the "type" method, that returns one of these, is not documented. > Done. >> +int >> +gdbpy_initialize_minsymbols (void) >> +{ >> + if (PyType_Ready (&minsym_object_type) < 0) >> + return -1; >> + >> + msympy_objfile_data_key >> + = register_objfile_data_with_cleanup (NULL, del_objfile_msymbols); >> + >> + if (PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_UNKNOWN", >> + mst_unknown) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_TEXT", >> + mst_text) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_TEXT_GNU_IFUNC", >> + mst_text_gnu_ifunc) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_SLOT_GOT_PLT", >> + mst_slot_got_plt) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_DATA", >> + mst_data) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_BSS", mst_bss) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_ABS", mst_abs) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_SOLIB_TRAMPOLINE", >> + mst_solib_trampoline) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_TEXT", >> + mst_file_text) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_DATA", >> + mst_file_data) < 0 >> + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_BSS", >> + mst_file_bss) < 0) > > I was a bit worried about exposing the internal enum values, but it seems like > we do this in other places (like gdb.COMMAND_* constants). If scripts use the > labels, they don't really care what the numerical value is. > >> + return -1; >> + >> + return gdb_pymodule_addobject (gdb_module, "MinSymbol", >> + (PyObject *) &minsym_object_type); >> +} >> + >> + >> + >> +static gdb_PyGetSetDef minsym_object_getset[] = { >> + { "name", msympy_get_name, NULL, >> + "Name of the minimal symbol, as it appears in the source code.", NULL }, >> + { "linkage_name", msympy_get_linkage_name, NULL, >> + "Name of the minimal symbol, as used by the linker (i.e., may be mangled).", >> + NULL }, >> + { "filename", msympy_get_file_name, NULL, >> + "Name of source file that contains this minimal symbol. Only applies for" >> + " mst_file_*.", >> + NULL }, >> + { "print_name", msympy_get_print_name, NULL, >> + "Name of the minimal symbol in a form suitable for output.\n\ >> +This is either name or linkage_name, depending on whether the user asked GDB\n\ >> +to display demangled or mangled names.", NULL }, >> + { "section", msympy_get_section, NULL, >> + "Section that contains this minimal symbol, if any", NULL, }, > > I would suggest naming this "section_name". It would leave the "section" property > available so that ff we ever have a Python type to represent binary file sections, > we can use it to return that. > Done. >> + { "type", msympy_get_type, NULL, >> + "Type that this minimal symbol represents." }, >> + { NULL } /* Sentinel */ >> +}; >> + >> +static PyMethodDef minsym_object_methods[] = { >> + { "is_valid", msympy_is_valid, METH_NOARGS, >> + "is_valid () -> Boolean.\n\ >> +Return true if this minimal symbol is valid, false if not." }, >> + { "is_code", msympy_is_code, METH_NOARGS, >> + "is_code () -> Boolean.\n\ >> +Return true if this minimal symbol represents code." }, >> + { "is_data", msympy_is_data, METH_NOARGS, >> + "is_data () -> Boolean.\n\ >> +Return true if this minimal symbol represents data." }, >> + { "value", msympy_value, METH_VARARGS, >> + "value ([frame]) -> gdb.Value\n\ >> +Return the value of the minimal symbol." }, >> + {NULL} /* Sentinel */ >> +}; >> + >> +PyTypeObject minsym_object_type = { >> + PyVarObject_HEAD_INIT (NULL, 0) >> + "gdb.MinSymbol", /*tp_name*/ >> + sizeof (minsym_object), /*tp_basicsize*/ >> + 0, /*tp_itemsize*/ >> + msympy_dealloc, /*tp_dealloc*/ >> + 0, /*tp_print*/ >> + 0, /*tp_getattr*/ >> + 0, /*tp_setattr*/ >> + 0, /*tp_compare*/ >> + 0, /*tp_repr*/ >> + 0, /*tp_as_number*/ >> + 0, /*tp_as_sequence*/ >> + 0, /*tp_as_mapping*/ >> + 0, /*tp_hash */ >> + 0, /*tp_call*/ >> + msympy_str, /*tp_str*/ > > I would suggest implementing repr instead, as we have done for > gdb.Objfile and others. Also, I would suggest using the output > style > > > > to be somewhat consistent. Done. AFAIU, the purpose of repr is to print a unique representation, and distinct symbols can have the same name, so I went for: ... ... for local symbols, dropping the filename=%s part for local symbols. > I think it helps when developing to > have the type of the object printed. Plus, we make sure people > don't rely on the output of repr/str to format the output the > way they want :). > Retested as attached. Thanks, - Tom --------------1461ED06460D45853EBA08CC Content-Type: text/x-patch; name="0001-gdb-python-Add-interface-to-access-minimal_symbols.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename*0="0001-gdb-python-Add-interface-to-access-minimal_symbols.patc"; filename*1="h" Content-length: 34958 [gdb/python] Add interface to access minimal_symbols [ Submitted earlier here ( https://sourceware.org/ml/gdb-patches/2016-02/msg00124.html ). ] This patch adds a new gdb.MinSymbol object to export the minimal_symbol interface. Build and reg-tested on x86_64-linux. 2018-09-27 Jeff Mahoney Tom de Vries * NEWS: Mention new function gdb.lookup_minimal_symbol and new class gdb.MinSymbol. * Makefile.in (SUBDIR_PYTHON_SRCS): Add python/py-minsymbol.c. * python/py-minsymbol.c: New file. * python/py-objfile.c (objectfile_object_to_objfile): New function. * python/python-internal.h (minsym_object_type) (gdbpy_lookup_minimal_symbol, objectfile_object_to_objfile): (gdbpy_initialize_minsymbols): Declare. * python/python.c (do_start_initialization): Call gdbpy_initialize_minsymbols. (python_GdbMethods): Add lookup_minimal_symbol entry. * python.texi (@node Python API): Add "Minimal Symbols In Python" menu entry. (@node Minimal Symbols In Python): New node. * gdb.texinfo (@anchor{set print demangle}): New anchor. * gdb.python/py-minsymbol.c: New test. * gdb.python/py-minsymbol.exp: New file. --- gdb/Makefile.in | 1 + gdb/doc/python.texi | 139 ++++++++ gdb/python/py-minsymbol.c | 511 ++++++++++++++++++++++++++++++ gdb/python/py-objfile.c | 9 + gdb/python/python-internal.h | 7 + gdb/python/python.c | 5 + gdb/testsuite/gdb.python/Makefile.in | 22 ++ gdb/testsuite/gdb.python/py-minsymbol.exp | 59 ++++ 8 files changed, 753 insertions(+) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 73e15fcf12..75de424a36 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -377,6 +377,7 @@ SUBDIR_PYTHON_SRCS = \ python/py-instruction.c \ python/py-lazy-string.c \ python/py-linetable.c \ + python/py-minsymbol.c \ python/py-newobjfileevent.c \ python/py-objfile.c \ python/py-param.c \ diff --git a/gdb/NEWS b/gdb/NEWS index 4331769f21..b9b08a0daa 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -139,6 +139,9 @@ FreeBSD/riscv riscv*-*-freebsd* gdb.SYMBOL_TYPES_DOMAIN are now deprecated. These were never correct and did not work properly. + ** The new function gdb.lookup_minimal_symbol can be used to find minimal + symbols. It return the new class gdb.MinSymbol. + * Configure changes --enable-ubsan diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 0226b6d88d..c1bdaa357f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -10672,6 +10672,7 @@ These settings are of interest when debugging C@t{++} programs: @table @code @cindex demangling C@t{++} names +@anchor{set print demangle} @item set print demangle @itemx set print demangle on Print C@t{++} names in their source form rather than in the encoded diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index ff5fecea1b..f22fdfe8d6 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -158,6 +158,7 @@ optional arguments while skipping others. Example: * Frames In Python:: Accessing inferior stack frames from Python. * Blocks In Python:: Accessing blocks from Python. * Symbols In Python:: Python representation of symbols. +* Minimal Symbols In Python:: Python representation of minimal symbols. * Symbol Tables In Python:: Python representation of symbol tables. * Line Tables In Python:: Python representation of line tables. * Breakpoints In Python:: Manipulating breakpoints using Python. @@ -4886,6 +4887,152 @@ The value's address is a symbol. This is only used for Fortran common blocks. @end vtable +@node Minimal Symbols In Python +@subsubsection Python representation of Minimal Symbols. + +@cindex minsymbols in python +@tindex gdb.MinSymbol + +@value{GDBN} represents every variable, function and type provided by +the binary file format (f.i. ELF, PE or mach-O) as an entry in a +symbol table. @xref{Symbols, ,Examining the Symbol Table}. +Typical symbols like functions, variables, etc are represented by +@code{gdb.Symbol} objects in Python. Some symbols are defined with less +information associated with them, like linker script variables +or assembly labels. Python represents these minimal symbols in @value{GDBN} +with the @code{gdb.MinSymbol} object. + +The following minimal symbol-related functions are available in the @code{gdb} +module: + +@defun gdb.lookup_minimal_symbol (name @r{[}, sfile@r{][}, objfile@r{]}) +This function searches for a minimal symbol by name. The search scope +can be restricted by the @var{sfile} and @var{objfile} arguments. + +@itemize @bullet +@item +The @var{name} argument is the name of the minimal symbol. It must be +a string. Both mangled and demangled names can be used. +@item +The optional @var{sfile} argument restricts the search to the basename +of source file @var{sfile} for local symbols. For global symbols, +this argument has no effect. The @var{sfile} argument must be a string. +@item +The optional @var{objfile} +restricts the search to the objfile that contains the minimal symbol. +The @var{objfile} argument must be a @code{gdb.Objfile} object. +@item +The result is a @code{gdb.MinSymbol} object or @code{None} if the symbol +is not found. In case there's more than one match, the first one +found is returned. +@end itemize +@end defun + +A @code{gdb.MinSymbol} object has the following attributes: + +@defvar MinSymbol.name +The name of the symbol as a string. This attribute is not writable. +@end defvar + +@defvar MinSymbol.linkage_name +The name of the symbol, as used by the linker (i.e., may be mangled). +This attribute is not writable. +@end defvar + +@defvar MinSymbol.print_name +The name of the symbol in a form suitable for output. This is either +@code{name} or @code{linkage_name}, depending on whether the user +asked @value{GDBN} to display demangled or mangled names +(@pxref{set print demangle}). +@end defvar + +@defvar MinSymbol.filename +The file name of the source file where the minimal symbol is defined. +@end defvar + +@defvar MinSymbol.section_name +The name of the section in the object file containing this minimal symbol. +@end defvar + +@defvar MinSymbol.is_code +@code{True} if the minimal symbol is a function or a method. +@end defvar + +@defvar MinSymbol.is_data +@code{True} if the symbol is a variable or other data. +@end defvar + +@defun MinSymbol.type +The type of the symbol. The value can be one of: + +@vtable @code +@vindex MINSYMBOL_TYPE_UNKNOWN +@item gdb.MINSYMBOL_TYPE_UNKNOWN +This is used when the type has not been discovered or none of the +following types apply. This usually indicates an error either +in the symbol information or in @value{GDBN}'s handling of symbols. + +@vindex MINSYMBOL_TYPE_TEXT +@item gdb.MINSYMBOL_TYPE_TEXT +This type represents executable code. + +@vindex MINSYMBOL_TYPE_TEXT_GNU_IFUNC +@item gdb.MINSYMBOL_TYPE_TEXT_GNU_IFUNC +This type represents executable code that returns the address +of executable code. + +@vindex MINSYMBOL_TYPE_SLOT_GOT_PLT +@item gdb.MINSYMBOL_TYPE_SLOT_GOT_PLT +This type represents GOT for .plt sections. + +@vindex MINSYMBOL_TYPE_DATA +@item gdb.MINSYMBOL_TYPE_DATA +This type represents generally initialized (nonzero) data. + +@vindex MINSYMBOL_TYPE_BSS +@item gdb.MINSYMBOL_TYPE_BSS +This type represents generally uninitialized (zeroed) data. + +@vindex MINSYMBOL_TYPE_ABS +@item gdb.MINSYMBOL_TYPE_ABS +This type represents generally absolute (non-relocatable) data. + +@vindex MINSYMBOL_TYPE_SOLIB_TRAMPOLINE +@item gdb.MINSYMBOL_TYPE_SOLIB_TRAMPOLINE +This type represents the start address of a shared library trampoline entry. + +@vindex MINSYMBOL_TYPE_FILE_TEXT +@item gdb.MINSYMBOL_TYPE_FILE_TEXT +This type represents the static version of @code{gdb.MINSYMBOL_TYPE_TEXT}. + +@vindex MINSYMBOL_TYPE_FILE_DATA +@item gdb.MINSYMBOL_TYPE_FILE_DATA +This type represents the static version of @code{gdb.MINSYMBOL_TYPE_DATA}. + +@vindex MINSYMBOL_TYPE_FILE_BSS +@item gdb.MINSYMBOL_TYPE_FILE_BSS +This type represents the static version of @code{gdb.MINSYMBOL_TYPE_BSS}. +@end vtable +@end defun + +A @code{gdb.MinSymbol} object has the following methods: + +@defun MinSymbol.is_valid () +Returns @code{True} if the @code{gdb.MinSymbol} object is valid, +@code{False} if not. A @code{gdb.MinSymbol} object can become invalid if +the symbol it refers to does not exist in @value{GDBN} any longer. +All other @code{gdb.MinSymbol} methods will throw an exception if it is +invalid at the time the method is called. +@end defun + +@defun MinSymbol.value () +Compute the value of the minimal symbol, as a @code{gdb.Value}. The value +returned represents the address of the minimal symbol. Since minimal symbols +represent objects without rich type information, the @code{gdb.Type} +associated with the @code{gdb.Value} objects will be limited to whether +the minimal symbol describes executable code or data. +@end defun + @node Symbol Tables In Python @subsubsection Symbol table representation in Python diff --git a/gdb/python/py-minsymbol.c b/gdb/python/py-minsymbol.c new file mode 100644 index 0000000000..93df3f9da5 --- /dev/null +++ b/gdb/python/py-minsymbol.c @@ -0,0 +1,560 @@ +/* Python interface to minsymbols. + + Copyright (C) 2018 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 "block.h" +#include "exceptions.h" +#include "frame.h" +#include "symtab.h" +#include "python-internal.h" +#include "objfiles.h" +#include "value.h" +#include "py-ref.h" + +typedef struct msympy_symbol_object { + PyObject_HEAD + + /* The GDB bound_minimal_symbol structure this object is wrapping. */ + struct bound_minimal_symbol bound; + + /* A minsym object is associated with an objfile, so keep track with + doubly-linked list, rooted in the objfile. This lets us + invalidate the underlying struct minimal_symbol when the objfile is + deleted. */ + struct msympy_symbol_object *prev; + struct msympy_symbol_object *next; +} minsym_object; + +/* Return the symbol that is wrapped by this symbol object. */ +static struct minimal_symbol * +minsym_object_to_minsym (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &minsym_object_type)) + return NULL; + return ((minsym_object *) obj)->bound.minsym; +} + +/* Return the objectfile containing the symbol that is wrapped by this symbol + object. */ +static struct objfile * +minsym_object_to_objfile (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &minsym_object_type)) + return NULL; + return ((minsym_object *) obj)->bound.objfile; +} + +/* Require a valid symbol. All access to minsym_object->bound.minsym should be + gated by this call. */ +#define MSYMPY_REQUIRE_VALID(minsym_obj, minsym) \ + do { \ + minsym = minsym_object_to_minsym (minsym_obj); \ + if (minsym == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("MinSymbol is invalid.")); \ + return NULL; \ + } \ + } while (0) + +/* Require a valid bound. All access to minsym_object->bound should be + gated by this call. */ +#define MSYMPY_REQUIRE_VALID_BOUND(minsym_obj, minsym, objfile) \ + do { \ + minsym = minsym_object_to_minsym (minsym_obj); \ + objfile = minsym_object_to_objfile (minsym_obj); \ + if (minsym == NULL || objfile == NULL) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("MinSymbol is invalid.")); \ + return NULL; \ + } \ + } while (0) + +static const struct objfile_data *msympy_objfile_data_key; + +/* Return string object containing MSYMBOL_PRINT_NAME for minsym object + SELF. */ + +static PyObject * +msympy_str (PyObject *self) +{ + struct minimal_symbol *minsym = NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + + return PyString_FromString (MSYMBOL_PRINT_NAME (minsym)); +} + +/* Implement repr() for gdb.MinSymbol. */ + +static PyObject * +msympy_repr (PyObject *self) +{ + struct minimal_symbol *minsym = minsym_object_to_minsym (self); + struct objfile *objfile = minsym_object_to_objfile (self); + + if (minsym->filename != NULL) + return PyString_FromFormat ("", + MSYMBOL_LINKAGE_NAME (minsym), + minsym->filename, + objfile_filename (objfile)); + + return PyString_FromFormat ("", + MSYMBOL_LINKAGE_NAME (minsym), + objfile_filename (objfile)); +} + +/* Implement gdb.MinSymbol.name -> String. */ + +static PyObject * +msympy_get_name (PyObject *self, void *closure) +{ + struct minimal_symbol *minsym = NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + + return PyString_FromString (MSYMBOL_NATURAL_NAME (minsym)); +} + +/* Implement gdb.MinSymbol.filename -> String. */ + +static PyObject * +msympy_get_file_name (PyObject *self, void *closure) +{ + struct minimal_symbol *minsym = NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + + return PyString_FromString (minsym->filename); +} + +/* Implement gdb.MinSymbol.linkage_name -> String. */ + +static PyObject * +msympy_get_linkage_name (PyObject *self, void *closure) +{ + struct minimal_symbol *minsym = NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + + return PyString_FromString (MSYMBOL_LINKAGE_NAME (minsym)); +} + +/* Implement gdb.MinSymbol.print_name -> String. */ + +static PyObject * +msympy_get_print_name (PyObject *self, void *closure) +{ + struct minimal_symbol *minsym = NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + + return msympy_str (self); +} + +/* Implement gdb.MinSymbol.section_name -> String. */ + +static PyObject * +msympy_get_section (PyObject *self, void *closure) +{ + struct minimal_symbol *minsym = NULL; + struct objfile *objfile = NULL; + struct obj_section *section; + const char *name; + + MSYMPY_REQUIRE_VALID_BOUND (self, minsym, objfile); + + section = MSYMBOL_OBJ_SECTION (objfile, minsym); + if (section != NULL) + { + name = bfd_section_name (objfile->obfd, section->the_bfd_section); + if (name != NULL) + return PyString_FromString (name); + } + + Py_RETURN_NONE; +} + +/* Implement gdb.MinSymbol.type -> Int. */ + +static PyObject * +msympy_get_type (PyObject *self, void *closure) +{ + struct minimal_symbol *minsym = NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + return PyInt_FromLong (MSYMBOL_TYPE (minsym)); +} + +/* Implement gdb.MinSymbol.is_valid (self) -> Boolean. */ + +static PyObject * +msympy_is_valid (PyObject *self, PyObject *args) +{ + struct minimal_symbol *minsym = NULL; + + minsym = minsym_object_to_minsym (self); + if (minsym == NULL) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Return gdbarch corresponding to minsym object MINSYM_OBJ. */ + +static struct gdbarch * +minsym_gdbarch (PyObject *minsym_obj) +{ + return get_objfile_arch (minsym_object_to_objfile (minsym_obj)); +} + +/* Return type corresponding to minsym object MINSYM_OBJ. */ + +static struct type * +minsym_type (PyObject *minsym_obj) +{ + struct type *type; + + switch (minsym_object_to_minsym (minsym_obj)->type) + { + case mst_text: + case mst_solib_trampoline: + case mst_file_text: + case mst_text_gnu_ifunc: + case mst_slot_got_plt: + type = builtin_type (minsym_gdbarch (minsym_obj))->builtin_func_ptr; + break; + + case mst_data: + case mst_abs: + case mst_bss: + case mst_file_data: + case mst_file_bss: + type = builtin_type (minsym_gdbarch (minsym_obj))->builtin_data_ptr; + break; + + case mst_unknown: + default: + type = builtin_type (minsym_gdbarch (minsym_obj))->builtin_void; + break; + } + + return type; +} + +/* Implement gdb.MinSymbol.is_code (self) -> Boolean. */ + +static PyObject * +msympy_is_code (PyObject *self, PyObject *args) +{ + struct minimal_symbol *minsym = NULL; + struct type *type; + MSYMPY_REQUIRE_VALID (self, minsym); + + type = builtin_type (minsym_gdbarch (self))->builtin_func_ptr; + + if (minsym_type (self) == type) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* Implement gdb.MinSymbol.is_data (self) -> Boolean. */ + +static PyObject * +msympy_is_data (PyObject *self, PyObject *args) +{ + struct minimal_symbol *minsym = NULL; + struct type *type; + MSYMPY_REQUIRE_VALID (self, minsym); + + type = builtin_type (minsym_gdbarch (self))->builtin_data_ptr; + + if (minsym_type (self) == type) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* Implementation of gdb.MinSymbol.value (self) -> gdb.Value. Returns + the value of the symbol, or an error in various circumstances. */ + +static PyObject * +msympy_value (PyObject *self, PyObject *args) +{ + minsym_object *minsym_obj = (minsym_object *)self; + struct minimal_symbol *minsym = NULL; + struct value *value = NULL; + + if (!PyArg_ParseTuple (args, "")) + return NULL; + + MSYMPY_REQUIRE_VALID (self, minsym); + TRY + { + value = value_at_lazy (minsym_type (self), + BMSYMBOL_VALUE_ADDRESS (minsym_obj->bound)); + } + CATCH (except, RETURN_MASK_ALL) + { + GDB_PY_HANDLE_EXCEPTION (except); + } + END_CATCH + + return value_to_value_object (value); +} + +/* Given a bound minimal symbol, and a minsym_object that has previously been + allocated and initialized, populate the minsym_object with the struct + bound_minimal_symbol data. Also, register the minsym_objectlife-cycle with + the life-cycle of the object file associated with this minimal symbol, if + needed. */ + +static void +set_symbol (minsym_object *obj, struct bound_minimal_symbol *bound) +{ + obj->bound = *bound; + obj->prev = NULL; + if (bound->objfile != NULL) + { + obj->next = (minsym_object *) objfile_data (bound->objfile, + msympy_objfile_data_key); + if (obj->next != NULL) + obj->next->prev = obj; + set_objfile_data (bound->objfile, msympy_objfile_data_key, obj); + } + else + obj->next = NULL; +} + +/* Create a new minsym object (gdb.MinSymbol) that encapsulates the struct + bound_minimal_symbol object from GDB. */ + +static PyObject * +bound_minsym_to_minsym_object (struct bound_minimal_symbol *bound) +{ + minsym_object *msym_obj; + + msym_obj = PyObject_New (minsym_object, &minsym_object_type); + if (msym_obj != NULL) + set_symbol (msym_obj, bound); + + return (PyObject *) msym_obj; +} + +/* Deallocate minsym object. */ + +static void +msympy_dealloc (PyObject *obj) +{ + minsym_object *msym_obj = (minsym_object *) obj; + + if (msym_obj->prev != NULL) + msym_obj->prev->next = msym_obj->next; + else if (msym_obj->bound.objfile != NULL) + set_objfile_data (msym_obj->bound.objfile, + msympy_objfile_data_key, msym_obj->next); + if (msym_obj->next != NULL) + msym_obj->next->prev = msym_obj->prev; + msym_obj->bound.minsym = NULL; + msym_obj->bound.objfile = NULL; +} + +/* Implementation of + gdb.lookup_minimal_symbol (name, [sfile, [objfile]]) -> symbol or None. */ + +PyObject * +gdbpy_lookup_minimal_symbol (PyObject *self, PyObject *args, PyObject *kw) +{ + const char *name, *sfile = NULL; + struct objfile *objfile = NULL; + static const char *keywords[] = { "name", "sfile", "objfile", NULL }; + struct bound_minimal_symbol bound_minsym = {}; + PyObject *msym_obj = NULL, *sfile_obj = NULL, *objfile_obj = NULL; + gdb::unique_xmalloc_ptr sfile_tmp; + + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|OO", keywords, &name, + &sfile_obj, &objfile_obj)) + return NULL; + + if (sfile_obj != NULL && sfile_obj != Py_None) + { + sfile_tmp = gdbpy_obj_to_string (sfile_obj); + sfile = sfile_tmp.get (); + } + + if (objfile_obj != NULL && objfile_obj != Py_None) + { + objfile = objectfile_object_to_objfile (objfile_obj); + if (objfile == NULL) + return NULL; + } + + TRY + { + bound_minsym = lookup_minimal_symbol (name, sfile, objfile); + } + CATCH (except, RETURN_MASK_ALL) + { + GDB_PY_HANDLE_EXCEPTION (except); + } + END_CATCH + + if (bound_minsym.minsym != NULL) + msym_obj = bound_minsym_to_minsym_object (&bound_minsym); + + if (msym_obj != NULL) + return msym_obj; + + Py_RETURN_NONE; +} + +/* This function is called when an objfile is about to be freed. + Invalidate the minsym as further actions on the minsym would result + in bad data. All access to obj->bound.minsym should be gated by + MSYMPY_REQUIRE_VALID which will raise an exception on invalid + minimal symbols. */ + +static void +del_objfile_msymbols (struct objfile *objfile, void *datum) +{ + minsym_object *obj = (minsym_object *) datum; + while (obj != NULL) + { + minsym_object *next = obj->next; + + obj->bound.minsym = NULL; + obj->bound.objfile = NULL; + obj->next = NULL; + obj->prev = NULL; + + obj = next; + } +} + +/* Initialize gdb.MinSymbol. Return -1 on error, 0 on success. */ + +int +gdbpy_initialize_minsymbols (void) +{ + if (PyType_Ready (&minsym_object_type) < 0) + return -1; + + msympy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, del_objfile_msymbols); + + if (PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_UNKNOWN", + mst_unknown) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_TEXT", + mst_text) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_TEXT_GNU_IFUNC", + mst_text_gnu_ifunc) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_SLOT_GOT_PLT", + mst_slot_got_plt) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_DATA", + mst_data) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_BSS", mst_bss) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_ABS", mst_abs) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_SOLIB_TRAMPOLINE", + mst_solib_trampoline) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_TEXT", + mst_file_text) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_DATA", + mst_file_data) < 0 + || PyModule_AddIntConstant (gdb_module, "MINSYMBOL_TYPE_FILE_BSS", + mst_file_bss) < 0) + return -1; + + return gdb_pymodule_addobject (gdb_module, "MinSymbol", + (PyObject *) &minsym_object_type); +} + + + +static gdb_PyGetSetDef minsym_object_getset[] = { + { "name", msympy_get_name, NULL, + "Name of the minimal symbol, as it appears in the source code.", NULL }, + { "linkage_name", msympy_get_linkage_name, NULL, + "Name of the minimal symbol, as used by the linker (i.e., may be mangled).", + NULL }, + { "filename", msympy_get_file_name, NULL, + "Name of source file that contains this minimal symbol. Only applies for" + " mst_file_*.", + NULL }, + { "print_name", msympy_get_print_name, NULL, + "Name of the minimal symbol in a form suitable for output.\n\ +This is either name or linkage_name, depending on whether the user asked GDB\n\ +to display demangled or mangled names.", NULL }, + { "section_name", msympy_get_section, NULL, + "Name of section that contains this minimal symbol, if any", NULL, }, + { "type", msympy_get_type, NULL, + "Type that this minimal symbol represents." }, + { NULL } /* Sentinel */ +}; + +static PyMethodDef minsym_object_methods[] = { + { "is_valid", msympy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this minimal symbol is valid, false if not." }, + { "is_code", msympy_is_code, METH_NOARGS, + "is_code () -> Boolean.\n\ +Return true if this minimal symbol represents code." }, + { "is_data", msympy_is_data, METH_NOARGS, + "is_data () -> Boolean.\n\ +Return true if this minimal symbol represents data." }, + { "value", msympy_value, METH_VARARGS, + "value ([frame]) -> gdb.Value\n\ +Return the value of the minimal symbol." }, + {NULL} /* Sentinel */ +}; + +PyTypeObject minsym_object_type = { + PyVarObject_HEAD_INIT (NULL, 0) + "gdb.MinSymbol", /*tp_name*/ + sizeof (minsym_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + msympy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + msympy_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB minimal symbol object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + minsym_object_methods, /*tp_methods */ + 0, /*tp_members */ + minsym_object_getset /*tp_getset */ +}; diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index 2e24d0f3ff..89d8d6d815 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -417,6 +417,17 @@ objfpy_is_valid (PyObject *self, PyObject *args) Py_RETURN_TRUE; } +/* Return struct objfile reference that is wrapped by the SELF object. */ + +struct objfile * +objectfile_object_to_objfile (PyObject *self) +{ + objfile_object *obj = (objfile_object *) self; + OBJFPY_REQUIRE_VALID (obj); + + return obj->objfile; +} + /* Implementation of gdb.Objfile.add_separate_debug_file (self) -> Boolean. */ static PyObject * diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 1812abb5b7..28f89919ff 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -366,6 +366,8 @@ extern PyTypeObject block_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("block_object"); extern PyTypeObject symbol_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("symbol_object"); +extern PyTypeObject minsym_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("minsym_object"); extern PyTypeObject event_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); extern PyTypeObject breakpoint_object_type @@ -475,6 +477,8 @@ PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw); PyObject *gdbpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw); +PyObject *gdbpy_lookup_minimal_symbol (PyObject *self, PyObject *args, + PyObject *kw); PyObject *gdbpy_start_recording (PyObject *self, PyObject *args); PyObject *gdbpy_current_recording (PyObject *self, PyObject *args); PyObject *gdbpy_stop_recording (PyObject *self, PyObject *args); @@ -516,6 +520,7 @@ PyObject *objfpy_get_frame_filters (PyObject *, void *); PyObject *objfpy_get_frame_unwinders (PyObject *, void *); PyObject *objfpy_get_xmethods (PyObject *, void *); PyObject *gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw); +struct objfile *objectfile_object_to_objfile (PyObject *self); PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch); @@ -552,6 +557,8 @@ int gdbpy_initialize_commands (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_symbols (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +int gdbpy_initialize_minsymbols (void) + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_symtabs (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_blocks (void) diff --git a/gdb/python/python.c b/gdb/python/python.c index 348405e205..8d5ab0f649 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1684,6 +1684,7 @@ do_start_initialization () || gdbpy_initialize_record () < 0 || gdbpy_initialize_btrace () < 0 || gdbpy_initialize_symbols () < 0 + || gdbpy_initialize_minsymbols () < 0 || gdbpy_initialize_symtabs () < 0 || gdbpy_initialize_blocks () < 0 || gdbpy_initialize_functions () < 0 @@ -1984,6 +1985,10 @@ a boolean indicating if name is a field of the current implied argument\n\ METH_VARARGS | METH_KEYWORDS, "lookup_global_symbol (name [, domain]) -> symbol\n\ Return the symbol corresponding to the given name (or None)." }, +{ "lookup_minimal_symbol", (PyCFunction) gdbpy_lookup_minimal_symbol, + METH_VARARGS | METH_KEYWORDS, + "lookup_minimal_symbol (name, [sfile, [objfile]]) -> minsym\n\ +Return the symbol corresponding to the given name (or None)." }, { "lookup_objfile", (PyCFunction) gdbpy_lookup_objfile, METH_VARARGS | METH_KEYWORDS, diff --git a/gdb/testsuite/gdb.python/py-minsymbol.c b/gdb/testsuite/gdb.python/py-minsymbol.c new file mode 100644 index 0000000000..e33ee2041f --- /dev/null +++ b/gdb/testsuite/gdb.python/py-minsymbol.c @@ -0,0 +1,38 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2018 Free Software Foundation, Inc. + + 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 . */ + +/* So we have a data section */ +const char foo[] = "somestring"; + +asm("\ +.section .text\n\ +.global text_msym\n\ +text_msym:\n\ + .byte 0\n\ +.section .data\n\ +.globl data_msym\n\ +data_msym:\n\ + .asciz \"minsym text\"\n\ +data_msym2:\n\ + .asciz \"minsym2 text\"\n\ +"); + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.python/py-minsymbol.exp b/gdb/testsuite/gdb.python/py-minsymbol.exp new file mode 100644 index 0000000000..f765358719 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-minsymbol.exp @@ -0,0 +1,69 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. + +# 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 . + +# This file is part of the GDB testsuite. It tests the mechanism +# exposing values to Python. + +load_lib gdb-python.exp + +standard_testfile + +if {[prepare_for_testing $testfile.exp $testfile $srcfile nodebug]} { + return -1 +} + +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +# Test looking up missing value +gdb_test "python print (gdb.lookup_minimal_symbol('xyz'))" "None" "lookup missing symbol" + +# Test handling of invalid arguments +gdb_test "python print (gdb.lookup_minimal_symbol(None))" ".*TypeError: argument 1 must be str(ing)?, not None.*" "lookup_minimal_symbol name arg None" +gdb_test "python print (gdb.lookup_minimal_symbol('text_msym', None).name)" "text_msym" "lookup_minimal_symbol sfile arg None" +gdb_test "python print (gdb.lookup_minimal_symbol('text_msym', objfile=None).name)" "text_msym" "lookup_minimal_symbol objfile arg None" + +# Test looking up a minimal symbol of text type +gdb_test "print text_msym" " = \{\} 0x\[0-9a-f\]* " "locate text_msym with print" +gdb_py_test_silent_cmd "python x = gdb.lookup_minimal_symbol('text_msym')" "Lookup text_msym" 1 +gdb_test "python print (x.name)" "text_msym" "get text minsym name" +gdb_test "python print (x.linkage_name)" "text_msym" "get text minsym linkage_name" +# Using asm() ends up inventing a compiler-dependent filename +gdb_test "python print (x.filename)" ".*" "get text minsym filename" +gdb_test "python print (x.print_name)" "text_msym" "get text minsym print_name" +gdb_test "python print (x.section_name)" ".text" "get text minsym section" +gdb_test "python print (x.value())" "0x\[0-9a-f\]*.*" "get text minsym value" +gdb_test "python print (x.value().type)" "void \\(\\*\\)\\(\\)" "get text minsym value type" + +# Test looking up a minimal symbol of data type +gdb_test "print (void *)data_msym" "0x\[0-9a-f\]*.*" "locate data_msym with print" +gdb_py_test_silent_cmd "python x = gdb.lookup_minimal_symbol('data_msym')" "Lookup data_msym" 1 +gdb_test "python print (x.name)" "data_msym" "get data minsym name" +gdb_test "python print (x.linkage_name)" "data_msym" "get data minsym linkage_name" +# Using asm() ends up inventing a compiler-dependent filename +gdb_test "python print (x.filename)" ".*" "get data minsym filename" +gdb_test "python print (x.print_name)" "data_msym" "get data minsym print_name" +gdb_test "python print (x.section_name)" ".data" "get data minsym section" +gdb_test "python print (x.value())" "0x\[0-9a-f\]*.*" "get data minsym value" + +gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'foobar.c'))" "None" "Lookup local data_msym2 in foobar.c src" +gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'py-minsymbol.c').name)" "data_msym2" "Lookup local data_msym2 in py-minsymbol.c src" +gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'foobar/py-minsymbol.c').name)" "data_msym2" "Lookup local data_msym2 in py-minsymbol.c src" +gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'py-minsymbol'))" "None" "Lookup local data_msym2 in py-minsymbol.c src using substring" +gdb_test "python print(gdb.lookup_minimal_symbol('data_msym', 'foobar.c').name)" "data_msym" "Lookup global data_msym in foobar.c src" + +gdb_unload +gdb_test "python print (x.is_valid())" "False" "Test symbol non-validity" +gdb_test_no_output "python a = None" "Test symbol destructor" --------------1461ED06460D45853EBA08CC--