]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Finish .debug_types support in libdw and readelf.
authorRoland McGrath <roland@redhat.com>
Mon, 21 Jun 2010 00:55:50 +0000 (17:55 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 21 Jun 2010 00:55:50 +0000 (17:55 -0700)
NEWS
libdw/ChangeLog
libdw/dwarf_end.c
libdw/dwarf_nextcu.c
libdw/dwarf_offdie.c
libdw/libdw.h
libdw/libdw.map
libdw/libdwP.h
libdw/libdw_findcu.c
src/ChangeLog
src/readelf.c

diff --git a/NEWS b/NEWS
index 01a33db94fee7252dfba8a636b38bb6123123583..6237f5cb1aefb6987b5f1f81d64f0466ef6ac5fc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,13 +1,13 @@
 Version 0.148:
 
-libdw: Accept DWARF 4 formats.
+libdw: Accept DWARF 4 format: new functions dwarf_next_unit, dwarf_offdie_types.
        New functions dwarf_lineisa, dwarf_linediscriminator, dwarf_lineop_index.
        New function dwarf_cfi_validate_fde.
 
 libdwfl: Fixes in core-file handling, support cores from PIEs.
         When working from build IDs, don't open a named file that mismatches.
 
-readelf: Handle some DWARF 4 format bits.
+readelf: Handle DWARF 4 formats.
 
 Version 0.147:
 
index e446b507efb5b1e2459a67a02f6f30583d3c2d8a..34c7ba314f1e9ce57faf9a0558311ee40f3bfe9e 100644 (file)
@@ -1,5 +1,16 @@
 2010-06-20  Roland McGrath  <roland@redhat.com>
 
+       * libdw_findcu.c (__libdw_findcu): Take new flag argument,
+       to search TUs instead of CUs.
+       * libdwP.h: Update decl.
+       (struct Dwarf): New member tu_tree.
+       * dwarf_end.c (dwarf_end): Clean up tu_tree.
+       * dwarf_offdie.c (do_offdie): New function, broken out of ...
+       (dwarf_offdie): ... here.
+       (dwarf_offdie_types): New function.
+       * libdw.h: Declare it.
+       * libdw.map (ELFUTILS_0.148): Add it.
+
        * libdwP.h (CUDIE): Use cu_data.
        * dwarf_formblock.c: Likewise.
        * dwarf_formref_die.c: Likewise.
index 80dac7b7952ca39a2a7ac305c0a09ec0fce09851..ec10542e5c11f3a8e180abddfaa126bd06b78260 100644 (file)
@@ -92,6 +92,7 @@ dwarf_end (dwarf)
         allocated separately, but the abbreviation hash tables need
         to be handled.  */
       tdestroy (dwarf->cu_tree, cu_free);
+      tdestroy (dwarf->tu_tree, cu_free);
 
       struct libdw_memblock *memp = dwarf->mem_tail;
       /* The first block is allocated together with the Dwarf object.  */
index 288ee95e25c9f775029f875d67110334523198df..2e8f4d79107a9c77939921efc1f30cf51bf4f178 100644 (file)
@@ -63,7 +63,7 @@ dwarf_next_unit (dwarf, off, next_off, header_sizep, versionp, abbrev_offsetp,
      Dwarf_Off off;
      Dwarf_Off *next_off;
      size_t *header_sizep;
-     uint16_t *versionp;
+     Dwarf_Half *versionp;
      Dwarf_Off *abbrev_offsetp;
      uint8_t *address_sizep;
      uint8_t *offset_sizep;
index a9886f2c8193f1d700247414a7df51fa2a72b438..925fe512b482326e4d38dc24fe04bfa6cacabadc 100644 (file)
@@ -1,5 +1,5 @@
 /* Return DIE at given offset.
-   Copyright (C) 2002, 2003, 2005 Red Hat, Inc.
+   Copyright (C) 2002-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
 #include "libdwP.h"
 
 
-Dwarf_Die *
-dwarf_offdie (dbg, offset, result)
-     Dwarf *dbg;
-     Dwarf_Off offset;
-     Dwarf_Die *result;
+static Dwarf_Die *
+do_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result, bool debug_types)
 {
   if (dbg == NULL)
     return NULL;
 
-  if (offset >= dbg->sectiondata[IDX_debug_info]->d_size)
+  Elf_Data *const data = dbg->sectiondata[debug_types ? IDX_debug_types
+                                         : IDX_debug_info];
+  if (offset >= data->d_size)
     {
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return NULL;
@@ -75,10 +74,10 @@ dwarf_offdie (dbg, offset, result)
      determined any of the information.  */
   memset (result, '\0', sizeof (Dwarf_Die));
 
-  result->addr = (char *) dbg->sectiondata[IDX_debug_info]->d_buf + offset;
+  result->addr = (char *) data->d_buf + offset;
 
   /* Get the CU.  */
-  result->cu = __libdw_findcu (dbg, offset);
+  result->cu = __libdw_findcu (dbg, offset, debug_types);
   if (result->cu == NULL)
     {
       /* This should never happen.  The input file is malformed.  */
@@ -88,4 +87,23 @@ dwarf_offdie (dbg, offset, result)
 
   return result;
 }
+
+
+Dwarf_Die *
+dwarf_offdie (dbg, offset, result)
+     Dwarf *dbg;
+     Dwarf_Off offset;
+     Dwarf_Die *result;
+{
+  return do_offdie (dbg, offset, result, false);
+}
 INTDEF(dwarf_offdie)
+
+Dwarf_Die *
+dwarf_offdie_types (dbg, offset, result)
+     Dwarf *dbg;
+     Dwarf_Off offset;
+     Dwarf_Die *result;
+{
+  return do_offdie (dbg, offset, result, true);
+}
index d244d919ffa425256748a69f6a1c47f064ab74cf..d3e7a5abe028c6e40fafb91ac802f8201462e54e 100644 (file)
@@ -298,7 +298,7 @@ extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
    null, this reads a type unit from the .debug_types section; otherwise
    this reads a CU from the .debug_info section.  */
 extern int dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
-                           size_t *header_sizep, uint16_t *versionp,
+                           size_t *header_sizep, Dwarf_Half *versionp,
                            Dwarf_Off *abbrev_offsetp,
                            uint8_t *address_sizep, uint8_t *offset_sizep,
                            uint64_t *type_signaturep, Dwarf_Off *type_offsetp)
@@ -346,10 +346,15 @@ extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf);
 extern int dwarf_cfi_end (Dwarf_CFI *cache);
 
 
