New python function gdb.lookup_objfile.

gdb/ChangeLog:

	* NEWS: Mention gdb.lookup_objfile.
	* python/python.c (GdbMethods): Add lookup_objfile.
	* python/python-internal.h (gdbpy_lookup_objfile): Declare.
	* python/py-objfile.c: #include "symtab.h".
	(objfpy_build_id_ok, objfpy_build_id_matches): New functions.
	(objfpy_lookup_objfile_by_name): New function.
	(objfpy_lookup_objfile_by_build_id): New function.
	(gdbpy_lookup_objfile): New function.

gdb/doc/ChangeLog:

	* python.texi (Objfiles In Python): Document gdb.lookup_objfile.

gdb/testsuite/ChangeLog:

	* lib/gdb-python.exp (get_python_valueof): New function.
	* gdb.python/py-objfile.exp: Add tests for gdb.lookup_objfile.
This commit is contained in:
Doug Evans 2014-12-12 09:48:13 -08:00
parent f161c17134
commit 6dddd6a574
10 changed files with 237 additions and 1 deletions

View File

@ -1,3 +1,14 @@
2014-12-12 Doug Evans <dje@google.com>
* NEWS: Mention gdb.lookup_objfile.
* python/python.c (GdbMethods): Add lookup_objfile.
* python/python-internal.h (gdbpy_lookup_objfile): Declare.
* python/py-objfile.c: #include "symtab.h".
(objfpy_build_id_ok, objfpy_build_id_matches): New functions.
(objfpy_lookup_objfile_by_name): New function.
(objfpy_lookup_objfile_by_build_id): New function.
(gdbpy_lookup_objfile): New function.
2014-12-12 Maciej W. Rozycki <macro@codesourcery.com>
* mips-tdep.h (MSYMBOL_TARGET_FLAG_MIPS16): New macro.

View File

@ -28,6 +28,7 @@
** A new event "gdb.clear_objfiles" has been added, triggered when
selecting a new file to debug.
** You can now add attributes to gdb.Objfile and gdb.Progspace objects.
** New function gdb.lookup_objfile.
* New Python-based convenience functions:

View File

@ -1,3 +1,7 @@
2014-12-12 Doug Evans <dje@google.com>
* python.texi (Objfiles In Python): Document gdb.lookup_objfile.
2014-12-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* gdb.texinfo: Document "maint print user-registers".

View File

@ -3488,6 +3488,27 @@ Return a sequence of all the objfiles current known to @value{GDBN}.
@xref{Objfiles In Python}.
@end defun
@findex gdb.lookup_objfile
@defun gdb.lookup_objfile (name @r{[}, by_build_id{]})
Look up @var{name}, a file name or build ID, in the list of objfiles
for the current program space (@pxref{Progspaces In Python}).
If the objfile is not found throw the Python @code{ValueError} exception.
If @var{name} is a relative file name, then it will match any
source file name with the same trailing components. For example, if
@var{name} is @samp{gcc/expr.c}, then it will match source file
name of @file{/build/trunk/gcc/expr.c}, but not
@file{/build/trunk/libcpp/expr.c} or @file{/build/trunk/gcc/x-expr.c}.
If @var{by_build_id} is provided and is @code{True} then @var{name}
is the build ID of the objfile. Otherwise, @var{name} is a file name.
This is supported only on some operating systems, notably those which use
the ELF format for binary files and the @sc{gnu} Binutils. For more details
about this feature, see the description of the @option{--build-id}
command-line option in @ref{Options, , Command Line Options, ld.info,
The GNU Linker}.
@end defun
Each objfile is represented by an instance of the @code{gdb.Objfile}
class.

View File

