Here is a small reproducible: // Failed with gnu ld gcc -fuse-ld=bfd -fdata-sections -Wl,--gc-sections gctest.c gctest2.c /tmp/cc4jxArE.o: In function `dump': gctest2.c:(.text+0xc): undefined reference to `__start_my_section' collect2: error: ld returned 1 exit status // Fine with Gold: gcc -fuse-ld=gold -fdata-sections -Wl,--gc-sections gctest.c gctest2.c // gctest.c extern int variable; int main() { return variable; } // gctest2.c typedef struct A { int i; int j; } A; extern int printf(const char*,...); extern int atexit(void (*)(void)); A __attribute__((section("my_section"))) a[2] = {{1,2}, {3,4}}; extern A __start_my_section; extern A __stop_my_section; int variable = 0; void dump() { A* ap = &__start_my_section; printf("%d %d\n", ap->i, ap->j); } void __attribute__((constructor)) foo() { atexit(dump); }
(In reply to David Li from comment #0) > Here is a small reproducible: > > // Failed with gnu ld > > gcc -fuse-ld=bfd -fdata-sections -Wl,--gc-sections gctest.c gctest2.c > > /tmp/cc4jxArE.o: In function `dump': > gctest2.c:(.text+0xc): undefined reference to `__start_my_section' gold linker has this check to prevent any named section 'XXX' from being garbage collected if it finds a symbol __start_XXX or __stop_XXX: In gold/gc.h: //If the symbol name matches '__start_XXX' then the section with // the C identifier like name 'XXX' should not be garbage collected. // A similar treatment to symbols with the name '__stop_XXX'. if (is_prefix_of(cident_section_start_prefix, gsym->name())) { ... GNU ld should also be doing this? > collect2: error: ld returned 1 exit status > > > // Fine with Gold: > > gcc -fuse-ld=gold -fdata-sections -Wl,--gc-sections gctest.c gctest2.c > > > > > // gctest.c > > extern int variable; > int main() > { > return variable; > } > > > // gctest2.c > > typedef struct A { > int i; > int j; > } A; > > extern int printf(const char*,...); > extern int atexit(void (*)(void)); > A __attribute__((section("my_section"))) a[2] = {{1,2}, {3,4}}; > > extern A __start_my_section; > extern A __stop_my_section; > > int variable = 0; > > > void dump() > { > A* ap = &__start_my_section; > printf("%d %d\n", ap->i, ap->j); > } > > void __attribute__((constructor)) foo() { > atexit(dump); > }
Created attachment 8737 [details] A patch Try this.
(In reply to H.J. Lu from comment #2) > Created attachment 8737 [details] > A patch > > Try this. Verified the fix works fine.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bba037e0aef1f3b17cc6cf6fd041ed6110cc375a commit bba037e0aef1f3b17cc6cf6fd041ed6110cc375a Author: H.J. Lu <hjl.tools@gmail.com> Date: Thu Oct 22 12:17:43 2015 -0700 Always keep sections marked with SEC_KEEP SEC_KEEP check in elf_gc_sweep was missing in commit: commit bde6f3eb6dff94cea1d471e15c6154d55d49820f Author: H.J. Lu <hjl.tools@gmail.com> Date: Fri Jan 8 01:43:23 2010 +0000 Set SEC_KEEP on section XXX for undefined __start_XXX/__stop_XXX bfd/ 2010-01-07 H.J. Lu <hongjiu.lu@intel.com> PR ld/11133 * elflink.c (_bfd_elf_gc_mark_hook): Check section XXX for undefined __start_XXX/__stop_XXX in all input files and set SEC_KEEP. This patch adds SEC_KEEP check to elf_gc_sweep. bfd/ PR ld/19161 * elflink.c (elf_gc_sweep): Always keep sections marked with SEC_KEEP. ld/testsuite/ PR ld/19161 * ld-gc/gc.exp: Run pr19161 test. * ld-gc/pr19161-1.c: New file. * ld-gc/pr19161-2.c: Likewise. * ld-gc/pr19161.d: Likewise.
Fixed for 2.26.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1e7eae0dcc0e5473dda573b30107ffdd501b0d73 commit 1e7eae0dcc0e5473dda573b30107ffdd501b0d73 Author: Alan Modra <amodra@gmail.com> Date: Fri Oct 23 10:14:51 2015 +1030 Re: Always keep sections marked with SEC_KEEP Revert bba037e0, it breaks the gc-sections model. Instead fix the underlying problem which is that _bfd_elf_gc_mark_hook is too late to be setting SEC_KEEP. PR ld/11133 PR ld/19161 * elflink.c (elf_gc_sweep): Revert last patch. (_bfd_elf_gc_mark_hook): Don't set SEC_KEEP here.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1cce69b9dc8c58884c3cc4a8928fb234294e6886 commit 1cce69b9dc8c58884c3cc4a8928fb234294e6886 Author: Alan Modra <amodra@gmail.com> Date: Fri Oct 23 22:23:05 2015 +1030 Handle __start_* and __stop_* symbols in --gc-sections PR ld/11133 PR ld/19161 PR ld/19167 * elflink.c (_bfd_elf_gc_mark_hook): Delete code handling __start_* and __stop_* symbol refs. (_bfd_elf_gc_mark_rsec): Add start_stop parameter. Handle __start_* and __stop_* symbol refs here.. (_bfd_elf_gc_mark_reloc): ..and here. * elf-bfd.h (_bfd_elf_gc_mark_hook): Update prototype. * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Update _bfd_elf_gc_mark_rsec call.