[gdb/symtab] Support .debug_line with DW_FORM_line_strp
authorTom de Vries <tdevries@suse.de>
Mon, 22 Nov 2021 08:14:16 +0000 (09:14 +0100)
committerTom de Vries <tdevries@suse.de>
Mon, 22 Nov 2021 08:14:16 +0000 (09:14 +0100)
commitbab31d145160cd4dec7b9ad0e79346382ebf8385
tree85261ec6bfe218eb40d187efe56da0d409e05ea9
parent26bf28e29d7b3bddc6d2f8f34f07000f2b858588
[gdb/symtab] Support .debug_line with DW_FORM_line_strp

I noticed a new gcc option -gdwarf64 and tried it out (using gcc 11.2.1).

With a test-case hello.c:
...
int
main (void)
{
  printf ("hello\n");
  return 0;
}
...
compiled like this:
...
$ gcc -g -gdwarf64 ~/hello.c
...
I ran into:
...
$ gdb -q -batch a.out
DW_FORM_line_strp pointing outside of .debug_line_str section \
  [in module a.out]
...

Debugging gdb revealed that the string offset is:
...
(gdb) up
    objfile=0x182ab70, str_offset=1378684502312,
    form_name=0xeae9b5 "DW_FORM_line_strp")
    at src/gdb/dwarf2/section.c:208
208         error (_("%s pointing outside of %s section [in module %s]"),
(gdb) p /x str_offset
$1 = 0x14100000128
(gdb)
...
which is read when parsing a .debug_line entry at 0x1e0.

Looking with readelf at the 0x1e0 entry, we have:
...
 The Directory Table (offset 0x202, lines 2, columns 1):
  Entry Name
  0     (indirect line string, offset: 0x128): /data/gdb_versions/devel
  1     (indirect line string, offset: 0x141): /home/vries
...
which in a hexdump looks like:
...
  0x00000200 1f022801 00004101 00000201 1f020f02
...

What happens is the following:
- readelf interprets the DW_FORM_line_strp reference to .debug_line_str as
  a 4 byte value, and sees entries 0x00000128 and 0x00000141.
- gdb instead interprets it as an 8 byte value, and sees as first entry
  0x0000014100000128, which is too big so it bails out.

AFAIU, gdb is wrong.  It assumes DW_FORM_line_strp is 8 bytes on the basis
that the corresponding CU is 64-bit DWARF.  However, the .debug_line
contribution has it's own initial_length field, and encodes there that it's
32-bit DWARF.

Fix this by using the correct offset size for DW_FORM_line_strp references
in .debug_line.

Note: the described test-case does trigger this complaint (both with and
without this patch):
...
$ gdb -q -batch -iex "set complaints 10" a.out
During symbol reading: intermixed 32-bit and 64-bit DWARF sections
...

The reason that the CU has 64-bit dwarf is because -gdwarf64 was passed to
gcc.  The reason that the .debug_line entry has 32-bit dwarf is because that's
what gas generates.  Perhaps this is complaint-worthy, but I don't think it
is wrong.

Tested on x86_64-linux, using native and target board dwarf64.exp.
gdb/dwarf2/line-header.c
gdb/dwarf2/read.c
gdb/dwarf2/read.h
gdb/testsuite/gdb.dwarf2/dw2-lines.exp
gdb/testsuite/lib/dwarf.exp