-/* Return DIE at given offset.  */
+/* Return DIE at given offset in .debug_types section.  */
 extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset,
                                Dwarf_Die *result) __nonnull_attribute__ (3);
 
+/* Return DIE at given offset in .debug_types section.  */
+extern Dwarf_Die *dwarf_offdie_types (Dwarf *dbg, Dwarf_Off offset,
+                                     Dwarf_Die *result)
+     __nonnull_attribute__ (3);
+
 /* Return offset of DIE.  */
 extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die);
 
index 9cf8cd388b7dd880fea4138eb9a634adbda820b1..954fff67d922edfe9065a0acc0a8daab0c25f00e 100644 (file)
@@ -247,4 +247,5 @@ ELFUTILS_0.148 {
     dwarf_lineop_index;
 
     dwarf_next_unit;
+    dwarf_offdie_types;
 } ELFUTILS_0.146;
index 558f961c9b8fde95ebfc5336f9696be1fe951762..bb0ae1d119979a80ed17dfb296ade3db0d90b765 100644 (file)
@@ -171,9 +171,10 @@ struct Dwarf
   void *cu_tree;
   Dwarf_Off next_cu_offset;
 
-  /* Hash table for .debug_types type units.  */
-  Dwarf_Sig8_Hash sig8_hash;
+  /* Search tree and sig8 hash table for .debug_types type units.  */
+  void *tu_tree;
   Dwarf_Off next_tu_offset;
