There are many reasons one may want to use a partial linker script, such as rearranging sections. Going with a complete linker script in those cases is most of the time too much of a hassle. See following reduced test case: $ cat > test.c <<EOF __attribute__((section(".foo"))) void foo() {} void bar() {} EOF $ cat > test.ld <<EOF SECTIONS { /DISCARD/ : { *(.foo) } } EOF $ gcc -B gold -o test.so -shared test.c test.ld gold/ld: error: test.ld: SECTIONS seen after other input files; try -T/--script gold/ld: internal error in write_sections, at ../../gold/reloc.cc:830 collect2: error: ld returned 1 exit status So, yeah, sure, test.ld is after other input files, like test.c, but even putting it before test.c doesn't work because, guess what, gcc adds crti.o and crtbeginS.o before test.ld. $ gcc -B gold -Wl,--version collect2 version 4.9.1 gold/ld -plugin /usr/lib/gcc/x86_64-linux-gnu/4.9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJe4jfn.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o -Lgold -L/usr/lib/gcc/x86_64-linux-gnu/4.9 -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../.. --version -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o GNU gold (GNU Binutils for Debian 2.24.51.20140918) 1.11 Copyright (C) 2014 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty. bfd.ld is perfectly happy with the same command line: $ gcc -o test.so -shared test.c test.ld $ readelf -SW test.so | grep foo $ gcc -Wl,--version collect2 version 4.9.1 /usr/bin/ld -plugin /usr/lib/gcc/x86_64-linux-gnu/4.9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper -plugin-opt=-fresolution=/tmp/cceYFA30.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.9 -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../.. --version -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o GNU ld (GNU Binutils for Debian) 2.24.51.20140918 Copyright (C) 2014 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty. Note that when you go past the ordering issue due to the gcc crt files, there are still issues: $ gold/ld -shared -o test.so test.ld test.o $ readelf -lSW test.so There are 14 section headers, starting at offset 0x1288: Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 0000000000000000 001000 000006 00 AX 0 0 1 [ 2] .eh_frame PROGBITS 0000000000000008 001008 000038 00 A 0 0 8 [ 3] .dynsym DYNSYM 0000000000000040 001040 000030 18 A 4 1 8 [ 4] .dynstr STRTAB 0000000000000070 001070 000005 00 A 0 0 1 [ 5] .hash HASH 0000000000000078 001078 000014 04 A 3 0 8 [ 6] .data PROGBITS 000000000000008c 00108c 000000 00 WA 0 0 1 [ 7] .dynamic DYNAMIC 0000000000000090 001090 0000b0 10 WA 4 0 8 [ 8] .bss NOBITS 0000000000000140 001140 000000 00 WA 0 0 1 [ 9] .comment PROGBITS 0000000000000000 001140 00001e 01 MS 0 0 1 [10] .note.gnu.gold-version NOTE 0000000000000000 001160 00001c 00 0 0 4 [11] .symtab SYMTAB 0000000000000000 001180 000078 18 12 3 8 [12] .strtab STRTAB 0000000000000000 0011f8 000019 00 0 0 1 [13] .shstrtab STRTAB 0000000000000000 001211 000075 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) Look where the .text section ends up, compared to when building without test.ld: There are 15 section headers, starting at offset 0x500: Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .dynsym DYNSYM 0000000000000158 000158 000090 18 A 2 1 8 [ 2] .dynstr STRTAB 00000000000001e8 0001e8 000021 00 A 0 0 1 [ 3] .hash HASH 0000000000000210 000210 00002c 04 A 1 0 8 [ 4] .text PROGBITS 000000000000023c 00023c 000006 00 AX 0 0 1 [ 5] .foo PROGBITS 0000000000000242 000242 000006 00 AX 0 0 1 [ 6] .eh_frame PROGBITS 0000000000000248 000248 000058 00 A 0 0 8 [ 7] .dynamic DYNAMIC 00000000000012a0 0002a0 0000b0 10 WA 2 0 8 [ 8] .data PROGBITS 0000000000001350 000350 000000 00 WA 0 0 1 [ 9] .bss NOBITS 0000000000001350 000350 000000 00 WA 0 0 1 [10] .comment PROGBITS 0000000000000000 000350 00001e 01 MS 0 0 1 [11] .note.gnu.gold-version NOTE 0000000000000000 000370 00001c 00 0 0 4 [12] .symtab SYMTAB 0000000000000000 000390 0000c0 18 13 3 8 [13] .strtab STRTAB 0000000000000000 000450 000031 00 0 0 1 [14] .shstrtab STRTAB 0000000000000000 000481 00007a 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) IIRC (I actually hit this problem a while ago, sorry I didn't report earlier), different linker scripts have different side effects.
I believe https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=624208 is the same bug.