]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: Add DW_MACRO constants and DW_MACRO_GNU compatibility defines.
authorMark Wielaard <mark@klomp.org>
Wed, 26 Jul 2017 21:02:18 +0000 (23:02 +0200)
committerMark Wielaard <mark@klomp.org>
Wed, 2 Aug 2017 11:51:52 +0000 (13:51 +0200)
Accept version 5 .debug_macro format, which is identical to the GNU
version 4 format. No real support yet for the new supplementary object
file (sup) and indirect string references (strx).  GCC doesn't generate
them yet. readelf does recognize them, but doesn't try to decode them.
dwarf_getmacros currently rejects the new formats.

Signed-off-by: Mark Wielaard <mark@klomp.org>
ChangeLog
NEWS
libdw/ChangeLog
libdw/dwarf.h
libdw/dwarf_getmacros.c
src/ChangeLog
src/readelf.c
tests/ChangeLog
tests/dwarf-getmacros.c

index b7efc847b9b0f835093fe5fc3263cbc952b03ce8..8748ab86dbc5d7ef3f6ae927a8fea2c3d6978f7b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+       * NEWS: Mention dwarf_getmacros handling version 5 .debug_macro.
+
 2017-07-26  Mark Wielaard  <mark@klomp.org>
 
        * NEWS: Mention dwarf_peel_type DWARF5 tags improvement.
diff --git a/NEWS b/NEWS
index 054ac95a4a030dd911e47799997c6605e1705e33..5c2d8add59ab169e0e5184857f723431a5cacefd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,11 @@
 Version 0.170
 
 libdw: Added new DWARF5 attribute, tag, character encoding, language code,
-       calling convention and defaulted member function constants to dwarf.h.
+       calling convention, defaulted member function and macro constants
+       to dwarf.h.
        New function dwarf_default_lower_bound.
        dwarf_peel_type now handles DWARF5 immutable, packed and shared tags.
+       dwarf_getmacros now handles DWARF5 .debug_macro sections.
 
 strip: Add -R, --remove-section=SECTION and --keep-section=SECTION.
 
index d0b3f4ca8e846746070c126734d659f7a249c595..6533eb5019d65e084dddd7c7cea8b1377e6417e7 100644 (file)
@@ -1,3 +1,10 @@
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+       * dwarf.h: Add DW_MACRO_* and compat defines for DW_MACRO_GNU_*.
+       * dwarf_getmacros.c (get_table_for_offset): Accept either version
+       4 or 5. Use DW_MACRO names instead of DW_MACRO_GNU names.
+       (read_macros): Use table version for fake_cu.
+
 2017-07-26  Mark Wielaard  <mark@klomp.org>
 
        * dwarf_peel_type.c (dwarf_peel_type): Handle DW_TAG_immutable_type,
index 82a68f26cc56d6616b1212a11daf72e1d64d25bc..902d26176255bf5c1f7ac1c9f4e6a2531960bd92 100644 (file)
@@ -780,20 +780,38 @@ enum
   };
 
 
-/* DWARF debug_macro type encodings.  GNU/DWARF5 extension.  */
+/* DWARF debug_macro type encodings.  */
 enum
   {
-    DW_MACRO_GNU_define = 0x01,
-    DW_MACRO_GNU_undef = 0x02,
-    DW_MACRO_GNU_start_file = 0x03,
-    DW_MACRO_GNU_end_file = 0x04,
-    DW_MACRO_GNU_define_indirect = 0x05,
-    DW_MACRO_GNU_undef_indirect = 0x06,
-    DW_MACRO_GNU_transparent_include = 0x07,
-    DW_MACRO_GNU_lo_user = 0xe0,
-    DW_MACRO_GNU_hi_user = 0xff
+    DW_MACRO_define = 0x01,
+    DW_MACRO_undef = 0x02,
+    DW_MACRO_start_file = 0x03,
+    DW_MACRO_end_file = 0x04,
+    DW_MACRO_define_strp = 0x05,
+    DW_MACRO_undef_strp = 0x06,
+    DW_MACRO_import = 0x07,
+    DW_MACRO_define_sup = 0x08,
+    DW_MACRO_undef_sup = 0x09,
+    DW_MACRO_import_sup = 0x0a,
+    DW_MACRO_define_strx = 0x0b,
+    DW_MACRO_undef_strx = 0x0c,
+    DW_MACRO_lo_user = 0xe0,
+    DW_MACRO_hi_user = 0xff
   };
 
