New python attribute gdb.Objfile.build_id.
authorDoug Evans <dje@google.com>
Thu, 4 Dec 2014 19:32:24 +0000 (11:32 -0800)
committerDoug Evans <dje@google.com>
Thu, 4 Dec 2014 19:32:24 +0000 (11:32 -0800)
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.

12 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/build-id.c
gdb/build-id.h
gdb/doc/ChangeLog
gdb/doc/python.texi
gdb/python/py-objfile.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-objfile.exp
gdb/testsuite/lib/gdb.exp
gdb/utils.c
gdb/utils.h

index 352d1076a3cc02ab808dba8580e75069c2af6426..e6da0b5d9437002310f13f22a0bb34a3cf356cdb 100644 (file)
@@ -1,3 +1,15 @@
+2014-12-04  Doug Evans  <dje@google.com>
+
+       * 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  <jan.kratochvil@redhat.com>
 
        * block.c (block_lookup_symbol_primary): New function.
index 7262502473288da6b6d1f8cfadcba3f05c5bc3b4..16ed91eb8c877a70ec7ab70ce15f7ac2ba28361d 100644 (file)
--- 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.
index 0f553cef29872c4531834103e4ae35a21b7d3513..5c1f415fd10b9153f362e7c7b2a500c24d65914d 100644 (file)
@@ -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)
index ddd2645743ee4aefd1fffd167326e26358fbdb9a..548ea5e63045ae269a8b359d9d111edc84355e67 100644 (file)
 #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.  */
 
index 08b49f50a028aae33fae46a12d87b5227078d431..7f36a311cd635d1e45b4ceff6712d11ec5fc93c2 100644 (file)
@@ -1,3 +1,7 @@
+2014-12-04  Doug Evans  <dje@google.com>
+
+       * python.texi (Objfiles In Python): Document Objfile.build_id.
+
 2014-12-02  Nick Bull  <nicholaspbull@gmail.com>
 
        * python.texi (Events In Python): Document new events
index 63db2b2a3dca62cb4de677dab40e80487b5268c1..a9514100f42043829694e59ff13020b8778e7b7a 100644 (file)
@@ -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}.
index c99de87e33d45ca45fe86ddd7b24e5e309e91faf..05a7c21ff406909a34036bf5693f8c5c0e30dc9b 100644 (file)
@@ -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)
+
 \f
 
 /* 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,
index f1584e03a090d06c5451eef2849466d56d49689b..b19a5c078d4206cca15526e4d6fcad3bf9f85ba8 100644 (file)
@@ -1,3 +1,9 @@
+2014-12-04  Doug Evans  <dje@google.com>
+
+       * 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  <macro@codesourcery.com>
 
        * gdb.cp/expand-psymtabs-cxx.exp: Accept any address of
index 7bf41ed9d07f95e4ab06a4b445fe2b1c1fbd34ad..74384edde7e396cfbe5c33998dede93440fabba9 100644 (file)
@@ -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)" "<gdb\.Progspace object at .*>" \
   "Get objfile program space"
 gdb_test "python print (objfile.is_valid())" "True" \
index 2c79bc12721d1e9b425a8624c404111604f51023..a29b6614e6c02be1c5e5d9c649d75ee787c489c4 100644 (file)
@@ -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"
 }
index 1f5f4f4b6f3df50f24333fb7c1d7d40657d07ed7..1ab183c2ce7f3c9adb2c2e679134648991c9773e 100644 (file)
@@ -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;
+}
+
 \f
 
 /* A cleanup function that calls regfree.  */
index 15680119f15f0f04ceb69d63043b61431b803754..660b548ab54c1dac5d8d721b2cad15dd33506d9b 100644 (file)
@@ -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 */