This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PING][PATCH][gdb/python] Add interface to access minimal_symbols
- From: Tom de Vries <tdevries at suse dot de>
- To: Simon Marchi <simon dot marchi at ericsson dot com>, gdb-patches at sourceware dot org, Phil Muldoon <pmuldoon at redhat dot com>, Tom Tromey <tom at tromey dot com>
- Date: Mon, 26 Nov 2018 12:16:57 +0100
- Subject: [PING][PATCH][gdb/python] Add interface to access minimal_symbols
- References: <20181004211115.GA31056@delia> <39c4336d-c749-6f79-5a29-0b764fc4935e@ericsson.com> <211c4746-389a-93b7-faf9-c8f9b6245541@suse.de>
On 31-10-18 17:59, Tom de Vries wrote:
> 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 <jeffm@suse.com>
>>> Tom de Vries <tdevries@suse.de>
>>>
>>> * 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
>>
>> <gdb.MinSymbol name=%s>
>>
>> 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:
> ...
> <gdb.MinSymbol name=%s filename=%s objfile=%s>
> ...
> 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.
>
Ping.
OK for trunk?
Thanks,
- Tom
> 0001-gdb-python-Add-interface-to-access-minimal_symbols.patch
>
> [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 <jeffm@suse.com>
> Tom de Vries <tdevries@suse.de>
>
> * 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 <http://www.gnu.org/licenses/>. */
> +
> +#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 ("<gdb.MinSymbol name=%s filename=%s"
> + " objfile=%s>",
> + MSYMBOL_LINKAGE_NAME (minsym),
> + minsym->filename,
> + objfile_filename (objfile));
> +
> + return PyString_FromFormat ("<gdb.MinSymbol name=%s objfile=%s>",
> + 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<char> 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 <http://www.gnu.org/licenses/>. */
> +
> +/* 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 <http://www.gnu.org/licenses/>.
> +
> +# 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" " = \{<text variable, no debug info>\} 0x\[0-9a-f\]* <text_msym>" "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"
>