Bug 30355 - [DWARFv5] readelf: loc_offset XX too big
Summary: [DWARFv5] readelf: loc_offset XX too big
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.40
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-04-14 17:34 UTC by Nick Desaulniers
Modified: 2023-04-19 10:51 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nick Desaulniers 2023-04-14 17:34:57 UTC
When running readelf on a Linux kernel built with clang with DEBUG_INFO_DWARF5=y and CONFIG_LTO_CLANG_FULL=y, I get a stream of warnings related to loc_offset that I wasn't able to reproduce with llvm-dwarfdump.  This could be perhaps a bug in clang's encoding of loc_offset, but might also be an issue in GNU readelf, or perhaps even somewhere else.

$ /usr/bin/readelf --debug-dump=info vmlinux 1>/dev/null
readelf: Warning: loc_offset 78 too big
...

even with an allnoconfig kernel with the above two configs re-enabled, the resulting vmlinux size is 34M in size; probably too large to attach here?
Comment 1 Nick Clifton 2023-04-17 12:58:36 UTC
Hi Nick,

  Do you get errors if you examine the kernel with eu-readelf as well ?

  Are you able to strip the debug info out of the kernel and upload that as a standalone file ?

  The implication of the error message is that the DWARF decoder has seen a DW_FORM_loclistx form with an index value of 78, but the .debug_loclists section does not have 78 (or more) entries in its index table.  This seems unlikely, so the problem is almost certainly a binutils bug.  But having a reproducer will really help to debug the problem.

Cheers
  Nick
Comment 2 Nick Desaulniers 2023-04-17 16:50:55 UTC
$ eu-readelf --debug-dump=info vmlinux 1>/dev/null

produced no output to stderr, and the return code was 0.

What's the best way to strip out the debug info?

$ objcopy --only-keep-debug vmlinux vmlinux-debug
$ du -h vmlinux vmlinux-debug
34M	vmlinux
33M	vmlinux-debug

Looks like .text was retained. Hmm.

---

It looks like there's another utility called dwarfdump; https://manpages.ubuntu.com/manpages/impish/man1/dwarfdump.1.html. It seems to complain about loclists as well.

```
$ dwarfdump --check-loc vmlinux
*** DWARF CHECK: .debug_loc[lists]: Address outside a valid .text range: TAG DW_TAG_formal_parameter with attribute DW_AT_location. ***
...
*** DWARF CHECK: .debug_loc[lists]: Address outside a valid .text range: TAG DW_TAG_variable with attribute DW_AT_location. ***
...
*** TOTAL ERRORS FOR ALL COMPILERS ***

DWARF CHECK RESULT
<item>                    <checks>    <errors>
locations                    10374        4416
** Summarize **              12739        4416

There were 22 DWARF errors reported: see ERROR above.
$ dwarfdump --check-loc vmlinux 2>&1 | grep DWARF | sort -u
*** DWARF CHECK: .debug_loc[lists]: Address outside a valid .text range: TAG DW_TAG_formal_parameter with attribute DW_AT_location. ***
*** DWARF CHECK: .debug_loc[lists]: Address outside a valid .text range: TAG DW_TAG_variable with attribute DW_AT_location. ***
```

I do see many instances of the same low pc and high pc value.
$ dwarfdump --check-loc vmlinux 2>&1 | grep "Low PC = 0xffffffc009b001ec" | wc -l
164

Inspecting this with llvm-dwardump, it looks like the DW_TAG_compile_unit, DW_TAG_subprogram, and DW_TAG_formal_parameter all have the same value for their lowest PC value. So that's probably the first pc value in the CU?  It does have a loclist of 0x00000279.  Maybe these are red herrings though.

> readelf: Warning: loc_offset 78 too big

Using llvm-dwarfdump, I couldn't find any reference to 78 (or 0x0000004e). Using dwarfdump, I see 0x0000004e all over the place, for many different types of tags.
Comment 3 Nick Clifton 2023-04-18 10:45:43 UTC
(In reply to Nick Desaulniers from comment #2)
 
> What's the best way to strip out the debug info?
> 
> $ objcopy --only-keep-debug vmlinux vmlinux-debug
> $ du -h vmlinux vmlinux-debug
> 34M	vmlinux
> 33M	vmlinux-debug
> 
> Looks like .text was retained. Hmm.
 
Well that is odd.  The command line that you used was
exactly what I would have suggested.  Maybe this will
work instead:

  objcopy --only-section=".debug.*" vmlinux vnlinux-debug
Comment 4 Sourceware Commits 2023-04-19 10:49:06 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=28ab94f51dcdee056d96e57ad04c27c22cf854ea

commit 28ab94f51dcdee056d96e57ad04c27c22cf854ea
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Apr 19 11:48:24 2023 +0100

    Fix: readelf: loc_offset XX too big
    
      PR 30355
      * dwarf.c (read_and_display_attr_value): Correctly handle DW_loclistx attributes that index a version 5 .debug_loclists section.
Comment 5 Nick Clifton 2023-04-19 10:51:35 UTC
[reproducer obtained offline]

This was a silly snafu in the DWARF decoder.  When decoding the DW_AT_loclistx attribute it was assuming that the .debug_loclists section were in DWARF v4 (or earlier) format, and not trying to access the index table.  

Fixed with a small patch.