@ -24,6 +24,7 @@
#include "language.h"
#include "build-id.h"
#include "elf-bfd.h"
#include "symtab.h"
typedef struct
{
@ -384,6 +385,147 @@ objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
}
/* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
Return non-zero if STRING is a potentially valid build id. */
static int
objfpy_build_id_ok (const char *string)
{
size_t i, n = strlen (string);
if (n % 2 != 0)
return 0;
for (i = 0; i < n; ++i)
{
if (!isxdigit (string[i]))
return 0;
}
return 1;
}
/* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
Returns non-zero if BUILD_ID matches STRING.
It is assumed that objfpy_build_id_ok (string) returns TRUE. */
static int
objfpy_build_id_matches (const struct elf_build_id *build_id,
const char *string)
{
size_t i;
if (strlen (string) != 2 * build_id->size)
return 0;
for (i = 0; i < build_id->size; ++i)
{
char c1 = string[i * 2], c2 = string[i * 2 + 1];
int byte = (host_hex_value (c1) << 4) | host_hex_value (c2);
if (byte != build_id->data[i])
return 0;
}
return 1;
}
/* Subroutine of gdbpy_lookup_objfile to simplify it.
Look up an objfile by its file name. */
static struct objfile *
objfpy_lookup_objfile_by_name (const char *name)
{
struct objfile *objfile;
ALL_OBJFILES (objfile)
{
if ((objfile->flags & OBJF_NOT_FILENAME) != 0)
continue;
/* Don't return separate debug files. */
if (objfile->separate_debug_objfile_backlink != NULL)
continue;
if (compare_filenames_for_search (objfile_name (objfile), name))
return objfile;
}
return NULL;
}
/* Subroutine of gdbpy_lookup_objfile to simplify it.
Look up an objfile by its build id. */
static struct objfile *
objfpy_lookup_objfile_by_build_id (const char *build_id)
{
struct objfile *objfile;
ALL_OBJFILES (objfile)
{
const struct elf_build_id *obfd_build_id;
if (objfile->obfd == NULL)
continue;
/* Don't return separate debug files. */
if (objfile->separate_debug_objfile_backlink != NULL)
continue;
obfd_build_id = build_id_bfd_get (objfile->obfd);
if (obfd_build_id == NULL)
continue;
if (objfpy_build_id_matches (obfd_build_id, build_id))
return objfile;
}
return NULL;
}
/* Implementation of gdb.lookup_objfile. */
PyObject *
gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
{
static char *keywords[] = { "name", "by_build_id", NULL };
const char *name;
PyObject *by_build_id_obj = NULL;
int by_build_id;
struct objfile *objfile;
if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords,
&name, &PyBool_Type, &by_build_id_obj))
return NULL;
by_build_id = 0;
if (by_build_id_obj != NULL)
{
int cmp = PyObject_IsTrue (by_build_id_obj);
if (cmp < 0)
return NULL;
by_build_id = cmp;
}
if (by_build_id)
{
if (!objfpy_build_id_ok (name))
{
PyErr_SetString (PyExc_TypeError, _("Not a valid build id."));
return NULL;
}
objfile = objfpy_lookup_objfile_by_build_id (name);
}
else
objfile = objfpy_lookup_objfile_by_name (name);
if (objfile != NULL)
{
PyObject *result = objfile_to_objfile_object (objfile);
Py_XINCREF (result);
return result;
}
PyErr_SetString (PyExc_ValueError, _("Objfile not found."));
return NULL;
}
/* Clear the OBJFILE pointer in an Objfile object and remove the

View File

@ -393,6 +393,7 @@ PyObject *objfile_to_objfile_object (struct objfile *)
PyObject *objfpy_get_printers (PyObject *, void *);
PyObject *objfpy_get_frame_filters (PyObject *, void *);
PyObject *objfpy_get_xmethods (PyObject *, void *);
PyObject *gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw);
PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);

View File

@ -1956,6 +1956,14 @@ 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_objfile", (PyCFunction) gdbpy_lookup_objfile,
METH_VARARGS | METH_KEYWORDS,
"lookup_objfile (name, [by_build_id]) -> objfile\n\
Look up the specified objfile.\n\
If by_build_id is True, the objfile is looked up by using name\n\
as its build id." },
{ "block_for_pc", gdbpy_block_for_pc, METH_VARARGS,
"Return the block containing the given pc value, or None." },
{ "solib_name", gdbpy_solib_name, METH_VARARGS,

View File

@ -1,3 +1,8 @@
2014-12-12 Doug Evans <dje@google.com>
* lib/gdb-python.exp (get_python_valueof): New function.
* gdb.python/py-objfile.exp: Add tests for gdb.lookup_objfile.
2014-12-12 Andreas Arnez <arnez@linux.vnet.ibm.com>
* gdb.base/completion.exp: Add test for completion of "info

View File

@ -32,23 +32,39 @@ if ![runto_main] then {
return 0
}
set python_error_text "Error while executing Python code\\."
gdb_py_test_silent_cmd "python sym = gdb.lookup_symbol(\"some_var\")" \
"Find a symbol in objfile" 1
gdb_py_test_silent_cmd "python objfile = sym\[0\].symtab.objfile" \
"Get backing object file" 1
gdb_test "python print (objfile.filename)" ".*py-objfile.*" \
gdb_test "python print (objfile.filename)" "${testfile}" \
"Get objfile file name"
gdb_test "python print (gdb.lookup_objfile (\"${testfile}\").filename)" \
"${testfile}"
gdb_test "python print (gdb.lookup_objfile (\"junk\"))" \
"Objfile not found\\.\r\n${python_error_text}"
set binfile_build_id [get_build_id $binfile]
if [string compare $binfile_build_id ""] {
verbose -log "binfile_build_id = $binfile_build_id"
gdb_test "python print (objfile.build_id)" "$binfile_build_id" \
"Get objfile build id"
gdb_test "python print (gdb.lookup_objfile (\"$binfile_build_id\", by_build_id=True).filename)" \
"${testfile}"
} else {
unsupported "build-id is not supported by the compiler"
}
# Other lookup_objfile_by_build_id tests we can do, even if compiler doesn't
# support them.
gdb_test "python print (gdb.lookup_objfile (\"foo\", by_build_id=True))" \
"Not a valid build id\\.\r\n${python_error_text}"
gdb_test "python print (gdb.lookup_objfile (\"1234abcdef\", by_build_id=True))" \
"Objfile not found\\.\r\n${python_error_text}"
gdb_test "python print (objfile.progspace)" "<gdb\.Progspace object at .*>" \
"Get objfile program space"
gdb_test "python print (objfile.is_valid())" "True" \
@ -93,3 +109,9 @@ gdb_test "python print (sep_objfile.owner.filename)" "${testfile}2" \
gdb_test "p main" "= {int \\(\\)} $hex <main>" \
"print main with debug info"
# Separate debug files are not findable.
if { [get_python_valueof "sep_objfile.build_id" "None"] != "None" } {
gdb_test "python print (gdb.lookup_objfile (sep_objfile.build_id, by_build_id=True))" \
"Objfile not found\\.\r\n${python_error_text}"
}

View File

@ -45,3 +45,24 @@ proc gdb_py_test_multiple { name args } {
}
return 0
}
# Return the result of python expression EXPR.
# DEFAULT is returned if there's an error.
# This is modelled after get_integer_valueof.
proc get_python_valueof { exp default } {
global gdb_prompt
set test "get python valueof \"${exp}\""
set val ${default}
gdb_test_multiple "python print (\"valueof: %s\" % (${exp}))" "$test" {
-re "valueof: (\[^\r\n\]*)\[\r\n\]*$gdb_prompt $" {
set val $expect_out(1,string)
pass "$test ($val)"
}
timeout {
fail "$test (timeout)"
}
}
return ${val}
}