aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/NEWS1
-rw-r--r--gdb/doc/ChangeLog4
-rw-r--r--gdb/doc/python.texi21
-rw-r--r--gdb/python/py-objfile.c142
-rw-r--r--gdb/python/python-internal.h1
-rw-r--r--gdb/python/python.c8
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.python/py-objfile.exp24
-rw-r--r--gdb/testsuite/lib/gdb-python.exp21
10 files changed, 237 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a54e2c1..70d4629 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/NEWS b/gdb/NEWS
index a47dfbf..d2c5637 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -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:
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index b8152df..9b36c37 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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".
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index efd258d..234ce5c 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -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.
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index d90928b..e78ceba 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -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
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 716c0de..544fe93 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -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);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 1362bd2..b1d8283 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -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,
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index b21ac45..22f3ffc 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp
index f3a8a6c..5d3c084 100644
--- a/gdb/testsuite/gdb.python/py-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-objfile.exp
@@ -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}"
+}
diff --git a/gdb/testsuite/lib/gdb-python.exp b/gdb/testsuite/lib/gdb-python.exp
index d5e7928..eefff73 100644
--- a/gdb/testsuite/lib/gdb-python.exp
+++ b/gdb/testsuite/lib/gdb-python.exp
@@ -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}
+}