https://sourceware.org/bugzilla/show_bug.cgi?id=33835

            Bug ID: 33835
           Summary: readelf incorrect handling of DWARF5 CU DIE addr_base
                    attribute
           Product: binutils
           Version: 2.42
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: binutils
          Assignee: unassigned at sourceware dot org
          Reporter: thanm at golang dot org
  Target Milestone: ---

Users of "readelf" report problems running the tool's DWARF dump flag
on binaries built with the most recent version of the Go compiler (1.25),
Go bug report here https://github.com/golang/go/issues/77246

The symptom is a warning about .debug_addr being out of range. Example:

$ go build -o himom.exe -ldflags=-linkmode=external himom.go
$ readelf --debug-dump=info 1> /dev/null 2> /tmp/errs.txt
$ head -2 /tmp/errs.txt
readelf: Warning: Offset into section .debug_addr too big: 0x47002e00
readelf: Warning: Offset into section .debug_addr too big: 0x47002e08
$

What appears to be happening is that readelf is getting a bad value
for the DW_AT_addr_base attribute for the compilation unit in question
(this is slightly subtle in that the dumped/displayed value is correct, but
the value used later on for base calculations is bad).

I checked out a copy of binutils-gdb at
a815cdb41312bc3b8536dcb5a2cf2c263c3418f8
and built a fresh copy of readelf to debug. Details of the debug session in
https://github.com/golang/go/issues/77246#issuecomment-3795498354.

It appears that the problem relates to the function read_bases
(binutils/dwarf.c line 3782), called from line 4340 as a means of
collecting up the values of DW_AT_addr_base and related attributes for
DWARF 5 binaries. This function was introduced in binutils commit 84102ebc29a
from what I can tell.

The function read_bases works by cycling through the attributes in a given
compilation unit DIE looking for items that interest it. When it encounters
attrs that are uninteresting it calls the helper function skip_attribute
(defined on line 3669 of dwarf.c), which is intended to skip past the
payload of a given attribute.

At line 3747 in skip_attribute there is this code

    case DW_FORM_string:
      inc = strnlen ((char *) data, end - data);
      break;

which is intended to skip over the payload of a DW_FORM_string attr,
however since it is not including the terminating nul byte, the
result returned is incorrect (for comparison, the code in
"skip_attr_bytes" at line 2060 does use the correct formula -- not clear
why we have two versions).

This means that when read_bases does arrive at an attribute of interest,
the data pointer for the attr is incorrect if the DIE in question contains
a DW_FORM_string attr before it.

This patch should fix the issue:

$ git diff
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index b5e9917b5fc..a9cb88d5631 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -3745,7 +3745,7 @@ skip_attribute (unsigned long    form,
                             dwarf_version);

     case DW_FORM_string:
-      inc = strnlen ((char *) data, end - data);
+      inc = strnlen ((char *) data, end - data) + 1;
       break;
     case DW_FORM_block:
     case DW_FORM_exprloc:
$

Thanks.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to