+  Dwarf_Sig8_Hash sig8_hash;
 
   /* Address ranges.  */
   Dwarf_Aranges *aranges;
@@ -389,7 +390,7 @@ extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
      __nonnull_attribute__ (1) internal_function;
 
 /* Find CU for given offset.  */
-extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset)
+extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu)
      __nonnull_attribute__ (1) internal_function;
 
 /* Return tag of given DIE.  */
index 7e0b35685ed71e5b401bcf0c354f7cf9b5341a0d..8e5f9e9b1285ad6293cb44d91076549af501e20a 100644 (file)
@@ -136,17 +136,22 @@ findcu_cb (const void *arg1, const void *arg2)
 }
 
 struct Dwarf_CU *
-__libdw_findcu (dbg, start)
+__libdw_findcu (dbg, start, debug_types)
      Dwarf *dbg;
      Dwarf_Off start;
+     bool debug_types;
 {
+  void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree;
+  Dwarf_Off *next_offset
+    = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
+
   /* Maybe we already know that CU.  */
   struct Dwarf_CU fake = { .start = start, .end = 0 };
-  struct Dwarf_CU **found = tfind (&fake, &dbg->cu_tree, findcu_cb);
+  struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb);
   if (found != NULL)
     return *found;
 
-  if (start < dbg->next_cu_offset)
+  if (start < *next_offset)
     {
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return NULL;
@@ -155,22 +160,22 @@ __libdw_findcu (dbg, start)
   /* No.  Then read more CUs.  */
   while (1)
     {
-      Dwarf_Off oldoff = dbg->next_cu_offset;
-      struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, false);
+      Dwarf_Off oldoff = *next_offset;
+      struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, debug_types);
       if (newp == NULL)
        return NULL;
 
       /* Add the new entry to the search tree.  */
-      if (tsearch (newp, &dbg->cu_tree, findcu_cb) == NULL)
+      if (tsearch (newp, tree, findcu_cb) == NULL)
        {
          /* Something went wrong.  Undo the operation.  */
-         dbg->next_cu_offset = oldoff;
+         *next_offset = oldoff;
          __libdw_seterrno (DWARF_E_NOMEM);
          return NULL;
        }
 
       /* Is this the one we are looking for?  */
-      if (start < dbg->next_cu_offset)
+      if (start < *next_offset)
        // XXX Match exact offset.
        return newp;
     }
index 72d34a8fa0bfb4e38ee1534dc451a5cc0a5b8af0..59e8b8bcfee9e6af006f98efba385f0bf9323db9 100644 (file)
@@ -1,5 +1,11 @@
 2010-06-20  Roland McGrath  <roland@redhat.com>
 
+       * readelf.c (print_debug_units): New function, broken out of ...
+       (print_debug_info_section): ... here.  Call it.
+       (print_debug_types_section): New function.
+       (enum section_e): Add section_types alias for section_info.
+       (print_debug): Add types to the sections table.
+
        * readelf.c (print_debug_frame_section): Handle version 4 format.
 
        * readelf.c (print_debug_line_section): Handle version 4 format.
index 2215e8613438da8b8e1c98c25bc3bbad421d0f1f..f5be7f14d5205b36b9384efb139d1584c605ed71 100644 (file)
@@ -180,7 +180,8 @@ static enum section_e
   section_abbrev = 1,          /* .debug_abbrev  */
   section_aranges = 2,         /* .debug_aranges  */
   section_frame = 4,           /* .debug_frame or .eh_frame & al.  */
-  section_info = 8,            /* .debug_info  */
+  section_info = 8,            /* .debug_info, .debug_types  */
+  section_types = section_info,
   section_line = 16,           /* .debug_line  */
   section_loc = 32,            /* .debug_loc  */
   section_pubnames = 64,       /* .debug_pubnames  */
