Patchwork [gdb/python] Add interface to access minimal_symbols

login
register
mail settings
Submitter Tom de Vries
Date Oct. 4, 2018, 9:11 p.m.
Message ID <20181004211115.GA31056@delia>
Download mbox | patch
Permalink /patch/29652/
State New
Headers show

Comments

Tom de Vries - Oct. 4, 2018, 9:11 p.m.
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

[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(+)
Simon Marchi - Oct. 5, 2018, 4:43 a.m.
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".
* Please make sure that all functions are documented (with an introductory comment).

> 
> [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.

> +
> +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])

?

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

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.

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?

> +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.

> +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.

> +  { "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.  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 :).

Simon
Eli Zaretskii - Oct. 5, 2018, 6:45 a.m.
> Date: Thu, 4 Oct 2018 23:11:17 +0200
> From: Tom de Vries <tdevries@suse.de>
> 
> [ 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.

Thanks.

> Build and reg-tested on x86_64-linux.
> 
> OK for trunk?

I have a couple of comments for the documentation part.

I think this warrants a NEWS entry.

> +@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

"gdb.Symbol" should be in @code.

> +@findex gdb.lookup_minimal_symbol
> +@defun gdb.lookup_minimal_symbol (name @r{[}, sfile@r{]}, objfile@r{[})

There's no need to use @findex for methods you introduce with @defun,
since the latter automatically creates an @findex entry.

> +This function searches for a minimal symbol by name.
> +The search scope can be restricted by the sfile and objfile arguments.
                                             ^^^^^     ^^^^^^^
Argument names in text should have the @var markup, like you did below:

> +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.

> +@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.

When you refer to other GDB features, it is generally a good idea to
have a hyperlink there.  In this case, I believe you refer to the
command "set print demangle", described in "Print Settings", so please
use @pxref or @xref to add a cross-reference there.

> +@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.

The last sentence sounds a bit mysterious to me: what are "filenames
used internally by the compiler"?  Maybe an example will clarify that.

> +@defvar MinSymbol.section
> +The name of the binary section containing this minimal symbol.

I would suggest to use "section in the object file"; "binary" might be
misinterpreted to mean that the section itself is binary.

> +@vindex MINSYMBOL_TYPE_SLOT_GOT_PLT
> +@item gdb.MINSYMBOL_TYPE_SLOT_GOT_PLT
> +This type represents GOT for .plt sections.

I don't believe we have "GOT" mentioned anywhere else in the manual,
so (1) please use @acronym{GOT}, and (2) please tell in the text what
this acronym stands for.

> +@vindex MINSYMBOL_TYPE_FILE_DATA
> +@item gdb.MINSYMBOL_TYPE_FILE_DATA
> +This type represents the static version of gdb.MINSYMBOL_TYPE_DATA.
> +
> +@vindex MINSYMBOL_TYPE_FILE_BSS
> +@item gdb.MINSYMBOL_TYPE_FILE_BSS
> +This type represents the static version of gdb.MINSYMBOL_TYPE_BSS.
> +@end vtable

The 2 "gdb.*" symbols above should be in @code.

The documentation part is approved with the above gotchas fixed.
Tom de Vries - Oct. 31, 2018, 5:02 p.m.
On 10/5/18 8:45 AM, Eli Zaretskii wrote:
>> Date: Thu, 4 Oct 2018 23:11:17 +0200
>> From: Tom de Vries <tdevries@suse.de>
>>
>> [ 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.
> 
> Thanks.
> 
>> Build and reg-tested on x86_64-linux.
>>
>> OK for trunk?
> 
> I have a couple of comments for the documentation part.
> 
> I think this warrants a NEWS entry.
> 

Added.

>> +@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
> 
> "gdb.Symbol" should be in @code.
> 

Done.

>> +@findex gdb.lookup_minimal_symbol
>> +@defun gdb.lookup_minimal_symbol (name @r{[}, sfile@r{]}, objfile@r{[})
> 
> There's no need to use @findex for methods you introduce with @defun,
> since the latter automatically creates an @findex entry.
> 

Removed.

>> +This function searches for a minimal symbol by name.
>> +The search scope can be restricted by the sfile and objfile arguments.
>                                              ^^^^^     ^^^^^^^
> Argument names in text should have the @var markup, like you did below:
> 

Done.

>> +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.
> 
>> +@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.
> 
> When you refer to other GDB features, it is generally a good idea to
> have a hyperlink there.  In this case, I believe you refer to the
> command "set print demangle", described in "Print Settings", so please
> use @pxref or @xref to add a cross-reference there.
> 

Done.

>> +@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.
> 
> The last sentence sounds a bit mysterious to me: what are "filenames
> used internally by the compiler"?  Maybe an example will clarify that.
> 

I've removed that bit.

>> +@defvar MinSymbol.section
>> +The name of the binary section containing this minimal symbol.
> 
> I would suggest to use "section in the object file"; "binary" might be
> misinterpreted to mean that the section itself is binary.
> 

Done.

>> +@vindex MINSYMBOL_TYPE_SLOT_GOT_PLT
>> +@item gdb.MINSYMBOL_TYPE_SLOT_GOT_PLT
>> +This type represents GOT for .plt sections.
> 
> I don't believe we have "GOT" mentioned anywhere else in the manual,
> so (1) please use @acronym{GOT}, and (2) please tell in the text what
> this acronym stands for.
> 

Done.

>> +@vindex MINSYMBOL_TYPE_FILE_DATA
>> +@item gdb.MINSYMBOL_TYPE_FILE_DATA
>> +This type represents the static version of gdb.MINSYMBOL_TYPE_DATA.
>> +
>> +@vindex MINSYMBOL_TYPE_FILE_BSS
>> +@item gdb.MINSYMBOL_TYPE_FILE_BSS
>> +This type represents the static version of gdb.MINSYMBOL_TYPE_BSS.
>> +@end vtable
> 
> The 2 "gdb.*" symbols above should be in @code.
> 

Done.

> The documentation part is approved with the above gotchas fixed.
> 

Retested and reposted at
https://sourceware.org/ml/gdb-patches/2018-10/msg00756.html .

Thanks,
- Tom
Tom Tromey - Nov. 29, 2018, 10:12 p.m.
>>>>> "Simon" == Simon Marchi <simon.marchi@ericsson.com> writes:

Simon> I think I have read (probably from Phil or Tom Tromey) that the intention was to
Simon> expose minsyms and full symbols using the same Symbol class, to avoid exposing
Simon> the fact that GDB represents symbols in different ways internally.  I don't know
Simon> if there was some concrete plans for that or if it was just at the idea stage.

I think various ideas were kicked around but nothing was really
committed to.  And, to my knowledge, nobody has really done any work in
this area.

The biggest fear, IMO, was that exposing either symbols or minimal
symbols to Python would lock us in to some undesirable API in the
future.  The basis for this fear is the (common?) belief that gdb's
internal symbol tables are not very good.  I suppose I've been hoping
for years that either somebody would finally clean things up, or that
I'd somehow get around to it.

Nowadays I tend to think we should push forward even with something that
isn't perfect.  While the worst case is pretty bad -- having to delete
some Python API and cause some chaos for users -- I imagine it won't
come to that.  And anyway Python is dynamic enough that one can usually
work around the problems.

Tom

Patch

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.
+
+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{[})
+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.
+
+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.
+
+@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 gdb.MINSYMBOL_TYPE_TEXT.
+
+@vindex MINSYMBOL_TYPE_FILE_DATA
+@item gdb.MINSYMBOL_TYPE_FILE_DATA
+This type represents the static version of gdb.MINSYMBOL_TYPE_DATA.
+
+@vindex MINSYMBOL_TYPE_FILE_BSS
+@item gdb.MINSYMBOL_TYPE_FILE_BSS
+This type represents the static version of gdb.MINSYMBOL_TYPE_BSS.
+@end vtable
+
 @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..44e19ddf2f
--- /dev/null
+++ b/gdb/python/py-minsymbol.c
@@ -0,0 +1,492 @@ 
+/* 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;
+}
+
+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->symbol 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)
+
+#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;
+
+static PyObject *
+msympy_str (PyObject *self)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return PyString_FromString (MSYMBOL_PRINT_NAME (minsym));
+}
+
+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));
+}
+
+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);
+}
+
+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));
+}
+
+static PyObject *
+msympy_get_print_name (PyObject *self, void *closure)
+{
+  struct minimal_symbol *minsym = NULL;
+
+  MSYMPY_REQUIRE_VALID (self, minsym);
+
+  return msympy_str (self);
+}
+
+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)
+    {
+      name = bfd_section_name (objfile->obfd, section->the_bfd_section);
+      if (name)
+	return PyString_FromString (name);
+    }
+
+  Py_RETURN_NONE;
+}
+
+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));
+}
+
+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;
+}
+
+static struct gdbarch *
+minsym_gdbarch (PyObject *minsym_obj)
+{
+  return get_objfile_arch (minsym_object_to_objfile (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;
+}
+
+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;
+}
+
+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);
+}
+
+static void
+set_symbol (minsym_object *obj, struct bound_minimal_symbol *bound)
+{
+  obj->bound = *bound;
+  obj->prev = NULL;
+  if (bound->objfile)
+    {
+      obj->next = (minsym_object *) objfile_data (bound->objfile,
+						  msympy_objfile_data_key);
+      if (obj->next)
+	obj->next->prev = obj;
+      set_objfile_data (bound->objfile, msympy_objfile_data_key, obj);
+    }
+  else
+    obj->next = NULL;
+}
+
+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)
+    set_symbol (msym_obj, bound);
+
+  return (PyObject *) msym_obj;
+}
+
+static void
+msympy_dealloc (PyObject *obj)
+{
+  minsym_object *msym_obj = (minsym_object *) obj;
+
+  if (msym_obj->prev)
+    msym_obj->prev->next = msym_obj->next;
+  else if (msym_obj->bound.objfile)
+    set_objfile_data (msym_obj->bound.objfile,
+		      msympy_objfile_data_key, msym_obj->next);
+  if (msym_obj->next)
+    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 && sfile_obj != Py_None)
+    {
+      sfile_tmp = gdbpy_obj_to_string (sfile_obj);
+      sfile = sfile_tmp.get ();
+    }
+
+  if (objfile_obj && objfile_obj != Py_None)
+    {
+      objfile = objfpy_object_to_objfile (objfile_obj);
+      if (!objfile)
+	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)
+    msym_obj = bound_minsym_to_minsym_object (&bound_minsym);
+
+  if (msym_obj)
+    return msym_obj;
+
+  Py_RETURN_NONE;
+}
+
+static void
+del_objfile_msymbols (struct objfile *objfile, void *datum)
+{
+  minsym_object *obj = (minsym_object *) datum;
+  while (obj)
+    {
+      minsym_object *next = obj->next;
+
+      obj->bound.minsym = NULL;
+      obj->bound.objfile = NULL;
+      obj->next = NULL;
+      obj->prev = NULL;
+
+      obj = next;
+    }
+}
+
+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", msympy_get_section, NULL,
+    "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*/
+  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*/
+  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..736027a7a7 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -417,6 +417,15 @@  objfpy_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+struct objfile *
+objfpy_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..35368f205d 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 *objfpy_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 8fbce78469..2fc57ae2bb 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..4ce111d306
--- /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..16bbaf64e1
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-minsymbol.exp
@@ -0,0 +1,67 @@ 
+# 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 debug]} {
+    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))" "text_msym" "lookup_minimal_symbol sfile arg None"
+gdb_test "python print (gdb.lookup_minimal_symbol('text_msym', objfile=None))" "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)" "text_msym" "lookup text min sym"
+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)" ".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)" ".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 data_msym2 in foobar.c src"
+gdb_test "python print(gdb.lookup_minimal_symbol('data_msym2', 'py-minsymbol.c'))" "data_msym2" "Lookup data_msym2 in py-minsymbol.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"