gcc 4.7 (not yet released) introduces a new __TMC_END__ global hidden symbol to mark the end of a .tm_clone_table section. When linking a program that doesn't use any tm_clone_table entries the __TMC_END__ symbol is left in .symtab pointing outside any section. For example just compiling an empty program int main(int argc, char **argv) { return 0; } produces on x86_64 with gcc (GCC) 4.7.0 20120119 (Red Hat 4.7.0-0.8) and binutils-2.22-4.fc17.x86_64 a __TMC_END__ symbol in .symtab that looks as follows: 66: 0000000000600850 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__ Section 24 is: [24] .data PROGBITS 0000000000600848 00000848 00000004 0 WA 0 0 4 So the address of __TMC_END__ is outside that section. With gcc < 4.7 the following mimics what happens: $ cat attrsec.c typedef void (*func_ptr) (void); static func_ptr __TMC_LIST__[] __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void*)))) = { }; extern func_ptr __TMC_END__[] __attribute__((__visibility__ ("hidden"))); void deregister_tm_clones (void) { if (__TMC_END__ - __TMC_LIST__ == 0) return; } func_ptr __TMC_END__[] __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void *)))) __attribute__((__visibility__ ("hidden"))) = { }; $ gcc -c attrsec.c $ readelf -a attrsec.o [...] [ 5] .tm_clone_table PROGBITS 0000000000000000 00000068 0000000000000000 0000000000000000 WA 0 0 8 [...] Symbol table '.symtab' contains 12 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS attrsec.c 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 5 6: 0000000000000000 0 OBJECT LOCAL DEFAULT 5 __TMC_LIST__ 7: 0000000000000000 0 SECTION LOCAL DEFAULT 7 8: 0000000000000000 0 SECTION LOCAL DEFAULT 8 9: 0000000000000000 0 SECTION LOCAL DEFAULT 6 10: 0000000000000000 34 FUNC GLOBAL DEFAULT 1 deregister_tm_clones 11: 0000000000000000 0 OBJECT GLOBAL HIDDEN 5 __TMC_END__ $ cat attrsecmain.c int main (int argc, char **argv) { deregister_tm_clones (); return 0; } $ gcc -o attrsec attrsec.o attrsecmain.c $ readelf -a attrsec [...] [24] .data PROGBITS 0000000000600898 00000898 0000000000000004 0000000000000000 WA 0 0 4 [...] 64: 00000000006008a0 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__
Since __TMC_END__ is 0, it is placed in .bss section.
(In reply to comment #1) > Since __TMC_END__ is 0, it is placed in .bss section. O that is interesting. In both my examples the .bss section is right after the section that the .symtab st_shndx field claims the symbol is in. And the address does fall in that section. So are we just seeing some off-by-one issue? Although I would not have expected that because the variables are marked with __attribute__((used, section(".tm_clone_table")), wouldn't that force them in the .tm_clone_table sections? (Which seems to have been purged after the link.)
__TMC_END__ isn't placed in the .bss section. You'd have seen that in the object file. Of course that doesn't happen because there is a section attribute. There is something odd happening though. The .tm_clone_table section is zero sized (which makes sense for all programs that don't use TM). The section is layed out in the map file: .tm_clone_table 0x00000000006008a0 0x0 .tm_clone_table 0x00000000006008a0 0x0 z.o but the section is not present in the output (presumably due to the size being zero?). But the two symbols that were in the section get arbitrarily moved to .data: [24] .data PROGBITS 0000000000600898 00000898 0000000000000004 0000000000000000 WA 0 0 4 ... 69: 00000000006008a0 0 OBJECT GLOBAL HIDDEN 24 __TMC_LIST__ 70: 00000000006008a0 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__ (I adjusted the test case so that the start symbol was also global, so that I could see it in all the output files.) My current guess is that there's some "unused section" pruning code that's triggering to remove the section. My guess is that it should avoid doing that if there are symbols present in the section.
FYI, gold gets this correct: [25] .tm_clone_table PROGBITS 00000000004018c8 000008c8 0000000000000000 0000000000000000 WA 0 0 8 ... 18: 00000000004018c8 0 OBJECT LOCAL HIDDEN 25 __TMC_LIST__ 19: 00000000004018c8 0 OBJECT LOCAL HIDDEN 25 __TMC_END__
GNU ld does indeed drop output sections whose size is zero (with various exceptions and caveats). See strip_excluded_output_sections in ld/ldlang.c. This is done because otherwise all the output sections listed in the linker script would wind up in the output file. gold works differently.
Proposed patch: http://sourceware.org/ml/binutils/2012-01/msg00269.html
CVSROOT: /cvs/src Module name: src Changes by: rth@sourceware.org 2012-02-13 18:08:51 Modified files: bfd : ChangeLog linker.c ld/testsuite : ChangeLog ld/testsuite/ld-elf: warn2.d Log message: PR ld/13621 bfd/ * linker.c (fix_syms): Force symbols outside any section into bfd_abs_section_ptr. ld/testsuite/ * ld-elf/warn2.d: Expect ABS section for Foo. * ld-elf/zerosize1.d, zerosize1.s: New test. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5607&r2=1.5608 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/linker.c.diff?cvsroot=src&r1=1.91&r2=1.92 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1490&r2=1.1491 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/warn2.d.diff?cvsroot=src&r1=1.6&r2=1.7
Fixed.
Thanks for pushing the fix so quickly. I verified it fixes the eu-elflint issues. Note that you forgot to add/commit the new test files: * ld-elf/zerosize1.d, zerosize1.s: New test.
CVSROOT: /cvs/src Module name: src Changes by: rth@sourceware.org 2012-02-14 20:43:26 Modified files: ld/testsuite : ChangeLog Added files: ld/testsuite/ld-elf: zerosize1.d zerosize1.s Log message: PR ld/13621 * ld-elf/zerosize1.d, ld-elf/zerosize1.s: New test. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1492&r2=1.1493 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/zerosize1.d.diff?cvsroot=src&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/zerosize1.s.diff?cvsroot=src&r1=NONE&r2=1.1
CVSROOT: /cvs/src Module name: src Changes by: amodra@sourceware.org 2012-05-05 04:51:16 Modified files: bfd : ChangeLog linker.c ld/testsuite : ChangeLog ld/testsuite/ld-elf: warn2.d Removed files: ld/testsuite/ld-elf: zerosize1.d zerosize1.s Log message: PR ld/14052 PR ld/13621 bfd/ * linker.c (_bfd_nearby_section): Revert 2012-02-13 change. ld/testsuite/ * ld-elf/warn2.d: Revert 2012-02-13 change. * ld-elf/zerosize1.d, ld-elf/zerosize1.s: Delete. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5669&r2=1.5670 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/linker.c.diff?cvsroot=src&r1=1.94&r2=1.95 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1518&r2=1.1519 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/warn2.d.diff?cvsroot=src&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/zerosize1.d.diff?cvsroot=src&r1=1.2&r2=NONE http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-elf/zerosize1.s.diff?cvsroot=src&r1=1.1&r2=NONE
Reopening since I've just reverted the fix that was applied for this bug. Making symbols absolute just isn't a good idea. See http://sourceware.org/bugzilla/show_bug.cgi?id=14052
I don't see any reason why a symbol can't be defined at the end of a section (ie. section vma + section size), which is what happens now.