@@ -5385,17 +5386,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
   return DWARF_CB_OK;
 }
 
-
 static void
-print_debug_info_section (Dwfl_Module *dwflmod,
-                         Ebl *ebl __attribute__ ((unused)),
-                         GElf_Ehdr *ehdr __attribute__ ((unused)),
-                         Elf_Scn *scn,
-                         GElf_Shdr *shdr, Dwarf *dbg)
+print_debug_units (Dwfl_Module *dwflmod,
+                  Ebl *ebl __attribute__ ((unused)),
+                  GElf_Ehdr *ehdr __attribute__ ((unused)),
+                  Elf_Scn *scn,
+                  GElf_Shdr *shdr, Dwarf *dbg,
+                  bool debug_types)
 {
+  const char *secname = debug_types ? ".debug_types" : ".debug_info";
+
   printf (gettext ("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
-         elf_ndxscn (scn), ".debug_info", (uint64_t) shdr->sh_offset);
+         elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
 
   /* If the section is empty we don't have to do anything.  */
   if (shdr->sh_size == 0)
@@ -5408,20 +5411,34 @@ print_debug_info_section (Dwfl_Module *dwflmod,
 
   /* New compilation unit.  */
   size_t cuhl;
-  //Dwarf_Half version;
+  Dwarf_Half version;
   Dwarf_Off abbroffset;
   uint8_t addrsize;
   uint8_t offsize;
   Dwarf_Off nextcu;
+  uint64_t typesig;
+  Dwarf_Off typeoff;
  next_cu:
-  if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
-                   &offsize) != 0)
+  if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
+                      &abbroffset, &addrsize, &offsize,
+                      debug_types ? &typesig : NULL,
+                      debug_types ? &typeoff : NULL) != 0)
     goto do_return;
 
-  printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
-                  " Version: %" PRIu16 ", Abbreviation section offset: %"
-                  PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
-         (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
+  if (debug_types)
+    printf (gettext (" Type unit at offset %" PRIu64 ":\n"
+                    " Version: %" PRIu16 ", Abbreviation section offset: %"
+                    PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8
+                    "\n Type signature: %#" PRIx64
+                    ", Type offset: %" PRIu64 "\n"),
+           (uint64_t) offset, version, abbroffset, addrsize, offsize,
+           typesig, (uint64_t) typeoff);
+  else
+    printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
+                    " Version: %" PRIu16 ", Abbreviation section offset: %"
+                    PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8
+                    "\n"),
+           (uint64_t) offset, version, abbroffset, addrsize, offsize);
 
 
   struct attrcb_args args =
@@ -5437,11 +5454,12 @@ print_debug_info_section (Dwfl_Module *dwflmod,
 
   int level = 0;
 
-  if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
+  if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
+               (dbg, offset, &dies[level]) == NULL))
     {
       error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
                            " in section '%s': %s"),
-            (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
+            (uint64_t) offset, secname, dwarf_errmsg (-1));
       goto do_return;
     }
 
@@ -5460,7 +5478,7 @@ print_debug_info_section (Dwfl_Module *dwflmod,
        {
          error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
                                " in section '%s': %s"),
-                (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
+                (uint64_t) offset, secname, dwarf_errmsg (-1));
          goto do_return;
        }
 
@@ -5511,6 +5529,20 @@ print_debug_info_section (Dwfl_Module *dwflmod,
   free (dies);
 }
 
+static void
+print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+                         Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
+}
+
+static void
+print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+                          Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
+}
+
 
 static void
 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
@@ -6642,6 +6674,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
              NEW_SECTION (aranges),
              NEW_SECTION (frame),
              NEW_SECTION (info),
+             NEW_SECTION (types),
              NEW_SECTION (line),
              NEW_SECTION (loc),
              NEW_SECTION (pubnames),