When compiling GCC 4.7 on Fedora 15 with systemtap-sdt-devel-1.4-9.fc15.x86_64, x64-64 unwind-dw2.s has .pushsection .note.stapsdt,"?","note" .balign 4 .4byte 992f-991f,994f-993f,3 991: .asciz "stapsdt" 992: .balign 4 993: .8byte 990b .8byte _.stapsdt.base .8byte 0 .asciz "libgcc" .asciz "unwind" .asciz "8@%rdi 8@%rsi" 994: .balign 4 .popsection # 0 "" 2 # 1555 "/export/gnu/import/git/gcc-x32/libgcc/../gcc/unwind-dw2.c" 1 .ifndef _.stapsdt.base .pushsection .stapsdt.base,"aG","progbits",.stapsdt.base,comdat .weak _.stapsdt.base .hidden _.stapsdt.base _.stapsdt.base: .space 1 .size _.stapsdt.base,1 It is unsafe since .stapsdt.base section may be deleted by another .stapsdt.base section group and it leads to undefined reference error in .note.stapsdt section. 2 sections must be put in the same section group.
The intention is that the .note.stapsdt gets into the same section group as the section it is defined in. That is what the "?" .pushsection flag is about. Are you are saying the .stapsdt.base section should be in the same section group? But I believe we only want one .stapsdt.base section, that is why it is in a comdat group, so that duplicates can be deleted. And nothing in the .stapsdt.base section refers to anything else. It is just there to detect the prelinking address adjustment. I am probably missing the exact scenario when this causes an issue. Could you post a fuller example that shows the actual error you see?
Please build and run "make check" GCC mainline on Fedora 15/x86. I see `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(libc-lowlevellock.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(dl-lookup.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(setjmp.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(__longjmp.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(__longjmp.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(dl-runtime.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/../lib/libc.a(dl-runtime.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o)^M [hjl@gnu-33 tmp]$ readelf -Sg bsd-_setjmp.o There are 14 section headers, starting at offset 0x15c: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .group GROUP 00000000 000034 000008 04 12 2 4 [ 2] .text PROGBITS 00000000 000040 000037 00 AX 0 0 16 [ 3] .data PROGBITS 00000000 000078 000000 00 WA 0 0 4 [ 4] .bss NOBITS 00000000 000078 000000 00 WA 0 0 4 [ 5] .note.stapsdt NOTE 00000000 000078 000040 00 0 0 4 [ 6] .rel.note.stapsdt REL 00000000 000454 000010 08 12 5 4 [ 7] .stapsdt.base PROGBITS 00000000 0000b8 000001 00 AG 0 0 1 [ 8] .note.GNU-stack PROGBITS 00000000 0000b9 000000 00 0 0 1 [ 9] .eh_frame PROGBITS 00000000 0000bc 00002c 00 A 0 0 4 [10] .rel.eh_frame REL 00000000 000464 000008 08 12 9 4 [11] .shstrtab STRTAB 00000000 0000e8 000071 00 0 0 1 [12] .symtab SYMTAB 00000000 00038c 0000b0 10 13 9 4 [13] .strtab STRTAB 00000000 00043c 000018 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) COMDAT group section [ 1] `.group' [.stapsdt.base] contains 1 sections: [Index] Name [ 7] .stapsdt.base [hjl@gnu-33 tmp]$ .stapsdt.base and .note.stapsdt aren't in the same section group.
(In reply to comment #2) > Please build and run "make check" GCC mainline on Fedora 15/x86. > I see > > `_.stapsdt.base' referenced in section `.note.stapsdt' of > /usr/lib/../lib/libc.a(libc-lowlevellock.o): defined in discarded section > `.stapsdt.base[.stapsdt.base]' of /usr/lib/../lib/libc.a(bsd-_setjmp.o) I'll try and replicate. But don't currently have such a setup. > [hjl@gnu-33 tmp]$ readelf -Sg bsd-_setjmp.o > There are 14 section headers, starting at offset 0x15c: > > Section Headers: > [Nr] Name Type Addr Off Size ES Flg Lk Inf > Al > [...] > [ 5] .note.stapsdt NOTE 00000000 000078 000040 00 0 0 > 4 > [ 6] .rel.note.stapsdt REL 00000000 000454 000010 08 12 5 > 4 > [ 7] .stapsdt.base PROGBITS 00000000 0000b8 000001 00 AG 0 0 > 1 > [...] > Key to Flags: > W (write), A (alloc), X (execute), M (merge), S (strings) > I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) > O (extra OS processing required) o (OS specific), p (processor specific) > > COMDAT group section [ 1] `.group' [.stapsdt.base] contains 1 sections: > [Index] Name > [ 7] .stapsdt.base > [hjl@gnu-33 tmp]$ > > .stapsdt.base and .note.stapsdt aren't in the same section group. Why does it matter whether they are in the same section group or not? .stapsdt.base is in a comdat group, and so one copy will always be retained. It looks like the linker is picking the wrong section, one that does get discarded. While ignoring the section that is being kept and should be used to link against. I am curious why we haven't seen this before. Against which binutils/linker is this?
(In reply to comment #3) > > Why does it matter whether they are in the same section group or not? > .stapsdt.base is in a comdat group, and so one copy will always be retained. > > It looks like the linker is picking the wrong section, one that does get > discarded. While ignoring the section that is being kept and should be used to > link against. No. Linker is correct. YOU CAN'T HAVE LOCAL REFERENCES OUTSIDE OF A COMDAT GROUP. In your case, you have .pushsection .note.stapsdt,"?","note" .balign 4 .4byte 992f-991f,994f-993f,3 991: .asciz "stapsdt" 992: .balign 4 993: .8byte 990b .8byte _.stapsdt.base .8byte 0 .asciz "libgcc" .asciz "unwind" .asciz "8@%rdi 8@%rsi" 994: .balign 4 .popsection # 0 "" 2 # 1555 "/export/gnu/import/git/gcc-x32/libgcc/../gcc/unwind-dw2.c" 1 .ifndef _.stapsdt.base .pushsection .stapsdt.base,"aG","progbits",.stapsdt.base,comdat .weak _.stapsdt.base .hidden _.stapsdt.base _.stapsdt.base: .space 1 .size _.stapsdt.base,1 Non comdat member section, .note.stapsdt, has a local reference of _.stapsdt.base, which is defined in a comdat section. Did you mean to put .note.stapsdt section in the same comdat group as .stapsdt.base section? > I am curious why we haven't seen this before. > Against which binutils/linker is this? You need glibc with systemtap support, like Fedora 15, to see the problem: [hjl@gnu-6 tmp]$ cat gcsec-1.c /* AIX gld supports garbage collection. But AIX gcc does not support -ffunction-sections or -fdata-sections. */ /* { dg-do run { xfail rs6000-*-aix* powerpc*-*-aix* } } */ /* { dg-require-gc-sections "" } */ /* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections" } */ /* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections -static" { target static } } */ #include <stdlib.h> static int unusedint=5; static int usedint=1; int unused(void) { return 1; } int foo(void) { return usedint; } int main(void) { if (foo()) exit(0); else abort(); } [hjl@gnu-6 tmp]$ gcc gcsec-1.c -ffunction-sections -fdata-sections -Wl,--gc-sections -static -B/usr/bin/ `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(setjmp.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(dl-lookup.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(__longjmp.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(__longjmp.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(dl-runtime.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(dl-runtime.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(dl-sym.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/libgcc_eh.a(unwind-dw2.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) `.text' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(fork.o): defined in discarded section `.text' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(fork.o) `_.stapsdt.base' referenced in section `.note.stapsdt' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(fork.o): defined in discarded section `.stapsdt.base[.stapsdt.base]' of /usr/lib/gcc/x86_64-redhat-linux/4.6.0/../../../../lib64/libc.a(libc-lowlevellock.o) collect2: ld returned 1 exit status [hjl@gnu-6 tmp]$
(In reply to comment #4) > No. Linker is correct. YOU CAN'T HAVE LOCAL REFERENCES OUTSIDE OF > A COMDAT GROUP. I assume you are referring to gabi: "To facilitate removing a group without leaving dangling references and with only minimal processing of the symbol table, the following rules must be followed: A symbol table entry with STB_GLOBAL or STB_WEAK binding that is defined relative to one of a group's sections, and that is contained in a symbol table section that is not part of the group, must be converted to an undefined symbol (its section index must be changed to SHN_UNDEF) if the group members are discarded. References to this symbol table entry from outside the group are allowed." > Non comdat member section, .note.stapsdt, has a local > reference of _.stapsdt.base, which is defined in a comdat > section. Did you mean to put .note.stapsdt section in the same > comdat group as .stapsdt.base section? No. It is deliberately in its own COMDAT group to make sure there is only one .stapsdt.base section in the final object. > > I am curious why we haven't seen this before. > > Against which binutils/linker is this? > > You need glibc with systemtap support, like Fedora 15, to > see the problem: > [...] > [hjl@gnu-6 tmp]$ gcc gcsec-1.c -ffunction-sections -fdata-sections > -Wl,--gc-sections -static -B/usr/bin/ Thanks for that testcase. So it is --gc-sections that is removing the .stapsdt.base section because the linker thinks it is unused. hmmm. tricky. When is --gc-sections used?
(In reply to comment #5) > (In reply to comment #4) > > No. Linker is correct. YOU CAN'T HAVE LOCAL REFERENCES OUTSIDE OF > > A COMDAT GROUP. > > I assume you are referring to gabi: > > "To facilitate removing a group without leaving dangling references and with > only minimal processing of the symbol table, the following rules must be > followed: > > A symbol table entry with STB_GLOBAL or STB_WEAK binding that is defined ^^^^^^^^^^^^^^^^^^^^^^^ You missed the key part. > relative to one of a group's sections, and that is contained in a symbol table > section that is not part of the group, must be converted to an undefined symbol > (its section index must be changed to SHN_UNDEF) if the group members are > discarded. References to this symbol table entry from outside the group are > allowed." > > > > Non comdat member section, .note.stapsdt, has a local > > reference of _.stapsdt.base, which is defined in a comdat > > section. Did you mean to put .note.stapsdt section in the same > > comdat group as .stapsdt.base section? > > No. It is deliberately in its own COMDAT group to make sure there is only one > .stapsdt.base section in the final object. > Then don't make symbol defined in .stapsdt.base section referenced from other files local.
I will take a look. It may be a linker bug.
[hjl@gnu-6 pr12851]$ make clean rm -f a.out x [hjl@gnu-6 pr12851]$ cat foo.s .section .note.stapsdt,"?","note" .dc.a _.stapsdt.base .section .stapsdt.base,"aG","progbits",.stapsdt.base,comdat _.stapsdt.base: .space 1 .size _.stapsdt.base,1 [hjl@gnu-6 pr12851]$ cat bar.s .section .note.stapsdt,"?","note" .dc.a _.stapsdt.base .section .stapsdt.base,"aG","progbits",.stapsdt.base,comdat .weak _.stapsdt.base _.stapsdt.base: .space 1 .size _.stapsdt.base,1 [hjl@gnu-6 pr12851]$ cat start.s .text .global start /* Used by SH targets. */ start: .global _start _start: .global __start __start: .global main /* Used by HPPA targets. */ main: .dc.a 0 [hjl@gnu-6 pr12851]$ make x ./ld --gc-sections -o x foo1.o foo2.o start.o `_.stapsdt.base' referenced in section `.note.stapsdt' of foo1.o: defined in discarded section `.stapsdt.base[.stapsdt.base]' of foo1.o `_.stapsdt.base' referenced in section `.note.stapsdt' of foo2.o: defined in discarded section `.stapsdt.base[.stapsdt.base]' of foo2.o make: *** [x] Error 1 [hjl@gnu-6 pr12851]$ make y ./ld --gc-sections -o y bar1.o bar2.o start.o `_.stapsdt.base' referenced in section `.note.stapsdt' of bar1.o: defined in discarded section `.stapsdt.base[.stapsdt.base]' of bar1.o `_.stapsdt.base' referenced in section `.note.stapsdt' of bar2.o: defined in discarded section `.stapsdt.base[.stapsdt.base]' of bar1.o make: *** [y] Error 1 [hjl@gnu-6 pr12851]$
A patch is posted at http://sourceware.org/ml/binutils/2011-06/msg00107.html
CVSROOT: /cvs/src Module name: src Changes by: hjl@sourceware.org 2011-06-09 04:52:15 Modified files: bfd : ChangeLog elflink.c ld/testsuite : ChangeLog Added files: ld/testsuite/ld-elf: pr12851.d pr12851.s Log message: Check relocations in note sections for --gc-sections. bfd/ 2011-06-08 H.J. Lu <hongjiu.lu@intel.com> PR ld/12851 * elflink.c (elf_gc_sweep): Don't check SHT_NOTE sections here. (bfd_elf_gc_sections): Also check SHT_NOTE sections. ld/testsuite/ 2011-06-08 H.J. Lu <hongjiu.lu@intel.com> PR ld/12851 * ld-elf/pr12851.d: New. * ld-elf/pr12851.s: Likewise. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5375&r2=1.5376 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elflink.c.diff?cvsroot=src&r1=1.407&r2=1.408 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1420&r2=1.1421 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/pr12851.d.diff?cvsroot=src&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/pr12851.s.diff?cvsroot=src&r1=NONE&r2=1.1
Fixed.
CVSROOT: /cvs/src Module name: src Changes by: amodra@sourceware.org 2011-06-14 02:45:12 Modified files: bfd : ChangeLog elflink.c elf-bfd.h elfxx-target.h elf32-arm.c elf32-tic6x.c Log message: PR ld/12851 * elflink.c (_bfd_elf_gc_mark_extra_sections): New function. (elf_gc_sweep): Don't treat debug and sections like .comment specially here. (bfd_elf_gc_sections): Treat note sections as gc roots only when not part of a group. Always call gc_mark_extra_sections. * elf-bfd.h (_bfd_elf_gc_mark_extra_sections): Declare. * elfxx-target.h (elf_backend_gc_mark_extra_sections): Default to _bfd_elf_gc_mark_extra_sections. * elf32-arm.c (elf32_arm_gc_mark_extra_sections): Call _bfd_elf_gc_mark_extra_sections. * elf32-tic6x.c (elf32_tic6x_gc_mark_extra_sections): Likewise. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5384&r2=1.5385 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elflink.c.diff?cvsroot=src&r1=1.410&r2=1.411 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf-bfd.h.diff?cvsroot=src&r1=1.321&r2=1.322 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elfxx-target.h.diff?cvsroot=src&r1=1.125&r2=1.126 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf32-arm.c.diff?cvsroot=src&r1=1.270&r2=1.271 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf32-tic6x.c.diff?cvsroot=src&r1=1.25&r2=1.26
CVSROOT: /cvs/src Module name: src Changes by: amodra@sourceware.org 2011-06-14 02:46:58 Modified files: ld/testsuite : ChangeLog ld/testsuite/ld-elf: pr12851.d Log message: PR ld/12851 * ld-elf/pr12851.d: Correct target selection and comment. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1425&r2=1.1426 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/pr12851.d.diff?cvsroot=src&r1=1.1&r2=1.2