-
-
Notifications
You must be signed in to change notification settings - Fork 523
Description
First as always, a big thank you for all the hard work on mold. The performance gains have been incredibly impressive, especially with --separate-debug-file in a slower IO environment.
@mgulick and I noticed that gdb was significantly slower at symbol resolution with mold when we use --separate-debug-file, and while we're still looking into exactly what's going on in gdb, the thing that seems to stand out most is that there is this PHDR section header in the .dbg file that seems out of place (our best guess right now is that gdb chokes on it and starts searching the wrong section for symbols).
I've tried poking around the mold source code and see PHDR is a special "synthetic" chunk name that is intended to represent the Program Header, so it feels unintentional that it's being written into the section header (especially given its not there without --separate-debug-file), but I could be misunderstanding its purpose.
Can you confirm whether it's presence is expected? If it is, we can keep digging and hopefully get to a bug report for gdb.
Here's my minimal reproducer on Debian 12.12 using the latest mold commit (fcd5391) and gcc 12.2.0-14+deb12u1. Note that it seems somewhat sporadic for reasons I can't determine, so if it doesn't appear the first time you may need to relink a couple times.
$ cat foo.c
#include <stdio.h>
int foo(int f) {
puts("hello world");
return f + 1;
}
$ cat main.c
int foo(int);
int main() {
return foo(0);
}
cc -g -O0 -c -fPIC foo.c
cc -fuse-ld=mold -Wl,--separate-debug-file -shared -o libfooBAD.so foo.o
cc -g -O0 main.c -o bad -L. -lfooBAD -Wl,-rpath -Wl,'$ORIGIN'
cc -fuse-ld=mold -shared -o libfooGOOD.so foo.o
objcopy --only-keep-debug libfooGOOD.so libfooGOOD.so.dbg
strip libfooGOOD.so
objcopy --add-gnu-debuglink=libfooGOOD.so.dbg libfooGOOD.so
cc -g -O0 main.c -o good -L. -lfooGOOD -Wl,-rpath -Wl,'$ORIGIN'
readelf -SW libfooBAD.so.dbg | grep PHDR
[ 1] PHDR NOBITS 0000000000000040 000040 000230 00 A 0 0 8
readelf -SW libfooGOOD.so.dbg | grep PHDR
[empty]
And here's the full symbol table
$ readelf -SW libfooBAD.so.dbg
There are 38 section headers, starting at offset 0x4a8:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] PHDR NOBITS 0000000000000040 000040 000230 00 A 0 0 8
[ 2] .note.gnu.build-id NOTE 0000000000000270 000270 000024 00 A 0 0 4
[ 3] .gnu.hash NOBITS 0000000000000298 000294 000020 00 A 3 0 8
[ 4] .dynsym NOBITS 00000000000002b8 000294 0000a8 18 A 4 1 8
[ 5] .dynstr NOBITS 0000000000000360 000294 000076 00 A 0 0 1
[ 6] .gnu.version NOBITS 00000000000003d6 000294 00000e 02 A 3 0 2
[ 7] .gnu.version_r NOBITS 00000000000003e4 000294 000020 00 A 4 1 4
[ 8] .rela.dyn NOBITS 0000000000000408 000294 0000a8 18 A 3 0 8
[ 9] .rela.plt NOBITS 00000000000004b0 000294 000018 18 A 3 23 8
[10] .eh_frame NOBITS 00000000000004c8 000294 00003c 00 A 0 0 8
[11] .eh_frame_hdr NOBITS 0000000000000504 000294 000014 00 A 0 0 4
[12] .rodata NOBITS 0000000000000518 000294 000031 00 A 0 0 8
[13] .fini NOBITS 000000000000154c 000294 000009 00 AX 0 0 4
[14] .init NOBITS 0000000000001558 000294 000017 00 AX 0 0 4
[15] .plt NOBITS 0000000000001570 000294 000030 00 AX 0 0 16
[16] .plt.got NOBITS 00000000000015a0 000294 000008 00 AX 0 0 16
[17] .text NOBITS 00000000000015b0 000294 0000ee 00 AX 0 0 16
[18] .dynamic NOBITS 00000000000026a0 000294 0001c0 10 WA 4 0 8
[19] .fini_array NOBITS 0000000000002860 000294 000008 00 WA 0 0 8
[20] .init_array NOBITS 0000000000002868 000294 000008 00 WA 0 0 8
[21] .got NOBITS 0000000000002870 000294 000028 00 WA 0 0 8
[22] .relro_padding NOBITS 0000000000002898 000294 000768 00 WA 0 0 1
[23] .data NOBITS 0000000000003000 000294 000008 00 WA 0 0 8
[24] .got.plt NOBITS 0000000000003008 000294 000020 00 WA 0 0 8
[25] .tm_clone_table NOBITS 0000000000003028 000294 000000 00 WA 0 0 8
[26] .bss NOBITS 0000000000003028 000294 000001 00 WA 0 0 1
[27] .comment NOBITS 0000000000000000 000294 000077 01 MS 0 0 1
[28] .gnu_debuglink NOBITS 0000000000000000 00030c 000018 00 0 0 4
[29] .shstrtab STRTAB 0000000000000000 000324 00017e 00 0 0 1
[30] .debug_abbrev PROGBITS 0000000000000000 000e28 00009a 00 0 0 1
[31] .debug_aranges PROGBITS 0000000000000000 000ec2 000030 00 0 0 1
[32] .debug_info PROGBITS 0000000000000000 000ef2 0000cc 00 0 0 1
[33] .debug_line PROGBITS 0000000000000000 000fbe 00005f 00 0 0 1
[34] .debug_line_str PROGBITS 0000000000000000 00101d 00004f 01 MS 0 0 1
[35] .debug_str PROGBITS 0000000000000000 00106c 0000c1 01 MS 0 0 1
[36] .strtab STRTAB 0000000000000000 00112d 0002bd 00 0 0 1
[37] .symtab SYMTAB 0000000000000000 0013f0 0007f8 18 36 79 8
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
the program header on the debug info is also nulled out:
$ readelf -a libfooBAD.so.dbg
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0
NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0