[Bug symtab/34389] New: Source code lookup fails for code at or near 0 when linking with garbage collection
aburgess at redhat dot com via Gdb-prs <[email protected]>
| Newsgroups | gmane.comp.gdb.bugs.discuss |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://sourceware.org/bugzilla/show_bug.cgi?id=34389
Bug ID: 34389
Summary: Source code lookup fails for code at or near 0 when
linking with garbage collection
Product: gdb
Version: HEAD
Status: NEW
Severity: normal
Priority: P2
Component: symtab
Assignee: unassigned at sourceware dot org
Reporter: aburgess at redhat dot com
Target Milestone: ---
Created attachment 16836
--> https://sourceware.org/bugzilla/attachment.cgi?id=16836&action=edit
Reproducer for this bug.
This issue was reported here:
https://inbox.sourceware.org/gdb/CAGnW-qix0m4Y1zJG8OE640OkJZXwbsHX-Jk5JH6sfFy1aOvuNw@mail.gmail.com
I had an LLM create a simpler reproducer, but this is still risc-v
only, so you'll need to setup a risc-v tool chain. However, the bug
can be revealed using GDB's built-in risc-v simulator.
Download the attached `addr-zero.tar.xz` file then:
```
tar -xf addr-zero.tar.xz
cd addr-zero/
make
```
You should now have a `repro.elf` file.
Here's a session where I avoid triggering the bug, notice that when
I disassemble `target_func` I can see both the assembly instructions
and the source code:
```
(gdb) file repro.elf
(gdb) target sim
(gdb) load
(gdb) disassemble /s target_func
Dump of assembler code for function target_func:
file_a.c:
7 {
0x00000000000000a4 <+0>: addi sp,sp,-48
0x00000000000000a8 <+4>: sd ra,40(sp)
0x00000000000000ac <+8>: sd s0,32(sp)
0x00000000000000b0 <+12>: addi s0,sp,48
0x00000000000000b4 <+16>: mv a5,a0
0x00000000000000b8 <+20>: sw a5,-36(s0)
8 int a = x + 1;
0x00000000000000bc <+24>: lw a5,-36(s0)
0x00000000000000c0 <+28>: addiw a5,a5,1
0x00000000000000c4 <+32>: sw a5,-20(s0)
9 int b = a + 2;
0x00000000000000c8 <+36>: lw a5,-20(s0)
0x00000000000000cc <+40>: addiw a5,a5,2
0x00000000000000d0 <+44>: sw a5,-24(s0)
10 int c = b + 3;
0x00000000000000d4 <+48>: lw a5,-24(s0)
0x00000000000000d8 <+52>: addiw a5,a5,3
0x00000000000000dc <+56>: sw a5,-28(s0)
11 sink = c;
0x00000000000000e0 <+60>: lw a4,-28(s0)
0x00000000000000e4 <+64>: sw a4,260(zero) # 0x104 <sink>
12 return c;
0x00000000000000e8 <+68>: lw a5,-28(s0)
13 }
0x00000000000000ec <+72>: mv a0,a5
0x00000000000000f0 <+76>: ld ra,40(sp)
0x00000000000000f4 <+80>: ld s0,32(sp)
0x00000000000000f8 <+84>: addi sp,sp,48
0x00000000000000fc <+88>: ret
End of assembler dump.
(gdb)
```
And here's a session where I trigger the bug by first disassembling
the `target` function, now when I disassemble `target_func` I no
longer see the source code:
```
(gdb) file repro.elf
(gdb) target sim
(gdb) load
(gdb) disassemble /s helper
Dump of assembler code for function helper:
file_b.c:
12 {
0x0000000000000014 <+0>: addi sp,sp,-32
0x0000000000000018 <+4>: sd ra,24(sp)
0x000000000000001c <+8>: sd s0,16(sp)
0x0000000000000020 <+12>: addi s0,sp,32
0x0000000000000024 <+16>: mv a5,a0
0x0000000000000028 <+20>: sw a5,-20(s0)
13 bsink = x * 2;
0x000000000000002c <+24>: lw a5,-20(s0)
0x0000000000000030 <+28>: slliw a5,a5,0x1
0x0000000000000034 <+32>: sext.w a4,a5
0x0000000000000038 <+36>: sw a4,256(zero) # 0x100 <bsink>
14 return bsink;
0x000000000000003c <+40>: lw a5,256(zero) # 0x100 <bsink>
0x0000000000000040 <+44>: sext.w a5,a5
15 }
0x0000000000000044 <+48>: mv a0,a5
0x0000000000000048 <+52>: ld ra,24(sp)
0x000000000000004c <+56>: ld s0,16(sp)
0x0000000000000050 <+60>: addi sp,sp,32
0x0000000000000054 <+64>: ret
End of assembler dump.
(gdb) disassemble /s target_func
Dump of assembler code for function target_func:
0x00000000000000a4 <+0>: addi sp,sp,-48
0x00000000000000a8 <+4>: sd ra,40(sp)
0x00000000000000ac <+8>: sd s0,32(sp)
0x00000000000000b0 <+12>: addi s0,sp,48
0x00000000000000b4 <+16>: mv a5,a0
0x00000000000000b8 <+20>: sw a5,-36(s0)
0x00000000000000bc <+24>: lw a5,-36(s0)
0x00000000000000c0 <+28>: addiw a5,a5,1
0x00000000000000c4 <+32>: sw a5,-20(s0)
0x00000000000000c8 <+36>: lw a5,-20(s0)
0x00000000000000cc <+40>: addiw a5,a5,2
0x00000000000000d0 <+44>: sw a5,-24(s0)
0x00000000000000d4 <+48>: lw a5,-24(s0)
0x00000000000000d8 <+52>: addiw a5,a5,3
0x00000000000000dc <+56>: sw a5,-28(s0)
0x00000000000000e0 <+60>: lw a4,-28(s0)
0x00000000000000e4 <+64>: sw a4,260(zero) # 0x104 <sink>
0x00000000000000e8 <+68>: lw a5,-28(s0)
0x00000000000000ec <+72>: mv a0,a5
0x00000000000000f0 <+76>: ld ra,40(sp)
0x00000000000000f4 <+80>: ld s0,32(sp)
0x00000000000000f8 <+84>: addi sp,sp,48
0x00000000000000fc <+88>: ret
End of assembler dump.
(gdb)
```
The problem is that `repro.elf` is linked with garbage collection.
When function sections are garbage collected references to these
sections are left as 0 in the `.debug_rnglists` section, here's part
of the table from `repro.elf`:
```
Contents of the .debug_rnglists section:
Table at Offset: 0:
Length: 0x1e
DWARF version: 5
Address size: 8
Segment size: 0
Offset entries: 0
Offset Begin End
0000000c 0000000000000014 0000000000000058
00000016 0000000000000000 0000000000000990
00000021 <End of list>
```
Notice the entry at offset 0x1c starts at address 0, this is a
garbage collected entry.
Here's the rest of the `.debug_rnglists` table:
```
Table at Offset: 0x22:
Length: 0x13
DWARF version: 5
Address size: 8
Segment size: 0
Offset entries: 0
Offset Begin End
0000002e 0000000000000058 00000000000000a4
00000038 <End of list>
Table at Offset: 0x39:
Length: 0x13
DWARF version: 5
Address size: 8
Segment size: 0
Offset entries: 0
Offset Begin End
00000045 00000000000000a4 0000000000000100
0000004f <End of list>
```
Notice that both of these ranges, the one at 0x2e and the one at
0x45 both appear to sit within the garbage collected range at 0x16
which runs from 0x0 to 0x990.
The bug can be triggered by controlling the order in which GDB
searches the `compunit_symtab` objects. If we first disassemble
something from the `compunit_symtab` containing the garbage
collected function then this will be the first `compunit_symtab`
that GDB searches for later look ups, and, as its range covers the
addresses of other functions, that `compunit_symtab` will "claim"
those addresses, even though that `compunit_symtab` doesn't actually
have any line table entries for those addresses.
If we avoid searching the problematic `compunit_symtab` first, and
instead search the other `compunit_symtab` objects, then GDB will be
able to find those in later searches as they will continue to be
checked first.
This is only really a problem for targets that allow code to be
placed at, or near, address 0. Garbage collection effectively moves
the ranges of the deleted function(s) to start at 0. On targets
where address 0, and some space after that, is non-accessible, then
usually the range of the garbage collected functions falls within
this non-accessible range, as a consequence, this bug is a
non-issue, there will never be overlap between legitimate, mapped
code and the garbage collected ranges.
But for targets where code can be mapped at, or near, address 0,
there is the possibility of aliasing between deleted function ranges
real functions. If these two things come from different
`compunit_symtab` objects them GDB will run into issues finding the
correct `compunit_symtab`.
An ideal solution for this would be to have the linker be smarter
and fully discard ranges that correspond to sections that have been
discarded, but I don't know how easy that would be to implement.
Maybe we need to investigate strategies for dealing with this in
GDB.
--
You are receiving this mail because:
You are on the CC list for the bug.