public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH][gdb/python] Add interface to access minimal_symbols
@ 2018-10-04 21:11 Tom de Vries
  2018-10-05  4:43 ` Simon Marchi
  2018-10-05  6:46 ` Eli Zaretskii
  0 siblings, 2 replies; 10+ messages in thread
From: Tom de Vries @ 2018-10-04 21:11 UTC (permalink / raw)
  To: gdb-patches

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

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);
+}
+
+\f
+
+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"

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-04 21:11 [PATCH][gdb/python] Add interface to access minimal_symbols Tom de Vries
@ 2018-10-05  4:43 ` Simon Marchi
  2018-10-31 16:59   ` Tom de Vries
  2018-11-29 22:12   ` Tom Tromey
  2018-10-05  6:46 ` Eli Zaretskii
  1 sibling, 2 replies; 10+ messages in thread
From: Simon Marchi @ 2018-10-05  4:43 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches, Phil Muldoon, Tom Tromey

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);
> +}
> +
> +\f
> +
> +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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-04 21:11 [PATCH][gdb/python] Add interface to access minimal_symbols Tom de Vries
  2018-10-05  4:43 ` Simon Marchi
@ 2018-10-05  6:46 ` Eli Zaretskii
  2018-10-31 17:02   ` Tom de Vries
  1 sibling, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2018-10-05  6:46 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gdb-patches

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-05  4:43 ` Simon Marchi
@ 2018-10-31 16:59   ` Tom de Vries
  2018-11-26 11:17     ` [PING][PATCH][gdb/python] " Tom de Vries
                       ` (2 more replies)
  2018-11-29 22:12   ` Tom Tromey
  1 sibling, 3 replies; 10+ messages in thread
From: Tom de Vries @ 2018-10-31 16:59 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches, Phil Muldoon, Tom Tromey

[-- Attachment #1: Type: text/plain, Size: 14622 bytes --]

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);
>> +}
>> +
>> +\f
>> +
>> +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.

Thanks,
- Tom

[-- Attachment #2: 0001-gdb-python-Add-interface-to-access-minimal_symbols.patch --]
[-- Type: text/x-patch, Size: 34958 bytes --]

[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);
+}
+
+\f
+
+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"

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-05  6:46 ` Eli Zaretskii
@ 2018-10-31 17:02   ` Tom de Vries
  0 siblings, 0 replies; 10+ messages in thread
