gdb/python: Introduce gdb.lookup_static_symbols
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 15 Oct 2019 15:18:26 +0000 (16:18 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Sun, 10 Nov 2019 21:35:32 +0000 (21:35 +0000)
If gdb.lookup_static_symbol is going to return a single symbol then it
makes sense (I think) for it to return a context sensitive choice of
symbol, that is the global static symbol that would be visible to the
program at that point.

However, if the user of the python API wants to instead get a
consistent set of global static symbols, no matter where they stop,
then they have to instead consider all global static symbols with a
given name - there could be many.  That is what this new API function
offers, it returns a list (possibly empty) of all global static
symbols matching a given name (and optionally a given symbol domain).

gdb/ChangeLog:

* python/py-symbol.c (gdbpy_lookup_static_symbols): New
function.
* python/python-internal.h (gdbpy_lookup_static_symbols):
Declare new function.
* python/python.c (python_GdbMethods): Add
gdb.lookup_static_symbols method.
* NEWS: Mention gdb.lookup_static_symbols.

gdb/testsuite/ChangeLog:

* gdb.python/py-symbol.exp: Add test for
gdb.lookup_static_symbols.

gdb/doc/ChangeLog:

* python.texi (Symbols In Python): Add documentation for
gdb.lookup_static_symbols.

Change-Id: I1153b0ae5bcbc43b3dcf139043c7a48bf791e1a3

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/python.texi
gdb/python/py-symbol.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-symbol.exp

index ca0c0c366dcb1ec78dc2f2e1ea69d1bd3720d28c..dd280ec5cc48007340b07d71a929b5a14fad6c62 100644 (file)
@@ -1,3 +1,13 @@
+2019-11-10  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * python/py-symbol.c (gdbpy_lookup_static_symbols): New
+       function.
+       * python/python-internal.h (gdbpy_lookup_static_symbols):
+       Declare new function.
+       * python/python.c (python_GdbMethods): Add
+       gdb.lookup_static_symbols method.
+       * NEWS: Mention gdb.lookup_static_symbols.
+
 2019-11-10  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * python/py-symbol.c (gdbpy_lookup_static_symbol): Lookup in
index dc631794c093b7bfb5a10d4c58426a099e69c4ae..96ea6667878bdb968f0ced9c3bbe1953923ac373 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -77,6 +77,9 @@
   ** The new function gdb.lookup_static_symbol can be used to look up
      symbols with static linkage.
 
+  ** The new function gdb.lookup_static_symbols can be used to look up
+     all static symbols with static linkage.
+
   ** gdb.Objfile has new methods 'lookup_global_symbol' and
      'lookup_static_symbol' to lookup a symbol from this objfile only.
 
index 6db17b9c8ebb6bc0e16fe0a8073c6fbcca95c93c..fec0ebd8a1126a51009d6f7ca09e5ad571ff7fa6 100644 (file)
@@ -1,3 +1,8 @@
+2019-11-10  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * python.texi (Symbols In Python): Add documentation for
+       gdb.lookup_static_symbols.
+
 2019-11-10  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * python.texi (Symbols In Python): Extend documentation for
index 9e227deba905566be1bafe479c84ff4b43d5a1f3..c9f84d8299a11665094823330aa649cf37ca0c54 100644 (file)
@@ -4883,6 +4883,41 @@ search all object files in the order they appear in the debug
 information.
 @end defun
 
+@findex gdb.lookup_global_symbol
+@defun gdb.lookup_global_symbol (name @r{[}, domain@r{]})
+This function searches for a global symbol by name.
+The search scope can be restricted to by the domain argument.
+
+@var{name} is the name of the symbol.  It must be a string.
+The optional @var{domain} argument restricts the search to the domain type.
+The @var{domain} argument must be a domain constant defined in the @code{gdb}
+module and described later in this chapter.
+
+The result is a @code{gdb.Symbol} object or @code{None} if the symbol
+is not found.
+@end defun
+
+@findex gdb.lookup_static_symbols
+@defun gdb.lookup_static_symbols (name @r{[}, domain@r{]})
+Similar to @code{gdb.lookup_static_symbol}, this function searches for
+global symbols with static linkage by name, and optionally restricted
+by the domain argument.  However, this function returns a list of all
+matching symbols found, not just the first one.
+
+@var{name} is the name of the symbol.  It must be a string.
+The optional @var{domain} argument restricts the search to the domain type.
+The @var{domain} argument must be a domain constant defined in the @code{gdb}
+module and described later in this chapter.
+
+The result is a list of @code{gdb.Symbol} objects which could be empty
+if no matching symbols were found.
+
+Note that this function will not find function-scoped static variables. To look
+up such variables, iterate over the variables of the function's
+@code{gdb.Block} and check that @code{block.addr_class} is
+@code{gdb.SYMBOL_LOC_STATIC}.
+@end defun
+
 A @code{gdb.Symbol} object has the following attributes:
 
 @defvar Symbol.type
index 4c88877bcbed5306f4d735b39cec579e20e742c4..647c54b0a5b2799b2f11451e876e6566161ed7d9 100644 (file)
@@ -23,6 +23,7 @@
 #include "symtab.h"
 #include "python-internal.h"
 #include "objfiles.h"
+#include "symfile.h"
 
 typedef struct sympy_symbol_object {
   PyObject_HEAD
@@ -534,6 +535,66 @@ gdbpy_lookup_static_symbol (PyObject *self, PyObject *args, PyObject *kw)
   return sym_obj;
 }
 
+/* Implementation of
+   gdb.lookup_static_symbols (name [, domain]) -> symbol list.
+
+   Returns a list of all static symbols matching NAME in DOMAIN.  */
+
+PyObject *
+gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
+{
+  const char *name;
+  int domain = VAR_DOMAIN;
+  static const char *keywords[] = { "name", "domain", NULL };
+
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &name,
+                                       &domain))
+    return NULL;
+
+  gdbpy_ref<> return_list (PyList_New (0));
+  if (return_list == NULL)
+    return NULL;
+
+  try
+    {
+      /* Expand any symtabs that contain potentially matching symbols.  */
+      lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
+      expand_symtabs_matching (NULL, lookup_name, NULL, NULL, ALL_DOMAIN);
+
+      for (objfile *objfile : current_program_space->objfiles ())
+       {
+         for (compunit_symtab *cust : objfile->compunits ())
+           {
+             const struct blockvector *bv;
+             const struct block *block;
+
+             bv = COMPUNIT_BLOCKVECTOR (cust);
+             block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+
+             if (block != nullptr)
+               {
+                 symbol *symbol = lookup_symbol_in_static_block
+                   (name, block, (domain_enum) domain).symbol;
+
+                 if (symbol != nullptr)
+                   {
+                     PyObject *sym_obj
+                       = symbol_to_symbol_object (symbol);
+                     if (PyList_Append (return_list.get (), sym_obj) == -1)
+                       return NULL;
+                   }
+               }
+           }
+       }
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  return return_list.release ();
+}
+
 /* This function is called when an objfile is about to be freed.
    Invalidate the symbol as further actions on the symbol would result
    in bad data.  All access to obj->symbol should be gated by
index c5578430cfff9d596d542db91184634747cae7be..703c60032c0d31fe69fddeeedb4295702edf0f8d 100644 (file)
@@ -426,6 +426,8 @@ PyObject *gdbpy_lookup_global_symbol (PyObject *self, PyObject *args,
                                      PyObject *kw);
 PyObject *gdbpy_lookup_static_symbol (PyObject *self, PyObject *args,
                                      PyObject *kw);
+PyObject *gdbpy_lookup_static_symbols (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);
index ddf0e72d26f797b1b67d33b5d3b6eea797dc98a3..f94214e1b24933d3aa2cd0c582ab3cf41b239d37 100644 (file)
@@ -1994,6 +1994,10 @@ Return the symbol corresponding to the given name (or None)." },
     METH_VARARGS | METH_KEYWORDS,
     "lookup_static_symbol (name [, domain]) -> symbol\n\
 Return the static-linkage symbol corresponding to the given name (or None)." },
+  { "lookup_static_symbols", (PyCFunction) gdbpy_lookup_static_symbols,
+    METH_VARARGS | METH_KEYWORDS,
+    "lookup_static_symbols (name [, domain]) -> symbol\n\
+Return a list of all static-linkage symbols corresponding to the given name." },
 
   { "lookup_objfile", (PyCFunction) gdbpy_lookup_objfile,
     METH_VARARGS | METH_KEYWORDS,
index e170b7e7badb04513cf9cf84023e5bf7d2c7114a..9c69443bd784e03e15bafc7230c1322a1f298881 100644 (file)
@@ -1,3 +1,8 @@
+2019-11-10  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.python/py-symbol.exp: Add test for
+       gdb.lookup_static_symbols.
+
 2019-11-10  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.python/py-symbol.c: Declare and call function from new
index 61960075565b6de37422b2e9bb9ee17bd2fc0dec..ea41297f54f89911100d6bbccc408673f915c718 100644 (file)
@@ -29,6 +29,15 @@ if {[prepare_for_testing "failed to prepare" $testfile \
 # Skip all tests if Python scripting is not enabled.
 if { [skip_python_tests] } { continue }
 
+# Check that we find all static symbols before the inferior has
+# started, at which point some of the symtabs might not have been
+# expanded.
+gdb_test "python print (len (gdb.lookup_static_symbols ('rr')))" \
+    "2" "print (len (gdb.lookup_static_symbols ('rr')))"
+
+# Restart so we don't have expanded symtabs after the previous test.
+clean_restart ${binfile}
+
 # Test looking up a global symbol before we runto_main as this is the
 # point where we don't have a current frame, and we don't want to
 # require one.
@@ -108,6 +117,10 @@ gdb_breakpoint "function_in_other_file"
 gdb_continue_to_breakpoint "function_in_other_file"
 gdb_test "python print (gdb.lookup_static_symbol ('rr').value ())" "99" \
     "print value of rr from other file"
+gdb_test "python print (gdb.lookup_static_symbols ('rr')\[0\].value ())" "99" \
+    "print value of gdb.lookup_static_symbols ('rr')\[0\], from the other file"
+gdb_test "python print (gdb.lookup_static_symbols ('rr')\[1\].value ())" "42" \
+    "print value of gdb.lookup_static_symbols ('rr')\[1\], from the other file"
 
 # Now continue back to the first source file.
 set linenum [gdb_get_line_number "Break at end."]
@@ -119,6 +132,10 @@ gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
 # static symbol from the second source file.
 gdb_test "python print (gdb.lookup_static_symbol ('rr').value ())" "42" \
     "print value of rr from main file"
+gdb_test "python print (gdb.lookup_static_symbols ('rr')\[0\].value ())" "99" \
+    "print value of gdb.lookup_static_symbols ('rr')\[0\], from the main file"
+gdb_test "python print (gdb.lookup_static_symbols ('rr')\[1\].value ())" "42" \
+    "print value of gdb.lookup_static_symbols ('rr')\[1\], from the main file"
 
 # Test is_variable attribute.
 gdb_py_test_silent_cmd "python a = gdb.lookup_symbol(\'a\')" "Get variable a" 0