From 7c50a93137df660f7b2d9d68c0db748a9cb7868f Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Thu, 4 Dec 2014 11:32:24 -0800 Subject: [PATCH] New python attribute gdb.Objfile.build_id. gdb/ChangeLog: * NEWS: Mention gdb.Objfile.build_id. * build-id.c (build_id_bfd_get): Make non-static. * build-id.h (build_id_bfd_get): Add declaration. * python/py-objfile.c: #include "build-id.h", "elf-bfd.h". (OBJFPY_REQUIRE_VALID): New macro. (objfpy_get_build_id): New function. (objfile_getset): Add "build_id". * utils.c (make_hex_string): New function. * utils.h (make_hex_string): Add declaration. gdb/doc/ChangeLog: * python.texi (Objfiles In Python): Document Objfile.build_id. gdb/testsuite/ChangeLog: * lib/gdb.exp (get_build_id): New function. (build_id_debug_filename_get): Rewrite to use it. * gdb.python/py-objfile.exp: Add test for objfile.build_id. --- gdb/ChangeLog | 12 +++++++ gdb/NEWS | 2 ++ gdb/build-id.c | 4 +-- gdb/build-id.h | 4 +++ gdb/doc/ChangeLog | 4 +++ gdb/doc/python.texi | 11 ++++++ gdb/python/py-objfile.c | 48 +++++++++++++++++++++++++ gdb/testsuite/ChangeLog | 6 ++++ gdb/testsuite/gdb.python/py-objfile.exp | 10 ++++++ gdb/testsuite/lib/gdb.exp | 23 ++++++++---- gdb/utils.c | 17 +++++++++ gdb/utils.h | 5 +++ 12 files changed, 138 insertions(+), 8 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 352d1076a3..e6da0b5d94 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2014-12-04 Doug Evans + + * NEWS: Mention gdb.Objfile.build_id. + * build-id.c (build_id_bfd_get): Make non-static. + * build-id.h (build_id_bfd_get): Add declaration. + * python/py-objfile.c: #include "build-id.h", "elf-bfd.h". + (OBJFPY_REQUIRE_VALID): New macro. + (objfpy_get_build_id): New function. + (objfile_getset): Add "build_id". + * utils.c (make_hex_string): New function. + * utils.h (make_hex_string): Add declaration. + 2014-12-04 Jan Kratochvil * block.c (block_lookup_symbol_primary): New function. diff --git a/gdb/NEWS b/gdb/NEWS index 7262502473..16ed91eb8c 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -21,6 +21,8 @@ ** New attribute 'producer' for gdb.Symtab objects. ** gdb.Objfile objects have a new attribute "progspace", which is the gdb.Progspace object of the containing program space. + ** gdb.Objfile objects have a new attribute "build_id", + which is the build ID generated when the file was built. ** 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. diff --git a/gdb/build-id.c b/gdb/build-id.c index 0f553cef29..5c1f415fd1 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -27,9 +27,9 @@ #include "objfiles.h" #include "filenames.h" -/* Locate NT_GNU_BUILD_ID from ABFD and return its content. */ +/* See build-id.h. */ -static const struct elf_build_id * +const struct elf_build_id * build_id_bfd_get (bfd *abfd) { if (!bfd_check_format (abfd, bfd_object) diff --git a/gdb/build-id.h b/gdb/build-id.h index ddd2645743..548ea5e630 100644 --- a/gdb/build-id.h +++ b/gdb/build-id.h @@ -20,6 +20,10 @@ #ifndef BUILD_ID_H #define BUILD_ID_H +/* Locate NT_GNU_BUILD_ID from ABFD and return its content. */ + +extern const struct elf_build_id *build_id_bfd_get (bfd *abfd); + /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value. Otherwise, issue a warning and return false. */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 08b49f50a0..7f36a311cd 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2014-12-04 Doug Evans + + * python.texi (Objfiles In Python): Document Objfile.build_id. + 2014-12-02 Nick Bull * python.texi (Events In Python): Document new events diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 63db2b2a3d..a9514100f4 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -3495,6 +3495,17 @@ class. The file name of the objfile as a string. @end defvar +@defvar Objfile.build_id +The build ID of the objfile as a string. +If the objfile does not have a build ID then the value is @code{None}. + +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 defvar + @defvar Objfile.progspace The containing program space of the objfile as a @code{gdb.Progspace} object. @xref{Progspaces In Python}. diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index c99de87e33..05a7c21ff4 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -22,6 +22,8 @@ #include "charset.h" #include "objfiles.h" #include "language.h" +#include "build-id.h" +#include "elf-bfd.h" typedef struct { @@ -51,9 +53,21 @@ static PyTypeObject objfile_object_type static const struct objfile_data *objfpy_objfile_data_key; +/* Require that OBJF be a valid objfile. */ +#define OBJFPY_REQUIRE_VALID(obj) \ + do { \ + if (!(obj)->objfile) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Objfile no longer exists.")); \ + return NULL; \ + } \ + } while (0) + /* An Objfile method which returns the objfile's file name, or None. */ + static PyObject * objfpy_get_filename (PyObject *self, void *closure) { @@ -66,6 +80,38 @@ objfpy_get_filename (PyObject *self, void *closure) Py_RETURN_NONE; } +/* An Objfile method which returns the objfile's build id, or None. */ + +static PyObject * +objfpy_get_build_id (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + struct objfile *objfile = obj->objfile; + const struct elf_build_id *build_id = NULL; + volatile struct gdb_exception except; + + OBJFPY_REQUIRE_VALID (obj); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + build_id = build_id_bfd_get (objfile->obfd); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (build_id != NULL) + { + char *hex_form = make_hex_string (build_id->data, build_id->size); + PyObject *result; + + result = PyString_Decode (hex_form, strlen (hex_form), + host_charset (), NULL); + xfree (hex_form); + return result; + } + + Py_RETURN_NONE; +} + /* An Objfile method which returns the objfile's progspace, or None. */ static PyObject * @@ -364,6 +410,8 @@ static PyGetSetDef objfile_getset[] = "The __dict__ for this objfile.", &objfile_object_type }, { "filename", objfpy_get_filename, NULL, "The objfile's filename, or None.", NULL }, + { "build_id", objfpy_get_build_id, NULL, + "The objfile's build id, or None.", NULL }, { "progspace", objfpy_get_progspace, NULL, "The objfile's progspace, or None.", NULL }, { "pretty_printers", objfpy_get_printers, objfpy_set_printers, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index f1584e03a0..b19a5c078d 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-12-04 Doug Evans + + * lib/gdb.exp (get_build_id): New function. + (build_id_debug_filename_get): Rewrite to use it. + * gdb.python/py-objfile.exp: Add test for objfile.build_id. + 2014-12-04 Maciej W. Rozycki * gdb.cp/expand-psymtabs-cxx.exp: Accept any address of diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp index 7bf41ed9d0..74384edde7 100644 --- a/gdb/testsuite/gdb.python/py-objfile.exp +++ b/gdb/testsuite/gdb.python/py-objfile.exp @@ -39,6 +39,16 @@ gdb_py_test_silent_cmd "python objfile = sym\[0\].symtab.objfile" \ gdb_test "python print (objfile.filename)" ".*py-objfile.*" \ "Get objfile file name" + +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" +} else { + unsupported "build-id is not supported by the compiler" +} + gdb_test "python print (objfile.progspace)" "" \ "Get objfile program space" gdb_test "python print (objfile.is_valid())" "True" \ diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 2c79bc1272..a29b6614e6 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -4330,14 +4330,14 @@ gdb_caching_proc gdb_has_argv0 { # foo.debug --> foo's debug info # foo --> like foo, but with a new .gnu_debuglink section pointing to foo.debug. -# Return the build-id hex string (usually 160 bits as 40 hex characters) -# converted to the form: .build-id/ab/cdef1234...89.debug -# Return "" if no build-id found. -proc build_id_debug_filename_get { exec } { - set tmp [standard_output_file "${exec}-tmp"] +# Fetch the build id from the file. +# Returns "" if there is none. + +proc get_build_id { filename } { + set tmp [standard_output_file "${filename}-tmp"] set objcopy_program [gdb_find_objcopy] - set result [catch "exec $objcopy_program -j .note.gnu.build-id -O binary $exec $tmp" output] + set result [catch "exec $objcopy_program -j .note.gnu.build-id -O binary $filename $tmp" output] verbose "result is $result" verbose "output is $output" if {$result == 1} { @@ -4355,6 +4355,17 @@ proc build_id_debug_filename_get { exec } { } # Convert it to hex. binary scan $data H* data + return $data +} + +# Return the build-id hex string (usually 160 bits as 40 hex characters) +# converted to the form: .build-id/ab/cdef1234...89.debug +# Return "" if no build-id found. +proc build_id_debug_filename_get { filename } { + set data [get_build_id $filename] + if { $data == "" } { + return "" + } regsub {^..} $data {\0/} data return ".build-id/${data}.debug" } diff --git a/gdb/utils.c b/gdb/utils.c index 1f5f4f4b6f..1ab183c2ce 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1112,6 +1112,23 @@ gdb_print_host_address (const void *addr, struct ui_file *stream) { fprintf_filtered (stream, "%s", host_address_to_string (addr)); } + +/* See utils.h. */ + +char * +make_hex_string (const gdb_byte *data, size_t length) +{ + char *result = xmalloc (length * 2 + 1); + char *p; + size_t i; + + p = result; + for (i = 0; i < length; ++i) + p += sprintf (p, "%02x", data[i]); + *p = '\0'; + return result; +} + /* A cleanup function that calls regfree. */ diff --git a/gdb/utils.h b/gdb/utils.h index 15680119f1..660b548ab5 100644 --- a/gdb/utils.h +++ b/gdb/utils.h @@ -369,4 +369,9 @@ extern void warn_cant_dump_core (const char *reason); extern void dump_core (void); +/* Return the hex string form of LENGTH bytes of DATA. + Space for the result is malloc'd, caller must free. */ + +extern char *make_hex_string (const gdb_byte *data, size_t length); + #endif /* UTILS_H */ -- 2.34.1