diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -270,7 +270,11 @@ if (isReserved(sec) || script->shouldKeep(sec)) { enqueue(sec, 0); - } else if (isValidCIdentifier(sec->name)) { + } else if (sec->getSize() == 0 && sec->name.startswith("__llvm_prf_")) { + // libclang_rt-profile-* need GCC 11/Clang 13 to mark zero size + // __llvm_prf_* SHF_GNU_RETAIN. Without this workaround, + // -fprofile-generate/-fprofile-instr-generate linked programs may have + // spurious 'undefined hidden symbol: __start___llvm_prf_vnds' errors. cNamedSections[saver.save("__start_" + sec->name)].push_back(sec); cNamedSections[saver.save("__stop_" + sec->name)].push_back(sec); } diff --git a/lld/test/ELF/gc-sections-metadata-startstop.s b/lld/test/ELF/gc-sections-metadata-startstop.s --- a/lld/test/ELF/gc-sections-metadata-startstop.s +++ b/lld/test/ELF/gc-sections-metadata-startstop.s @@ -3,16 +3,30 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: ld.lld --gc-sections %t.o -o %t -# RUN: llvm-objdump --section-headers -t %t | FileCheck %s +# RUN: llvm-readelf -S -s %t | FileCheck %s -# CHECK: Sections: -# CHECK-NOT: yy -# CHECK: xx {{.*}} DATA -# CHECK-NOT: yy +## Note: we used to retain the C identifier name section xx due to __start_/__stop_. -# CHECK: SYMBOL TABLE: -# CHECK: xx 0000000000000000 .protected __start_xx -# CHECK: w *UND* 0000000000000000 __start_yy +## To make -fprofile-generate/-fprofile-instr-generated compiled programs link with libclang_rt.profile-* +## built with GCC<11/Clang<13, we install a workaround to retain zero size sections. + +# CHECK: Name Type Address Off Size ES Flg Lk Inf +# CHECK-NOT: xx +# CHECK-NOT: yy +# CHECK: __llvm_prf_names PROGBITS 0000000000200158 000158 000000 00 A 0 0 +# CHECK-NEXT: .text PROGBITS 0000000000201158 000158 000030 00 AX 0 0 +# CHECK-NEXT: __llvm_prf_cnts PROGBITS 0000000000202188 000188 000000 00 WA 0 0 +# CHECK-NEXT: __llvm_prf_data PROGBITS 0000000000202188 000188 000000 00 WA 0 0 +# CHECK-NEXT: __llvm_prf_vnds PROGBITS 0000000000202188 000188 000000 00 WA 0 0 +# CHECK-NOT: xx +# CHECK-NOT: yy + +# CHECK: WEAK DEFAULT UND __start_xx +# CHECK: WEAK DEFAULT UND __start_yy +# CHECK: GLOBAL PROTECTED [[#]] __start___llvm_prf_names +# CHECK: GLOBAL PROTECTED [[#]] __start___llvm_prf_cnts +# CHECK: GLOBAL PROTECTED [[#]] __start___llvm_prf_data +# CHECK: GLOBAL PROTECTED [[#]] __start___llvm_prf_vnds .weak __start_xx .weak __start_yy @@ -21,6 +35,10 @@ _start: .quad __start_xx .quad __start_yy +.quad __start___llvm_prf_names +.quad __start___llvm_prf_cnts +.quad __start___llvm_prf_data +.quad __start___llvm_prf_vnds .section xx,"a" .quad 0 @@ -31,3 +49,17 @@ .section yy,"ao",@progbits,.foo .quad 0 + +.section __llvm_prf_names,"a",@progbits +.section __llvm_prf_cnts,"aw",@progbits +.section __llvm_prf_data,"aw",@progbits +.section __llvm_prf_vnds,"aw",@progbits + +.section __llvm_prf_names,"a",@progbits,unique,1 +.byte 0 +.section __llvm_prf_cnts,"aw",@progbits,unique,1 +.byte 0 +.section __llvm_prf_data,"aw",@progbits,unique,1 +.byte 0 +.section __llvm_prf_vnds,"aw",@progbits,unique,1 +.byte 0 diff --git a/lld/test/ELF/linkerscript/sections-gc2.s b/lld/test/ELF/linkerscript/sections-gc2.s --- a/lld/test/ELF/linkerscript/sections-gc2.s +++ b/lld/test/ELF/linkerscript/sections-gc2.s @@ -10,7 +10,6 @@ # CHECK: Idx Name Size VMA Type # CHECK-NEXT: 0 -# CHECK-NEXT: used_in_reloc # CHECK-NEXT: .text # CHECK-NEXT: .comment # CHECK-NEXT: .symtab diff --git a/lld/test/ELF/lto/section-name.ll b/lld/test/ELF/lto/section-name.ll --- a/lld/test/ELF/lto/section-name.ll +++ b/lld/test/ELF/lto/section-name.ll @@ -28,8 +28,7 @@ ; CHECK-NEXT: bar_section PROGBITS ; CHECK-NOT: zed_section +;; Note: we used to retain foo_section/bar_section due to __start_/__stop_. ; GC-NOT: zed_section ; GC-NOT: foo_section -; GC: bar_section PROGBITS -; GC-NOT: zed_section -; GC-NOT: foo_section +; GC-NOT: bar_section diff --git a/lld/test/ELF/relocatable-gc.s b/lld/test/ELF/relocatable-gc.s --- a/lld/test/ELF/relocatable-gc.s +++ b/lld/test/ELF/relocatable-gc.s @@ -47,18 +47,16 @@ # KEEP_START: [ 1] .text # KEEP_START-NEXT: [ 2] .rela.text -# KEEP_START-NEXT: [ 3] qux -# KEEP_START-NEXT: [ 4] .group -# KEEP_START-NEXT: [ 5] .fred -# KEEP_START-NEXT: [ 6] .rela.fred -# KEEP_START-NEXT: [ 7] .note.GNU-stack +# KEEP_START-NEXT: [ 3] .group +# KEEP_START-NEXT: [ 4] .fred +# KEEP_START-NEXT: [ 5] .rela.fred +# KEEP_START-NEXT: [ 6] .note.GNU-stack -# KEEP_START: Symbol table '.symtab' contains 10 entries: -# KEEP_START: 5: {{.*}} SECTION -# KEEP_START-NEXT: 6: {{.*}} 1 _start -# KEEP_START-NEXT: 7: {{.*}} 5 fred -# KEEP_START-NEXT: 8: {{.*}} UND __start_qux -# KEEP_START-NEXT: 9: {{.*}} UND fred_und +# KEEP_START: Symbol table '.symtab' contains 9 entries: +# KEEP_START: 5: {{.*}} 1 _start +# KEEP_START-NEXT: 6: {{.*}} 4 fred +# KEEP_START-NEXT: 7: {{.*}} UND __start_qux +# KEEP_START-NEXT: 8: {{.*}} UND fred_und .section qux,"a",@progbits .byte 0 diff --git a/lld/test/ELF/startstop-gccollect.s b/lld/test/ELF/startstop-gccollect.s --- a/lld/test/ELF/startstop-gccollect.s +++ b/lld/test/ELF/startstop-gccollect.s @@ -8,14 +8,17 @@ ## Check that foo and bar sections are not garbage collected, ## we do not want to reclaim sections if they are referred ## by __start_* and __stop_* symbols. -# RUN: ld.lld %t --gc-sections -o %tout -# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s +# RUN: not ld.lld %t --gc-sections -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1 --implicit-check-not=error: + +# ERR1: error: undefined symbol: __start_foo +# ERR1: error: undefined symbol: __stop_bar # RUN: echo ".global __start_foo; __start_foo:" > %t2.s # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o # RUN: ld.lld -shared %t2.o -o %t2.so -# RUN: ld.lld %t --gc-sections -o %tout %t2.so -# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s +# RUN: not ld.lld %t %t2.so --gc-sections -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2 --implicit-check-not=error: + +# ERR2: error: undefined symbol: __stop_bar # DISASM: <_start>: # DISASM-NEXT: callq {{.*}} <__start_foo>