https://sourceware.org/bugzilla/show_bug.cgi?id=30791
Bug ID: 30791 Summary: Do not merge sections with same name and SHF_LINK_ORDER, but different sh_link value Product: binutils Version: unspecified Status: UNCONFIRMED Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: zimao at microsoft dot com Target Milestone: --- When a section has both SHF_LINK_ORDER and sh_link set, it means this section is kind of a child section of the linked to section. When merging two sections with the same name, both have SHF_LINK_ORDER set, but different sh_link value, one of the sh_link information will be absent in the merged section. In a real world example, both GCC (13.1) and clang (14.0) utilize this behavior for the "-ffunction-sections -fpatchable-function-entry=N". The compiler will generate multiple sections all named as "__patchable_function_entries", with different sh_link. Each section will be linked its own .text section. But when running code like `ld -r -o merged.o a.o b.o`, the current ld will merge all these "__patchable_function_entries" section into a single section. On the other hand, on the LLVM side, lld will keep these "pfe" sections separately after the linking. ref link: https://reviews.llvm.org/D68094 I think ld should not merge these sections as well, just like the behavior in lld. Example code: $ cat a.c int a(){return 1;} int b(){return 2;} $ cat b.c int c(){return 3;} int d(){return 4;} $ gcc -c -ffunction-sections -fpatchable-function-entry=2 a.c b.c $ readelf -S a.o [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 3] .text.a PROGBITS 0000000000000000 00000040 000000000000000d 0000000000000000 AX 0 0 16 [ 4] __patchable_[...] PROGBITS 0000000000000000 00000050 0000000000000008 0000000000000000 WAL 3 0 8 [ 5] .rela__patch[...] RELA 0000000000000000 00000188 0000000000000018 0000000000000018 I 14 4 8 [ 6] .text.b PROGBITS 0000000000000000 00000060 000000000000000d 0000000000000000 AX 0 0 16 [ 7] __patchable_[...] PROGBITS 0000000000000000 00000070 0000000000000008 0000000000000000 WAL 6 0 8 [ 8] .rela__patch[...] RELA 0000000000000000 000001a0 0000000000000018 0000000000000018 I 14 7 8 (some content removed, same result for the b.o) $ ld -r -o merged.o a.o b.o readelf -S merged.o | grep -E "(text)|(patchable)" -A1 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 AX 0 0 4 [ 2] .text.a PROGBITS 0000000000000000 00000040 000000000000000d 0000000000000000 AX 0 0 16 [ 3] .text.b PROGBITS 0000000000000000 00000050 000000000000000d 0000000000000000 AX 0 0 16 [ 4] .text.c PROGBITS 0000000000000000 00000060 000000000000000d 0000000000000000 AX 0 0 16 [ 5] .text.d PROGBITS 0000000000000000 00000070 000000000000000d 0000000000000000 AX 0 0 16 -- [ 8] __patchable_[...] PROGBITS 0000000000000000 00000130 0000000000000020 0000000000000000 WAL 2 0 8 $ ld.lld -r -o merged-2.o a.o b.o $ readelf -S merged-2.o | grep -E "(text)|(patchable)" -A1 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 AX 0 0 4 [ 2] .text.a PROGBITS 0000000000000000 00000040 000000000000000d 0000000000000000 AX 0 0 16 [ 3] __patchable_[...] PROGBITS 0000000000000000 00000050 0000000000000008 0000000000000000 WAL 2 0 8 -- [ 5] .text.b PROGBITS 0000000000000000 00000060 000000000000000d 0000000000000000 AX 0 0 16 [ 6] __patchable_[...] PROGBITS 0000000000000000 00000070 0000000000000008 0000000000000000 WAL 5 0 8 -- [12] .text.c PROGBITS 0000000000000000 00000130 000000000000000d 0000000000000000 AX 0 0 16 [13] __patchable_[...] PROGBITS 0000000000000000 00000140 0000000000000008 0000000000000000 WAL 12 0 8 -- [15] .text.d PROGBITS 0000000000000000 00000150 000000000000000d 0000000000000000 AX 0 0 16 [16] __patchable_[...] PROGBITS 0000000000000000 00000160 0000000000000008 0000000000000000 WAL 15 0 8 -- You are receiving this mail because: You are on the CC list for the bug.