From: Tom de Vries @ 2018-10-31 17:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PING][PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-31 16:59   ` Tom de Vries
@ 2018-11-26 11:17     ` Tom de Vries
  2018-11-26 21:31     ` [PATCH][gdb/python] " Simon Marchi
  2018-11-29 22:32     ` Tom Tromey
  2 siblings, 0 replies; 10+ messages in thread
From: Tom de Vries @ 2018-11-26 11:17 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches, Phil Muldoon, Tom Tromey

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"
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-31 16:59   ` Tom de Vries
  2018-11-26 11:17     ` [PING][PATCH][gdb/python] " Tom de Vries
@ 2018-11-26 21:31     ` Simon Marchi
  2018-11-27 18:10       ` Matt Rice
  2018-11-29 22:32     ` Tom Tromey
  2 siblings, 1 reply; 10+ messages in thread
From: Simon Marchi @ 2018-11-26 21:31 UTC (permalink / raw)
  To: Tom de Vries; +Cc: Simon Marchi, gdb-patches, Phil Muldoon, Tom Tromey

On 2018-10-31 12:59, Tom de Vries wrote:
> 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.

Thanks, that make sense.

The patch looks good to me, but since adding some new Python API is kind 
of a big deal (we are stuck with it after), I'd really like if Phil 
and/or Tom could give their opinions.  Especially since I remember Phil 
mentioning he had other plans for minimal symbols...

Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-11-26 21:31     ` [PATCH][gdb/python] " Simon Marchi
@ 2018-11-27 18:10       ` Matt Rice
  0 siblings, 0 replies; 10+ messages in thread
From: Matt Rice @ 2018-11-27 18:10 UTC (permalink / raw)
  To: Simon Marchi
  Cc: tdevries, Simon Marchi, gdb-patches, Phil Muldoon, Tom Tromey

On Mon, Nov 26, 2018 at 1:31 PM Simon Marchi <simon.marchi@polymtl.ca> wrote:
>
> On 2018-10-31 12:59, Tom de Vries wrote:
> > 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.
>
> Thanks, that make sense.
>
> The patch looks good to me, but since adding some new Python API is kind
> of a big deal (we are stuck with it after), I'd really like if Phil
> and/or Tom could give their opinions.  Especially since I remember Phil
> mentioning he had other plans for minimal symbols...

has been a long time since i've looked at the edge cases of minsym
filenames, and objfiles.
but I seem to recall the filename component being basically useless,
and the objfile is not necessarily correct,
and lacking the ODR/one definition rule, the name/filename/objfile is
not even necessarily unique.

perhaps a better uniqueness would be the address of the symbol?
i.e. even though the objfile may be wrong, the offset from the
previous objfile should still be unique
Anyhow if all of this is still the case, it gives me some pause that
exposing python seems a bit scary.
there were odd symbols in gdb associated with the wrong objfile coming
from libdecnumber,
of this sort last time saw it, or perhaps it was it the library linked
after libdecnumber?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-05  4:43 ` Simon Marchi
  2018-10-31 16:59   ` Tom de Vries
@ 2018-11-29 22:12   ` Tom Tromey
  1 sibling, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2018-11-29 22:12 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom de Vries, gdb-patches, Phil Muldoon, Tom Tromey

>>>>> "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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][gdb/python] Add interface to access minimal_symbols
  2018-10-31 16:59   ` Tom de Vries
  2018-11-26 11:17     ` [PING][PATCH][gdb/python] " Tom de Vries
  2018-11-26 21:31     ` [PATCH][gdb/python] " Simon Marchi
@ 2018-11-29 22:32     ` Tom Tromey
  2 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2018-11-29 22:32 UTC (permalink / raw)
  To: Tom de Vries; +Cc: Simon Marchi, gdb-patches, Phil Muldoon, Tom Tromey

>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:

Tom> This patch adds a new gdb.MinSymbol object to export the minimal_symbol
Tom> interface.

I hate to bikeshed the name to start with, but I'm going to anyway.  Why
the abbreviated name rather than gdb.MinimalSymbol?  Or alternatively
why not something less "gdb-ish", like gdb.LinkerSymbol?

Tom> +Typical symbols like functions, variables, etc are represented by
Tom> +@code{gdb.Symbol} objects in Python.  Some symbols are defined with less
Tom> +information associated with them, like linker script variables
Tom> +or assembly labels.  Python represents these minimal symbols in @value{GDBN}
Tom> +with the @code{gdb.MinSymbol} object.

I think this is mildly misleading and perhaps should also mention that
linker symbols will generally end up in here.

Tom> +@defvar MinSymbol.filename
Tom> +The file name of the source file where the minimal symbol is defined.

As mentioned elsewhere in the thread, I think this field is largely not
useful.  I feel like we once considered removing it from minsyms
entirely.  So, I tend to think this one should just be dropped, unless
you have some specific need for it (which would be interesting to hear
about).

Tom> +@defvar MinSymbol.section_name
Tom> +The name of the section in the object file containing this minimal symbol.

Are there platforms where sections do not have names?
What will happen to this on those?

Tom> +  return PyString_FromString (minsym->filename);

I suspect filename can be NULL here.
But see above.

Tom> +  if (section != NULL)
Tom> +    {
Tom> +      name = bfd_section_name (objfile->obfd, section->the_bfd_section);
Tom> +      if (name != NULL)
Tom> +	return PyString_FromString (name);
Tom> +    }
Tom> +
Tom> +  Py_RETURN_NONE;

Ok, I see the answer to my question here.  This should be documented.

Tom> +  type = builtin_type (minsym_gdbarch (self))->builtin_func_ptr;
Tom> +
Tom> +  if (minsym_type (self) == type)
Tom> +    Py_RETURN_TRUE;

This seems kind of roundabout to me.

Tom> +  type = builtin_type (minsym_gdbarch (self))->builtin_data_ptr;
Tom> +
Tom> +  if (minsym_type (self) == type)
Tom> +    Py_RETURN_TRUE;

Same here.

Tom> +  minsym_object *minsym_obj = (minsym_object *)self;

Space after the ")".

Tom> +static void
Tom> +set_symbol (minsym_object *obj, struct bound_minimal_symbol *bound)

I think a const reference for "bound" would be more natural here.

Tom> +static PyObject *
Tom> +bound_minsym_to_minsym_object (struct bound_minimal_symbol *bound)

Here too.

Tom> +  if (sfile_obj != NULL && sfile_obj != Py_None)
Tom> +    {
Tom> +      sfile_tmp = gdbpy_obj_to_string (sfile_obj);

If this returns NULL then this function should early-return as well.

Tom> +  if (bound_minsym.minsym != NULL)
Tom> +    msym_obj = bound_minsym_to_minsym_object (&bound_minsym);

If bound_minsym_to_minsym_object returns NULL, then an exception has
been set, so this function must return NULL.  But:

Tom> +  if (msym_obj != NULL)
Tom> +    return msym_obj;

... that isn't happening.

So the logic needs a bit of reordering here.

Tom> +/* Initialize gdb.MinSymbol.  Return -1 on error, 0 on success.  */
Tom> +
Tom> +int
Tom> +gdbpy_initialize_minsymbols (void)

Don't need the "void" here any more.

Tom> +/* Return struct objfile reference that is wrapped by the SELF object.  */
Tom> +
Tom> +struct objfile *
Tom> +objectfile_object_to_objfile (PyObject *self)

I think this should be named objfile_object_to_objfile instead.

Tom> +++ b/gdb/testsuite/gdb.python/py-minsymbol.exp

Some of the lines here are too long and can reasonably be split.

I think it would also make sense to check for the minsym for "main"
itself.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-11-29 22:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-04 21:11 [PATCH][gdb/python] Add interface to access minimal_symbols Tom de Vries
2018-10-05  4:43 ` Simon Marchi
2018-10-31 16:59   ` Tom de Vries
2018-11-26 11:17     ` [PING][PATCH][gdb/python] " Tom de Vries
2018-11-26 21:31     ` [PATCH][gdb/python] " Simon Marchi
2018-11-27 18:10       ` Matt Rice
2018-11-29 22:32     ` Tom Tromey
2018-11-29 22:12   ` Tom Tromey
2018-10-05  6:46 ` Eli Zaretskii
2018-10-31 17:02   ` Tom de Vries

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).