+/* Old GNU extension names for DWARF5 debug_macro type encodings.
+   There are no equivalents for the supplementary object file (sup)
+   and indirect string references (strx).  */
+#define DW_MACRO_GNU_define             DW_MACRO_define
+#define DW_MACRO_GNU_undef              DW_MACRO_undef
+#define DW_MACRO_GNU_start_file                 DW_MACRO_start_file
+#define DW_MACRO_GNU_end_file           DW_MACRO_end_file
+#define DW_MACRO_GNU_define_indirect    DW_MACRO_define_strp
+#define DW_MACRO_GNU_undef_indirect     DW_MACRO_undef_strp
+#define DW_MACRO_GNU_transparent_include DW_MACRO_import
+#define DW_MACRO_GNU_lo_user            DW_MACRO_lo_user
+#define DW_MACRO_GNU_hi_user            DW_MACRO_hi_user
+
 
 /* DWARF call frame instruction encodings.  */
 enum
index eb5050853905fff01e7415e650c99f6d2b639d81..db6582b6e36cc12f37f4181170f612c3fbc3ed0b 100644 (file)
@@ -158,7 +158,7 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
     }
 
   uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
-  if (version != 4)
+  if (version != 4 && version != 5)
     {
       __libdw_seterrno (DWARF_E_INVALID_VERSION);
       return NULL;
@@ -198,15 +198,17 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
 
   Dwarf_Macro_Op_Proto op_protos[255] =
     {
-      [DW_MACRO_GNU_define - 1] = p_udata_str,
-      [DW_MACRO_GNU_undef - 1] = p_udata_str,
-      [DW_MACRO_GNU_define_indirect - 1] = p_udata_strp,
-      [DW_MACRO_GNU_undef_indirect - 1] = p_udata_strp,
-      [DW_MACRO_GNU_start_file - 1] = p_udata_udata,
-      [DW_MACRO_GNU_end_file - 1] = p_none,
-      [DW_MACRO_GNU_transparent_include - 1] = p_secoffset,
-      /* N.B. DW_MACRO_undef_indirectx, DW_MACRO_define_indirectx
-        should be added when 130313.1 is supported.  */
+      [DW_MACRO_define - 1] = p_udata_str,
+      [DW_MACRO_undef - 1] = p_udata_str,
+      [DW_MACRO_define_strp - 1] = p_udata_strp,
+      [DW_MACRO_undef_strp - 1] = p_udata_strp,
+      [DW_MACRO_start_file - 1] = p_udata_udata,
+      [DW_MACRO_end_file - 1] = p_none,
+      [DW_MACRO_import - 1] = p_secoffset,
+      /* When adding support for DWARF5 supplementary object files and
+        indirect string tables also add support for DW_MACRO_define_sup,
+        DW_MACRO_undef_sup, DW_MACRO_import_sup, DW_MACRO_define_strx
+        and DW_MACRO_undef_strx.  */
     };
 
   if ((flags & 0x4) != 0)
@@ -354,10 +356,11 @@ read_macros (Dwarf *dbg, int sec_index,
 
       /* A fake CU with bare minimum data to fool dwarf_formX into
         doing the right thing with the attributes that we put out.
-        We arbitrarily pretend it's version 4.  */
+        We pretend it is the same version as the actual table.
+        Version 4 for the old GNU extension, version 5 for DWARF5.  */
       Dwarf_CU fake_cu = {
        .dbg = dbg,
-       .version = 4,
+       .version = table->version,
        .offset_size = table->is_64bit ? 8 : 4,
        .startp = (void *) startp + offset,
        .endp = (void *) endp,
index 3ebc7044860ac1fd6e67e35e56afc1b846187bf1..54ba767e97d53bd9b65c2850666bef0fe82f30ea 100644 (file)
@@ -1,3 +1,10 @@
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+       * readelf.c (print_debug_macro_section): Accept either version 4 or
+       version 5. Use DW_MACRO names instead of DW_MACRO_GNU names. Add
+       minimal support for DW_MACRO_define_sup, DW_MACRO_undef_sup,
+       DW_MACRO_import_sup, DW_MACRO_define_strx and DW_MACRO_undef_strx.
+
 2017-07-26  Mark Wielaard  <mark@klomp.org>
 
        * readelf.c (dwarf_defaulted_string): New function.
index 5e1685df1fc69adf48d708a4817938aeda7d8127..73be474bab75adcc9abfe6979008b33aa30235f2 100644 (file)
@@ -7394,7 +7394,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
       // 5 when it gets standardized.
-      if (vers != 4)
+      if (vers != 4 && vers != 5)
        {
          printf (gettext ("  unknown version, cannot parse section\n"));
          return;
@@ -7418,7 +7418,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
                  line_offset);
        }
 
-      const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
+      const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user];
       memset (vendor, 0, sizeof vendor);
       if (flag & 0x04)
        {
@@ -7435,12 +7435,12 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
                goto invalid_data;
              unsigned int opcode = *readp++;
              printf (gettext ("    [%" PRIx8 "]"), opcode);
-             if (opcode < DW_MACRO_GNU_lo_user
-                 || opcode > DW_MACRO_GNU_hi_user)
+             if (opcode < DW_MACRO_lo_user
+                 || opcode > DW_MACRO_hi_user)
                goto invalid_data;
              // Record the start of description for this vendor opcode.
              // uleb128 nr args, 1 byte per arg form.
-             vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
+             vendor[opcode - DW_MACRO_lo_user] = readp;
              if (readp + 1 > readendp)
                goto invalid_data;
              unsigned int args = *readp++;
@@ -7493,7 +7493,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
           switch (opcode)
             {
-            case DW_MACRO_GNU_start_file:
+            case DW_MACRO_start_file:
              get_uleb128 (u128, readp, readendp);
              if (readp >= readendp)
                goto invalid_data;
@@ -7523,12 +7523,12 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
              ++level;
              break;
 
-           case DW_MACRO_GNU_end_file:
+           case DW_MACRO_end_file:
              --level;
              printf ("%*send_file\n", level, "");
              break;
 
-           case DW_MACRO_GNU_define:
+           case DW_MACRO_define:
              get_uleb128 (u128, readp, readendp);
              endp = memchr (readp, '\0', readendp - readp);
              if (endp == NULL)
@@ -7538,7 +7538,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
              readp = endp + 1;
              break;
 
-           case DW_MACRO_GNU_undef:
+           case DW_MACRO_undef:
              get_uleb128 (u128, readp, readendp);
              endp = memchr (readp, '\0', readendp - readp);
              if (endp == NULL)
@@ -7548,7 +7548,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
              readp = endp + 1;
              break;
 
-           case DW_MACRO_GNU_define_indirect:
+           case DW_MACRO_define_strp:
              get_uleb128 (u128, readp, readendp);
              if (readp + offset_len > readendp)
                goto invalid_data;
@@ -7560,7 +7560,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
                      level, "", dwarf_getstring (dbg, off, NULL), u128);
              break;
 
-           case DW_MACRO_GNU_undef_indirect:
+           case DW_MACRO_undef_strp:
              get_uleb128 (u128, readp, readendp);
              if (readp + offset_len > readendp)
                goto invalid_data;
@@ -7572,7 +7572,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
                      level, "", dwarf_getstring (dbg, off, NULL), u128);
              break;
 
-           case DW_MACRO_GNU_transparent_include:
+           case DW_MACRO_import:
              if (readp + offset_len > readendp)
                goto invalid_data;
              if (offset_len == 8)
@@ -7583,15 +7583,78 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
                      level, "", off);
              break;
 
