The offset_size_flag is an DWARF 6 extension described in
https://dwarfstd.org/issues/220708.2.html

While writing tests for eu-dwp some issues with the eu-readelf display
of the .debug_cu_index were found. The offset_size_flag was only used
for the offsets table, not the size (lengths) table. And if the flag
was set only 4 bytes of the offset were read (instead of 8 bytes).

        * src/readelf.c (print_cu_index_section): Calculate
        lengths_end using off_bytes, use read_8ubyte_unaligned to
        read offsets when offset_size_flag is set, calculate prow
        using off_bytes, read and print sizes based on off_bytes.

Signed-off-by: Mark Wielaard <[email protected]>
---
 src/readelf.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index 8d7950d3a6c8..9d3bbbf6f240 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -12290,6 +12290,7 @@ print_cu_index_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
       readp++;
     }
 
+  /* Both offsets and sizes are either 32 or 64 bits (4 or 8 bytes).  */
   const unsigned char off_bytes = offset_size_flag == 0 ? 4 : 8;
 
   if (unlikely (readp > dataend - 4))
@@ -12325,17 +12326,17 @@ print_cu_index_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
      the hash table (ids of 8 bytes).  */
   const unsigned char *indices = hash_table + slot_count * 8;
   /* Sections used starts after the indices, indices and hash table
-     have the same number of slots, indeces are 4 bytes each, */
+     have the same number of slots, indices are 4 bytes each, */
   const unsigned char *sections = indices + slot_count * 4;
   /* Offset slots for each section follow the one row of sections.  */
   const unsigned char *offsets = sections + section_count * 4;
   /* Size slots for each section follow the offsets (used rows).  */
   const unsigned char *lengths = (offsets +
                                  unit_count * section_count * off_bytes);
-  /* The size table has one row of section_count 4-byte slots per unit,
+  /* The size table has one row of section_count slots per unit,
      just like the offset table, so it spans unit_count rows (not one).  */
   const unsigned char *lengths_end = (lengths +
-                                     unit_count * section_count * 4);
+                                     unit_count * section_count * off_bytes);
 
   /* Sanity check the above against dataend.  */
   if ((slot_count > UINT32_MAX / 8)
@@ -12395,7 +12396,7 @@ print_cu_index_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
          else
            for (size_t j = 0; j < section_count; j++)
              {
-               uint64_t off = read_4ubyte_unaligned (dbg, prow + j * 8);
+               uint64_t off = read_8ubyte_unaligned (dbg, prow + j * 8);
                fprintf (out, " %6" PRIu64, off);
              }
          fprintf (out, "\n");
@@ -12433,12 +12434,20 @@ print_cu_index_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
              continue;
            }
          /* Note row is one based, not zero based.  */
-         const unsigned char *prow = lengths + (row - 1) * section_count * 4;
-         for (size_t j = 0; j < section_count; j++)
-           {
-             uint32_t off = read_4ubyte_unaligned (dbg, prow + j * 4);
-             fprintf (out, " %6" PRIu32, off);
-           }
+         const unsigned char *prow = (lengths
+                                      + (row - 1) * section_count * off_bytes);
+         if (off_bytes == 4)
+           for (size_t j = 0; j < section_count; j++)
+             {
+               uint32_t sz = read_4ubyte_unaligned (dbg, prow + j * 4);
+               fprintf (out, " %6" PRIu32, sz);
+             }
+         else
+           for (size_t j = 0; j < section_count; j++)
+             {
+               uint64_t sz = read_8ubyte_unaligned (dbg, prow + j * 8);
+               fprintf (out, " %6" PRIu64, sz);
+             }
          fprintf (out, "\n");
        }
     }
-- 
2.54.0

Reply via email to