diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ca0c0c366d..dd280ec5cc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2019-11-10 Andrew Burgess + + * 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 * python/py-symbol.c (gdbpy_lookup_static_symbol): Lookup in diff --git a/gdb/NEWS b/gdb/NEWS index dc631794c0..96ea666787 100644 --- 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. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 6db17b9c8e..fec0ebd8a1 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2019-11-10 Andrew Burgess + + * python.texi (Symbols In Python): Add documentation for + gdb.lookup_static_symbols. + 2019-11-10 Andrew Burgess * python.texi (Symbols In Python): Extend documentation for diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 9e227deba9..c9f84d8299 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -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 diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c index 4c88877bcb..647c54b0a5 100644 --- a/gdb/python/py-symbol.c +++ b/gdb/python/py-symbol.c @@ -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 diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index c5578430cf..703c60032c 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -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); diff --git a/gdb/python/python.c b/gdb/python/python.c index ddf0e72d26..f94214e1b2 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -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, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e170b7e7ba..9c69443bd7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-11-10 Andrew Burgess + + * gdb.python/py-symbol.exp: Add test for + gdb.lookup_static_symbols. + 2019-11-10 Andrew Burgess * gdb.python/py-symbol.c: Declare and call function from new diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp index 6196007556..ea41297f54 100644 --- a/gdb/testsuite/gdb.python/py-symbol.exp +++ b/gdb/testsuite/gdb.python/py-symbol.exp @@ -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