+           case DW_MACRO_define_sup:
+             get_uleb128 (u128, readp, readendp);
+             if (readp + offset_len > readendp)
+               goto invalid_data;
+             if (offset_len == 8)
+               off = read_8ubyte_unaligned_inc (dbg, readp);
+             else
+               off = read_4ubyte_unaligned_inc (dbg, readp);
+             // Needs support for reading from supplementary object file.
+             printf ("%*s#define <str-at-0x%" PRIx64 ">, line %u (sup)\n",
+                     level, "", off, u128);
+             break;
+
+           case DW_MACRO_undef_sup:
+             get_uleb128 (u128, readp, readendp);
+             if (readp + offset_len > readendp)
+               goto invalid_data;
+             if (offset_len == 8)
+               off = read_8ubyte_unaligned_inc (dbg, readp);
+             else
+               off = read_4ubyte_unaligned_inc (dbg, readp);
+             // Needs support for reading from supplementary object file.
+             printf ("%*s#undef <str-at-0x%" PRIx64 ">, line %u (sup)\n",
+                     level, "", off, u128);
+             break;
+
+           case DW_MACRO_import_sup:
+             if (readp + offset_len > readendp)
+               goto invalid_data;
+             if (offset_len == 8)
+               off = read_8ubyte_unaligned_inc (dbg, readp);
+             else
+               off = read_4ubyte_unaligned_inc (dbg, readp);
+             printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
+                     level, "", off);
+             break;
+
+           case DW_MACRO_define_strx:
+             get_uleb128 (u128, readp, readendp);
+             if (readp + offset_len > readendp)
+               goto invalid_data;
+             if (offset_len == 8)
+               off = read_8ubyte_unaligned_inc (dbg, readp);
+             else
+               off = read_4ubyte_unaligned_inc (dbg, readp);
+             // Needs support for reading indirect string offset table
+             printf ("%*s#define <str-at-0x%" PRIx64 ">, line %u (strx)\n",
+                     level, "", off, u128);
+             break;
+
+           case DW_MACRO_undef_strx:
+             get_uleb128 (u128, readp, readendp);
+             if (readp + offset_len > readendp)
+               goto invalid_data;
+             if (offset_len == 8)
+               off = read_8ubyte_unaligned_inc (dbg, readp);
+             else
+               off = read_4ubyte_unaligned_inc (dbg, readp);
+             // Needs support for reading indirect string offset table.
+             printf ("%*s#undef <str-at-0x%" PRIx64 ">, line %u (strx)\n",
+                     level, "", off, u128);
+             break;
+
            default:
              printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
