readelf assumed each .debug_addr and .debug_str_offsets was associated
with precisely one CU DIE. But CU DIEs can have the same
DW_AT_addr_base or DW_AT_str_offsets_base. Change the code to find the
first CU associated with the offset.

         * src/readelf.c (print_debug_addr_section): Skip CUs that
         have an addr_base already handled.
         (print_debug_str_offsets_section): Likewise for
         str_offsets_base.

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

diff --git a/src/readelf.c b/src/readelf.c
index 5db86f0a84bc..3eab60c14b57 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -6053,7 +6053,13 @@ print_debug_addr_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
 
       fprintf (out, "Table at offset %" PRIx64 " ", off);
 
-      struct listptr *listptr = get_listptr (&known_addrbases, idx++);
+      /* Find the first CU that could plausibly be associated with
+        this address base offset. Skip CUs that point their addr_base
+        before this table.  */
+      struct listptr *listptr = get_listptr (&known_addrbases, idx);
+      while (listptr != NULL && listptr->offset < off)
+       listptr = get_listptr (&known_addrbases, ++idx);
+
       const unsigned char *next_unitp;
 
       uint64_t unit_length;
@@ -6087,7 +6093,7 @@ print_debug_addr_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
              version = 4;
 
              /* The addresses start here, but where do they end?  */
-             listptr = get_listptr (&known_addrbases, idx);
+             listptr = get_listptr (&known_addrbases, idx + 1);
              if (listptr == NULL)
                next_unitp = readendp;
              else if (listptr->cu->version < 5)
@@ -11402,7 +11408,13 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
 
       fprintf (out, "Table at offset %" PRIx64 " ", off);
 
-      struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
+      /* Find the first CU that could plausibly be associated with
+        this string offsets index. Skip CUs that point
+        str_offsets_base before this table.  */
+      struct listptr *listptr = get_listptr (&known_stroffbases, idx);
+      while (listptr != NULL && listptr->offset < off)
+       listptr = get_listptr (&known_stroffbases, ++idx);
+
       const unsigned char *next_unitp = readendp;
       uint8_t offset_size;
       bool has_header;
-- 
2.52.0

Reply via email to