From: Omar Sandoval <osan...@fb.com>

Dwarf_Macro_Op_Table::is_64bit conflates the address size and the offset
size: for .debug_macinfo, it is initialized based on the compilation
unit's address size, but for .debug_macro, it is initialized based on
the macro unit's offset size.  is_64bit is used to determine the address
size to pass to __libdw_getsrclines.  For a 64-bit architecture using
DWARF 5 with 32-bit offsets (the common case), this fails because
read_srclines checks that the given address size matches the address
size from the line number program header.

Fix it by splitting is_64bit into separate address_size and offset_size
members.

Fixes: fb90bf3f84b5 ("Support .debug_macro")
Signed-off-by: Omar Sandoval <osan...@fb.com>
---
 libdw/ChangeLog                 | 11 +++++++++++
 libdw/dwarf_getmacros.c         | 17 ++++++++++++++---
 libdw/dwarf_macro_getsrcfiles.c |  3 +--
 libdw/libdwP.h                  |  3 ++-
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 7528c093..d3f36cc8 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -7,6 +7,17 @@
        * dwarf_macro_param2.c (dwarf_macro_param2): Change form condition to
        switch statement and add DW_FORM_line_strp, DW_FORM_strp_sup,
        DW_FORM_strx, and DW_FORM_strx[1-4].
+       * dwarf_getmacros.c (get_macinfo_table): Replace assignment of
+       table->is_64bit with assignments of table->address_size and
+       table->offset_size.
+       (get_table_for_offset): Ditto.
+       (read_macros): Get fake CU offset_size from table->offset_size instead
+       of table->is_64bit.
+       * dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles): Get
+       address_size for __libdw_getsrclines from table->address_size instead
+       of table->is_64bit.
+       * libdwP.h (Dwarf_Macro_Op_Table): Replace is_64bit with address_size
+       and offset_size.
 
 2023-02-22  Mark Wielaard  <m...@klomp.org>
 
diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c
index fd929669..b7d98af4 100644
--- a/libdw/dwarf_getmacros.c
+++ b/libdw/dwarf_getmacros.c
@@ -134,7 +134,8 @@ get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, Dwarf_Die 
*cudie)
   table->offset = macoff;
   table->sec_index = IDX_debug_macinfo;
   table->line_offset = line_offset;
-  table->is_64bit = cudie->cu->address_size == 8;
+  table->address_size = cudie->cu->address_size;
+  table->offset_size = cudie->cu->offset_size;
   table->comp_dir = __libdw_getcompdir (cudie);
 
   return table;
@@ -182,6 +183,15 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
          return NULL;
     }
 
+  uint8_t address_size;
+  if (cudie != NULL)
+    address_size = cudie->cu->address_size;
+  else
+    {
+      char *ident = elf_getident (dbg->elf, NULL);
+      address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+    }
+
   /* """The macinfo entry types defined in this standard may, but
      might not, be described in the table""".
 
@@ -258,7 +268,8 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
     .line_offset = line_offset,
     .header_len = readp - startp,
     .version = version,
-    .is_64bit = is_64bit,
+    .address_size = address_size,
+    .offset_size = is_64bit ? 8 : 4,
 
     /* NULL if CUDIE is NULL or DW_AT_comp_dir is absent.  */
     .comp_dir = __libdw_getcompdir (cudie),
@@ -368,7 +379,7 @@ read_macros (Dwarf *dbg, int sec_index,
        .dbg = dbg,
        .sec_idx = sec_index,
        .version = table->version,
-       .offset_size = table->is_64bit ? 8 : 4,
+       .offset_size = table->offset_size,
        .str_off_base = str_offsets_base_off (dbg, (cudie != NULL
                                                    ? cudie->cu: NULL)),
        .startp = (void *) startp + offset,
diff --git a/libdw/dwarf_macro_getsrcfiles.c b/libdw/dwarf_macro_getsrcfiles.c
index 3b1794b1..4e8deeeb 100644
--- a/libdw/dwarf_macro_getsrcfiles.c
+++ b/libdw/dwarf_macro_getsrcfiles.c
@@ -72,8 +72,7 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro,
         will be broken.  */
 
       if (__libdw_getsrclines (dbg, line_offset, table->comp_dir,
-                              table->is_64bit ? 8 : 4,
-                              NULL, &table->files) < 0)
+                              table->address_size, NULL, &table->files) < 0)
        table->files = (void *) -1;
     }
 
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 5cbdc279..c3fe9f93 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -526,7 +526,8 @@ typedef struct
   Dwarf_Half header_len;
 
   uint16_t version;
-  bool is_64bit;
+  uint8_t address_size;
+  uint8_t offset_size;
   uint8_t sec_index;   /* IDX_debug_macro or IDX_debug_macinfo.  */
 
   /* Shows where in TABLE each opcode is defined.  Since opcode 0 is
-- 
2.41.0

Reply via email to