-             if (opcode < DW_MACRO_GNU_lo_user
-                 || opcode > DW_MACRO_GNU_lo_user
-                 || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
+             if (opcode < DW_MACRO_lo_user
+                 || opcode > DW_MACRO_lo_user
+                 || vendor[opcode - DW_MACRO_lo_user] == NULL)
                goto invalid_data;
 
              const unsigned char *op_desc;
-             op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
+             op_desc = vendor[opcode - DW_MACRO_lo_user];
 
              // Just skip the arguments, we cannot really interpret them,
              // but print as much as we can.
index fa3f94ed407f25c5530026386c0a3ccd1c376988..04efdc815fa68c33db52069459bf1d88fb142f42 100644 (file)
@@ -1,5 +1,9 @@
 2017-07-26  Mark Wielaard  <mark@klomp.org>
 
+       * dwarf-getmacros.c (mac): Use DW_MACRO names instead of DW_MACRO_GNU.
+
+2016-10-27  Mark Wielaard  <mjw@redhat.com>
+
        * dwarf_default_lower_bound.c: New test.
        * Makefile.am (check_PROGRAMS): Add dwarf_default_lower_bound.
        (TESTS): Likewise.
index 92e093cad5c615b98a663b99b870cfc4adafe6ea..ac70248ddabb934c1331bcfe0e9303280fa094b4 100644 (file)
@@ -38,7 +38,7 @@ mac (Dwarf_Macro *macro, void *dbg)
   dwarf_macro_opcode (macro, &opcode);
   switch (opcode)
     {
-    case DW_MACRO_GNU_transparent_include:
+    case DW_MACRO_import:
       {
        Dwarf_Attribute at;
        int r = dwarf_macro_param (macro, 0, &at);
@@ -56,7 +56,7 @@ mac (Dwarf_Macro *macro, void *dbg)
        break;
       }
 
-    case DW_MACRO_GNU_start_file:
+    case DW_MACRO_start_file:
       {
        Dwarf_Files *files;
        size_t nfiles;
@@ -73,7 +73,7 @@ mac (Dwarf_Macro *macro, void *dbg)
        break;
       }
 
-    case DW_MACRO_GNU_end_file:
+    case DW_MACRO_end_file:
       {
        --level;
        printf ("%*s/file\n", level, "");
@@ -81,7 +81,7 @@ mac (Dwarf_Macro *macro, void *dbg)
       }
 
     case DW_MACINFO_define:
-    case DW_MACRO_GNU_define_indirect:
+    case DW_MACRO_define_strp:
       {
        const char *value;
        dwarf_macro_param2 (macro, NULL, &value);
@@ -90,7 +90,7 @@ mac (Dwarf_Macro *macro, void *dbg)
       }
 
     case DW_MACINFO_undef:
-    case DW_MACRO_GNU_undef_indirect:
+    case DW_MACRO_undef_strp:
       break;
 
     default: