[PATCH 3/3] build system: section garbage collection - main part

From: Denys Vlasenko
Date: Sat Nov 24 2007 - 18:18:54 EST


On Saturday 24 November 2007 15:14, Denys Vlasenko wrote:
> 3.gc
> The meat of the patchset is here.
> Introduce config option DISCARD_UNUSED_SECTIONS.
> If it is selected:
> Pass -ffunction-sections -fdata-sections to gcc and
> --gc-sections --print-gc-sections to ld.
> Use arch/$(SRCARCH)/kernel/modules.lds.S linker script for linking *.ko
> files.
> Generate linker map files for vmlinux and modules.
> Add *(.text.*), *(.data.*) wildcards to linker scripts to accomodate
> new kinds of sections generated by gcc.
> Add KEEP(<sections>) directives to sections which must not be
> discarded. Fix arch/frv/Makefile to use DISCARD_UNUSED_SECTIONS instead
> of what seems to be a vestigial custom solution.

Signed-off-by: Denys Vlasenko <vda.linux@xxxxxxxxxxxxxx>
--
vda
diff -urpN linux-2.6.gc2/Makefile linux-2.6.gc3/Makefile
--- linux-2.6.gc2/Makefile 2007-11-23 18:55:08.000000000 -0800
+++ linux-2.6.gc3/Makefile 2007-11-24 14:46:38.000000000 -0800
@@ -526,6 +526,11 @@ KBUILD_CFLAGS += $(call cc-optio
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)

+ifdef CONFIG_DISCARD_UNUSED_SECTIONS
+CFLAGS += $(call cc-option, -ffunction-sections -fdata-sections)
+LDFLAGS_vmlinux += --gc-sections --print-gc-sections -Map vmlinux.map
+endif
+
# warn about C99 declaration after statement
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)

@@ -924,6 +929,7 @@ prepare: prepare0
# done in arch/$(ARCH)/kernel/Makefile

export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
+export CPPFLAGS_modules.lds += -P -C -U$(ARCH)

# The asm symlink changes when $(ARCH) changes.
# Detect this and ask user to run make mrproper
diff -urpN linux-2.6.gc2/arch/alpha/boot/bootloader.lds linux-2.6.gc3/arch/alpha/boot/bootloader.lds
--- linux-2.6.gc2/arch/alpha/boot/bootloader.lds 2007-11-23 18:55:08.000000000 -0800
+++ linux-2.6.gc3/arch/alpha/boot/bootloader.lds 2007-11-23 21:22:59.000000000 -0800
@@ -4,17 +4,17 @@ printk = srm_printk;
SECTIONS
{
. = 0x20000000;
- .text : { *(.text) }
+ .text : { *(.text) *(.text.*) }
_etext = .;
PROVIDE (etext = .);
.rodata : { *(.rodata) *(.rodata.*) }
- .data : { *(.data) CONSTRUCTORS }
+ .data : { *(.data) *(.data.*) CONSTRUCTORS }
.got : { *(.got) }
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
.sbss : { *(.sbss) *(.scommon) }
- .bss : { *(.bss) *(COMMON) }
+ .bss : { *(.bss) *(.bss.*) *(COMMON) }
_end = . ;
PROVIDE (end = .);

diff -urpN linux-2.6.gc2/arch/alpha/kernel/vmlinux.lds.S linux-2.6.gc3/arch/alpha/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/alpha/kernel/vmlinux.lds.S 2007-11-23 20:55:55.000000000 -0800
+++ linux-2.6.gc3/arch/alpha/kernel/vmlinux.lds.S 2007-11-23 21:30:54.000000000 -0800
@@ -129,6 +129,7 @@ SECTIONS
}
.bss : {
*(.bss)
+ *(.bss.*)
*(COMMON)
}
__bss_stop = .;
diff -urpN linux-2.6.gc2/arch/arm/boot/bootp/bootp.lds linux-2.6.gc3/arch/arm/boot/bootp/bootp.lds
--- linux-2.6.gc2/arch/arm/boot/bootp/bootp.lds 2007-11-23 18:55:08.000000000 -0800
+++ linux-2.6.gc3/arch/arm/boot/bootp/bootp.lds 2007-11-23 21:23:15.000000000 -0800
@@ -15,7 +15,7 @@ SECTIONS
.text : {
_stext = .;
*(.start)
- *(.text)
+ *(.text .text.*)
initrd_size = initrd_end - initrd_start;
_etext = .;
}
diff -urpN linux-2.6.gc2/arch/arm/boot/compressed/vmlinux.lds.in linux-2.6.gc3/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-2.6.gc2/arch/arm/boot/compressed/vmlinux.lds.in 2007-11-23 18:55:08.000000000 -0800
+++ linux-2.6.gc3/arch/arm/boot/compressed/vmlinux.lds.in 2007-11-23 21:24:25.000000000 -0800
@@ -35,12 +35,12 @@ SECTIONS
.got : { *(.got) }
_got_end = .;
.got.plt : { *(.got.plt) }
- .data : { *(.data) }
+ .data : { *(.data) *(.data.*) }
_edata = .;

. = BSS_START;
__bss_start = .;
- .bss : { *(.bss) }
+ .bss : { *(.bss) *(.bss.*) }
_end = .;

.stack (NOLOAD) : { *(.stack) }
diff -urpN linux-2.6.gc2/arch/arm/kernel/vmlinux.lds.S linux-2.6.gc3/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/arm/kernel/vmlinux.lds.S 2007-11-23 20:55:54.000000000 -0800
+++ linux-2.6.gc3/arch/arm/kernel/vmlinux.lds.S 2007-11-23 21:31:04.000000000 -0800
@@ -169,6 +169,7 @@ SECTIONS
.bss : {
__bss_start = .; /* BSS */
*(.bss)
+ *(.bss.*)
*(COMMON)
_end = .;
}
diff -urpN linux-2.6.gc2/arch/avr32/kernel/vmlinux.lds.S linux-2.6.gc3/arch/avr32/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/avr32/kernel/vmlinux.lds.S 2007-11-23 20:55:53.000000000 -0800
+++ linux-2.6.gc3/arch/avr32/kernel/vmlinux.lds.S 2007-11-23 21:31:12.000000000 -0800
@@ -124,6 +124,7 @@ SECTIONS
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
__bss_start = .;
*(.bss)
+ *(.bss.*)
*(COMMON)
. = ALIGN(8);
__bss_stop = .;
diff -urpN linux-2.6.gc2/arch/cris/arch-v10/vmlinux.lds.S linux-2.6.gc3/arch/cris/arch-v10/vmlinux.lds.S
--- linux-2.6.gc2/arch/cris/arch-v10/vmlinux.lds.S 2007-11-23 20:55:56.000000000 -0800
+++ linux-2.6.gc3/arch/cris/arch-v10/vmlinux.lds.S 2007-11-23 21:31:19.000000000 -0800
@@ -104,6 +104,7 @@ SECTIONS
.bss : {
*(COMMON)
*(.bss)
+ *(.bss.*)
}

. = ALIGN (0x20);
diff -urpN linux-2.6.gc2/arch/cris/arch-v32/vmlinux.lds.S linux-2.6.gc3/arch/cris/arch-v32/vmlinux.lds.S
--- linux-2.6.gc2/arch/cris/arch-v32/vmlinux.lds.S 2007-11-23 20:55:56.000000000 -0800
+++ linux-2.6.gc3/arch/cris/arch-v32/vmlinux.lds.S 2007-11-23 21:31:26.000000000 -0800
@@ -116,6 +116,7 @@ SECTIONS
.bss : {
*(COMMON)
*(.bss)
+ *(.bss.*)
}

. = ALIGN (0x20);
diff -urpN linux-2.6.gc2/arch/frv/Makefile linux-2.6.gc3/arch/frv/Makefile
--- linux-2.6.gc2/arch/frv/Makefile 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/frv/Makefile 2007-11-23 21:50:49.000000000 -0800
@@ -52,7 +52,9 @@ endif

#LDFLAGS_vmlinux := -Map linkmap.txt

-ifdef CONFIG_GC_SECTIONS
+# Is this needed? We do this already in kernel's top-level Makefile.
+# Also $(LINKFLAGS) seems to be unused.
+ifdef CONFIG_DISCARD_UNUSED_SECTIONS
KBUILD_CFLAGS += -ffunction-sections -fdata-sections
LINKFLAGS += --gc-sections
endif
diff -urpN linux-2.6.gc2/arch/h8300/boot/compressed/vmlinux.lds linux-2.6.gc3/arch/h8300/boot/compressed/vmlinux.lds
--- linux-2.6.gc2/arch/h8300/boot/compressed/vmlinux.lds 2007-11-23 20:55:45.000000000 -0800
+++ linux-2.6.gc3/arch/h8300/boot/compressed/vmlinux.lds 2007-11-23 21:25:10.000000000 -0800
@@ -5,13 +5,13 @@ SECTIONS
__stext = . ;
__text = .;
*(.startup.text)
- *(.text)
+ *(.text) *(.text.*)
__etext = . ;
}

.rodata :
{
- *(.rodata)
+ *(.rodata) *(.rodata.*)
}
.data :

diff -urpN linux-2.6.gc2/arch/ia64/hp/sim/boot/bootloader.lds linux-2.6.gc3/arch/ia64/hp/sim/boot/bootloader.lds
--- linux-2.6.gc2/arch/ia64/hp/sim/boot/bootloader.lds 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/ia64/hp/sim/boot/bootloader.lds 2007-11-23 21:25:44.000000000 -0800
@@ -7,13 +7,13 @@ SECTIONS
. = 0x100000;

_text = .;
- .text : { *(__ivt_section) *(.text) }
+ .text : { *(__ivt_section) *(.text) *(.text.*) }
_etext = .;

/* Global data */
_data = .;
.rodata : { *(.rodata) *(.rodata.*) }
- .data : { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
+ .data : { *(.data) *(.data.*) *(.gnu.linkonce.d*) CONSTRUCTORS }
__gp = ALIGN (8) + 0x200000;
.got : { *(.got.plt) *(.got) }
/* We want the small data sections together, so single-instruction offsets
@@ -24,7 +24,7 @@ SECTIONS

_bss = .;
.sbss : { *(.sbss) *(.scommon) }
- .bss : { *(.bss) *(COMMON) }
+ .bss : { *(.bss) *(.bss.*) *(COMMON) }
. = ALIGN(64 / 8);
_end = . ;

diff -urpN linux-2.6.gc2/arch/ia64/kernel/vmlinux.lds.S linux-2.6.gc3/arch/ia64/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/ia64/kernel/vmlinux.lds.S 2007-11-23 20:55:59.000000000 -0800
+++ linux-2.6.gc3/arch/ia64/kernel/vmlinux.lds.S 2007-11-23 21:31:52.000000000 -0800
@@ -244,7 +244,7 @@ SECTIONS
.sbss : AT(ADDR(.sbss) - LOAD_OFFSET)
{ *(.sbss) *(.scommon) }
.bss : AT(ADDR(.bss) - LOAD_OFFSET)
- { *(.bss) *(COMMON) }
+ { *(.bss) *(.bss.*) *(COMMON) }

_end = .;

diff -urpN linux-2.6.gc2/arch/ia64/scripts/check-segrel.lds linux-2.6.gc3/arch/ia64/scripts/check-segrel.lds
--- linux-2.6.gc2/arch/ia64/scripts/check-segrel.lds 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/ia64/scripts/check-segrel.lds 2007-11-23 21:28:43.000000000 -0800
@@ -1,9 +1,9 @@
SECTIONS {
. = SIZEOF_HEADERS;
- .rodata : { *(.rodata) } :ro
+ .rodata : { *(.rodata) *(.rodata.*) } :ro
.note : { *(.note*) }
. = 0xa0000;
- .data : { *(.data) } :dat
+ .data : { *(.data) *(.data.*) } :dat
/DISCARD/ : { *(*) }
}
PHDRS {
diff -urpN linux-2.6.gc2/arch/m32r/boot/compressed/vmlinux.lds.S linux-2.6.gc3/arch/m32r/boot/compressed/vmlinux.lds.S
--- linux-2.6.gc2/arch/m32r/boot/compressed/vmlinux.lds.S 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/m32r/boot/compressed/vmlinux.lds.S 2007-11-23 21:27:15.000000000 -0800
@@ -6,12 +6,12 @@ SECTIONS
. = CONFIG_MEMORY_START + 0x00400000;

_text = .;
- .text : { *(.text) } = 0
+ .text : { *(.text) *(.text.*) } = 0
.rodata : { *(.rodata) *(.rodata.*) }
_etext = .;

. = ALIGN(32 / 8);
- .data : { *(.data) }
+ .data : { *(.data) *(.data.*) }
. = ALIGN(32 / 8);
_got = .;
.got : { *(.got) _egot = .; *(.got.*) }
@@ -19,7 +19,7 @@ SECTIONS

. = ALIGN(32 / 8);
__bss_start = .;
- .bss : { *(.bss) *(.sbss) }
+ .bss : { *(.bss) *(.bss.*) *(.sbss) }
. = ALIGN(32 / 8);
_ebss = .;
. = ALIGN(4096);
diff -urpN linux-2.6.gc2/arch/m32r/kernel/vmlinux.lds.S linux-2.6.gc3/arch/m32r/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/m32r/kernel/vmlinux.lds.S 2007-11-23 20:55:57.000000000 -0800
+++ linux-2.6.gc3/arch/m32r/kernel/vmlinux.lds.S 2007-11-23 21:32:02.000000000 -0800
@@ -116,7 +116,7 @@ SECTIONS
/* freed after init ends here */

__bss_start = .; /* BSS */
- .bss : { *(.bss) }
+ .bss : { *(.bss) *(.bss.*) }
. = ALIGN(4);
__bss_stop = .;

diff -urpN linux-2.6.gc2/arch/m68k/kernel/vmlinux-std.lds linux-2.6.gc3/arch/m68k/kernel/vmlinux-std.lds
--- linux-2.6.gc2/arch/m68k/kernel/vmlinux-std.lds 2007-11-23 20:55:53.000000000 -0800
+++ linux-2.6.gc3/arch/m68k/kernel/vmlinux-std.lds 2007-11-23 21:32:16.000000000 -0800
@@ -33,7 +33,7 @@ SECTIONS
CONSTRUCTORS
}

- .bss : { *(.bss) } /* BSS */
+ .bss : { *(.bss) *(.bss.*) } /* BSS */

. = ALIGN(16);
.cacheline_aligned.data : { *(.cacheline_aligned.data) } :data
diff -urpN linux-2.6.gc2/arch/m68k/kernel/vmlinux-sun3.lds linux-2.6.gc3/arch/m68k/kernel/vmlinux-sun3.lds
--- linux-2.6.gc2/arch/m68k/kernel/vmlinux-sun3.lds 2007-11-23 20:55:53.000000000 -0800
+++ linux-2.6.gc3/arch/m68k/kernel/vmlinux-sun3.lds 2007-11-23 21:32:10.000000000 -0800
@@ -71,7 +71,7 @@ __init_begin = .;
.init.task.data : { *(.init_task.data) }


- .bss : { *(.bss) } /* BSS */
+ .bss : { *(.bss) *(.bss.*) } /* BSS */

_end = . ;

diff -urpN linux-2.6.gc2/arch/m68knommu/kernel/vmlinux.lds.S linux-2.6.gc3/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/m68knommu/kernel/vmlinux.lds.S 2007-11-23 20:55:53.000000000 -0800
+++ linux-2.6.gc3/arch/m68knommu/kernel/vmlinux.lds.S 2007-11-23 21:32:23.000000000 -0800
@@ -179,6 +179,7 @@ SECTIONS {
. = ALIGN(4);
_sbss = . ;
*(.bss)
+ *(.bss.*)
*(COMMON)
. = ALIGN(4) ;
_ebss = . ;
diff -urpN linux-2.6.gc2/arch/mips/kernel/vmlinux.lds.S linux-2.6.gc3/arch/mips/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/mips/kernel/vmlinux.lds.S 2007-11-23 20:55:54.000000000 -0800
+++ linux-2.6.gc3/arch/mips/kernel/vmlinux.lds.S 2007-11-23 21:32:30.000000000 -0800
@@ -169,6 +169,7 @@ SECTIONS
}
.bss : {
*(.bss)
+ *(.bss.*)
*(COMMON)
}
__bss_stop = .;
diff -urpN linux-2.6.gc2/arch/parisc/kernel/vmlinux.lds.S linux-2.6.gc3/arch/parisc/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/parisc/kernel/vmlinux.lds.S 2007-11-23 20:56:00.000000000 -0800
+++ linux-2.6.gc3/arch/parisc/kernel/vmlinux.lds.S 2007-11-23 21:32:37.000000000 -0800
@@ -141,6 +141,7 @@ SECTIONS
}
.bss : {
*(.bss)
+ *(.bss.*)
*(COMMON)
}
__bss_stop = .;
diff -urpN linux-2.6.gc2/arch/powerpc/boot/zImage.coff.lds.S linux-2.6.gc3/arch/powerpc/boot/zImage.coff.lds.S
--- linux-2.6.gc2/arch/powerpc/boot/zImage.coff.lds.S 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/powerpc/boot/zImage.coff.lds.S 2007-11-23 21:22:04.000000000 -0800
@@ -7,7 +7,7 @@ SECTIONS
_start = .;
.text :
{
- *(.text)
+ *(.text .text.*)
*(.fixup)
}
_etext = .;
@@ -41,7 +41,7 @@ SECTIONS
.bss :
{
*(.sbss)
- *(.bss)
+ *(.bss .bss.*)
}
_end = . ;

diff -urpN linux-2.6.gc2/arch/powerpc/boot/zImage.lds.S linux-2.6.gc3/arch/powerpc/boot/zImage.lds.S
--- linux-2.6.gc2/arch/powerpc/boot/zImage.lds.S 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/powerpc/boot/zImage.lds.S 2007-11-23 21:32:48.000000000 -0800
@@ -8,6 +8,7 @@ SECTIONS
.text :
{
*(.text)
+ *(.text.*)
*(.fixup)
}
_etext = .;
@@ -46,6 +47,7 @@ SECTIONS
{
*(.sbss)
*(.bss)
+ *(.bss.*)
}
. = ALIGN(4096);
_end = . ;
diff -urpN linux-2.6.gc2/arch/powerpc/boot/zImage.ps3.lds.S linux-2.6.gc3/arch/powerpc/boot/zImage.ps3.lds.S
--- linux-2.6.gc2/arch/powerpc/boot/zImage.ps3.lds.S 2007-11-23 18:55:09.000000000 -0800
+++ linux-2.6.gc3/arch/powerpc/boot/zImage.ps3.lds.S 2007-11-23 21:26:51.000000000 -0800
@@ -21,6 +21,7 @@ SECTIONS
.text :
{
*(.text)
+ *(.text.*)
*(.fixup)
}
_etext = .;
@@ -44,6 +45,7 @@ SECTIONS
{
*(.sbss)
*(.bss)
+ *(.bss.*)
}
. = ALIGN(4096);
_end = . ;
diff -urpN linux-2.6.gc2/arch/powerpc/kernel/vmlinux.lds.S linux-2.6.gc3/arch/powerpc/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/powerpc/kernel/vmlinux.lds.S 2007-11-23 20:55:55.000000000 -0800
+++ linux-2.6.gc3/arch/powerpc/kernel/vmlinux.lds.S 2007-11-23 21:32:54.000000000 -0800
@@ -37,7 +37,7 @@ SECTIONS
ALIGN_FUNCTION();
*(.head.text)
_text = .;
- *(.text .fixup .init.refok.text .exit.text.refok)
+ *(.text *(.text.*) .fixup .init.refok.text .exit.text.refok)
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
@@ -240,6 +240,7 @@ SECTIONS
*(.sbss) *(.scommon)
*(.dynbss)
*(.bss)
+ *(.bss.*)
*(COMMON)
__bss_stop = .;
}
diff -urpN linux-2.6.gc2/arch/ppc/kernel/vmlinux.lds.S linux-2.6.gc3/arch/ppc/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/ppc/kernel/vmlinux.lds.S 2007-11-23 20:55:54.000000000 -0800
+++ linux-2.6.gc3/arch/ppc/kernel/vmlinux.lds.S 2007-11-23 21:33:01.000000000 -0800
@@ -154,6 +154,7 @@ SECTIONS
*(.sbss) *(.scommon)
*(.dynbss)
*(.bss)
+ *(.bss.*)
*(COMMON)
}
__bss_stop = .;
diff -urpN linux-2.6.gc2/arch/s390/kernel/vmlinux.lds.S linux-2.6.gc3/arch/s390/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/s390/kernel/vmlinux.lds.S 2007-11-23 20:55:57.000000000 -0800
+++ linux-2.6.gc3/arch/s390/kernel/vmlinux.lds.S 2007-11-23 21:33:07.000000000 -0800
@@ -142,6 +142,7 @@ SECTIONS
.bss : {
__bss_start = .;
*(.bss)
+ *(.bss.*)
. = ALIGN(2);
__bss_stop = .;
}
diff -urpN linux-2.6.gc2/arch/sh/kernel/vmlinux.lds.S linux-2.6.gc3/arch/sh/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/sh/kernel/vmlinux.lds.S 2007-11-23 22:00:09.000000000 -0800
+++ linux-2.6.gc3/arch/sh/kernel/vmlinux.lds.S 2007-11-23 21:33:16.000000000 -0800
@@ -115,8 +115,17 @@ SECTIONS
.bss : {
__init_end = .;
__bss_start = .; /* BSS */
+
+ /* Why such strage name - .bss.k.page_aligned?
+ * .bss.page_aligned may clash with a section produced by gcc -fdata_sections.
+ * .bss_page_aligned, .page_aligned_bss will not work because
+ * we must use .bss.xxx section names for zero-initialized sections
+ * we want to combine into bss, otherwise gcc does not set
+ * 'nobits' flag for the section, and it cannot be merged into bss.
+ */
*(.bss.k.page_aligned)
*(.bss)
+ *(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* uClinux MTD sucks */
diff -urpN linux-2.6.gc2/arch/sh/kernel/vsyscall/vsyscall.lds.S linux-2.6.gc3/arch/sh/kernel/vsyscall/vsyscall.lds.S
--- linux-2.6.gc2/arch/sh/kernel/vsyscall/vsyscall.lds.S 2007-11-23 18:55:10.000000000 -0800
+++ linux-2.6.gc3/arch/sh/kernel/vsyscall/vsyscall.lds.S 2007-11-23 21:21:33.000000000 -0800
@@ -35,7 +35,7 @@ SECTIONS
*/
. = 0x400;

- .text : { *(.text) } :text =0x90909090
+ .text : { *(.text .text.*) } :text =0x90909090
.note : { *(.note.*) } :text :note
.eh_frame_hdr : { *(.eh_frame_hdr ) } :text :eh_frame_hdr
.eh_frame : {
diff -urpN linux-2.6.gc2/arch/sh64/boot/compressed/vmlinux.lds.S linux-2.6.gc3/arch/sh64/boot/compressed/vmlinux.lds.S
--- linux-2.6.gc2/arch/sh64/boot/compressed/vmlinux.lds.S 2007-11-23 18:55:10.000000000 -0800
+++ linux-2.6.gc3/arch/sh64/boot/compressed/vmlinux.lds.S 2007-11-23 21:30:14.000000000 -0800
@@ -32,7 +32,7 @@ SECTIONS
*(.gnu.warning)
} = NOP
. = ALIGN(4);
- .rodata : { *(.rodata) }
+ .rodata : { *(.rodata) *(.rodata.*) }

/* There is no 'real' reason for eight byte alignment, four would work
* as well, but gdb downloads much (*4) faster with this.
@@ -47,6 +47,7 @@ SECTIONS
{
_data = .;
*(.data)
+ *(.data.*)
}
_data_image = LOADADDR(.data);/* Address of data section in ROM */

@@ -58,6 +59,7 @@ SECTIONS
__bss_start = .; /* BSS */
.bss : {
*(.bss)
+ *(.bss.*)
}
. = ALIGN(4);
_end = . ;
diff -urpN linux-2.6.gc2/arch/sh64/kernel/vmlinux.lds.S linux-2.6.gc3/arch/sh64/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/sh64/kernel/vmlinux.lds.S 2007-11-23 20:55:55.000000000 -0800
+++ linux-2.6.gc3/arch/sh64/kernel/vmlinux.lds.S 2007-11-23 21:33:26.000000000 -0800
@@ -124,6 +124,7 @@ SECTIONS
__bss_start = .; /* BSS */
.bss : C_PHYS(.bss) {
*(.bss)
+ *(.bss.*)
}
. = ALIGN(8);
_end = . ;
diff -urpN linux-2.6.gc2/arch/sparc/kernel/vmlinux.lds.S linux-2.6.gc3/arch/sparc/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/sparc/kernel/vmlinux.lds.S 2007-11-23 20:55:53.000000000 -0800
+++ linux-2.6.gc3/arch/sparc/kernel/vmlinux.lds.S 2007-11-23 21:34:37.000000000 -0800
@@ -97,6 +97,7 @@ SECTIONS
.bss : {
*(.dynbss)
*(.bss)
+ *(.bss.*)
*(COMMON)
}
_end = . ;
diff -urpN linux-2.6.gc2/arch/sparc64/kernel/vmlinux.lds.S linux-2.6.gc3/arch/sparc64/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/sparc64/kernel/vmlinux.lds.S 2007-11-23 20:55:53.000000000 -0800
+++ linux-2.6.gc3/arch/sparc64/kernel/vmlinux.lds.S 2007-11-23 21:34:31.000000000 -0800
@@ -131,6 +131,7 @@ SECTIONS
.bss : {
*(.dynbss)
*(.bss)
+ *(.bss.*)
*(COMMON)
}
_end = . ;
diff -urpN linux-2.6.gc2/arch/um/kernel/uml.lds.S linux-2.6.gc3/arch/um/kernel/uml.lds.S
--- linux-2.6.gc2/arch/um/kernel/uml.lds.S 2007-11-23 20:55:54.000000000 -0800
+++ linux-2.6.gc3/arch/um/kernel/uml.lds.S 2007-11-23 21:34:25.000000000 -0800
@@ -91,6 +91,7 @@ SECTIONS
{
*(.dynbss)
*(.bss)
+ *(.bss.*)
*(COMMON)
}
_end = .;
diff -urpN linux-2.6.gc2/arch/v850/kernel/vmlinux.lds.S linux-2.6.gc3/arch/v850/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/v850/kernel/vmlinux.lds.S 2007-11-23 20:55:56.000000000 -0800
+++ linux-2.6.gc3/arch/v850/kernel/vmlinux.lds.S 2007-11-23 21:34:18.000000000 -0800
@@ -127,6 +127,7 @@
#define BSS_CONTENTS \
__sbss = . ; \
*(.bss) \
+ *(.bss.*) \
*(COMMON) \
. = ALIGN (4) ; \
__init_stack_end = . ; \
diff -urpN linux-2.6.gc2/arch/x86/kernel/Makefile_32 linux-2.6.gc3/arch/x86/kernel/Makefile_32
--- linux-2.6.gc2/arch/x86/kernel/Makefile_32 2007-11-23 22:16:54.000000000 -0800
+++ linux-2.6.gc3/arch/x86/kernel/Makefile_32 2007-11-23 22:16:43.000000000 -0800
@@ -2,8 +2,9 @@
# Makefile for the linux kernel.
#

-extra-y := head_32.o init_task.o vmlinux.lds
+extra-y := head_32.o init_task.o vmlinux.lds modules.lds
CPPFLAGS_vmlinux.lds += -Ui386
+CPPFLAGS_modules.lds += -Ui386

obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \
ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \
diff -urpN linux-2.6.gc2/arch/x86/kernel/Makefile_64 linux-2.6.gc3/arch/x86/kernel/Makefile_64
--- linux-2.6.gc2/arch/x86/kernel/Makefile_64 2007-11-23 22:17:07.000000000 -0800
+++ linux-2.6.gc3/arch/x86/kernel/Makefile_64 2007-11-23 22:16:43.000000000 -0800
@@ -2,8 +2,10 @@
# Makefile for the linux kernel.
#

-extra-y := head_64.o head64.o init_task.o vmlinux.lds
+extra-y := head_64.o head64.o init_task.o vmlinux.lds modules.lds
CPPFLAGS_vmlinux.lds += -Ux86_64
+CPPFLAGS_modules.lds += -Ux86_64
+
EXTRA_AFLAGS := -traditional

obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \
diff -urpN linux-2.6.gc2/arch/x86/kernel/modules.lds.S linux-2.6.gc3/arch/x86/kernel/modules.lds.S
--- linux-2.6.gc2/arch/x86/kernel/modules.lds.S 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.gc3/arch/x86/kernel/modules.lds.S 2007-11-23 22:16:04.000000000 -0800
@@ -0,0 +1,128 @@
+#ifdef CONFIG_X86_32
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+#else
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+#endif
+
+/*
+This linker script is used if CONFIG_DISCARD_UNUSED_SECTIONS=y.
+We are trying to minimize number of sections in .ko file
+by coalescing .text.x, rodata.x, .data.x and bss.x input
+sections into one output section each.
+
+Kernel module loader (kernel/module.c) needs to see the following sections:
+
+.init*
+.exit*
+.gnu.linkonce.this_module
+.percpu.data
+.modinfo
+__ksymtab_gpl_future
+__ksymtab_gpl
+__ksymtab_unused_gpl
+__ksymtab_unused
+__ksymtab
+__kcrctab_gpl_future
+__kcrctab_gpl
+__kcrctab_unused_gpl
+__kcrctab_unused
+__kcrctab
+__param
+__ex_table
+__obsparm
+__versions
+.debug (?!)
+$ARCH_UNWIND_SECTION_NAME (none for x86 yet)
+
+They must not be coalesced into sections with other names.
+
+*/
+
+SECTIONS
+{
+ /* ro, code */
+
+ /* .fixup and .altinstr_replacement work just fine
+ * without dedicated sections */
+ .text : {
+ *(SORT_BY_ALIGNMENT(.text*))
+ /* __ex_table points here */
+ *(SORT_BY_ALIGNMENT(.fixup*))
+ /* .altinstructions points here */
+ *(SORT_BY_ALIGNMENT(.altinstr_replacement*))
+ }
+ /* only if CONFIG_MODULE_UNLOAD */
+ .exit.text : { *(SORT_BY_ALIGNMENT(.exit.text)) }
+ /* end CONFIG_MODULE_UNLOAD */
+
+ /* ro, data */
+
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) }
+ /* Kernel searches through this table when it needs to handle an exception */
+ __ex_table : { *(__ex_table*) }
+ /* These two tables are not currently handled by in-kernel module loader,
+ * but likely will be in future kernels */
+ .altinstructions : { *(.altinstructions*) }
+ .smp_locks : { *(.smp_locks*) }
+ /* Used by depmod in order to generate modules.dep, modules.symbols */
+ __ksymtab_strings : { *(SORT_BY_ALIGNMENT(__ksymtab_strings)) }
+ /* EXPORT_SYMBOLs exported in this module */
+ __ksymtab_gpl_future : { *(__ksymtab_gpl_future) }
+ __ksymtab_gpl : { *(__ksymtab_gpl) }
+ __ksymtab_unused_gpl : { *(__ksymtab_unused_gpl) }
+ __ksymtab_unused : { *(__ksymtab_unused) }
+ __ksymtab : { *(__ksymtab) }
+ /* only if CONFIG_MODVERSIONS */
+ __kcrctab_gpl_future : { *(__kcrctab_gpl_future) }
+ __kcrctab_gpl : { *(__kcrctab_gpl) }
+ __kcrctab_unused_gpl : { *(__kcrctab_unused_gpl) }
+ __kcrctab_unused : { *(__kcrctab_unused) }
+ __kcrctab : { *(__kcrctab) }
+ /* from *.mod.c: const struct modversion_info ____versions[] */
+ __versions : { *(__versions) }
+ /* end CONFIG_MODVERSIONS */
+ __param : { *(.__param) }
+ __obsparm : { *(.__obsparm) }
+ /* from *.mod.c: const char __module_depends[] "depends=mod1,mod2" */
+ .modinfo : { *(SORT_BY_ALIGNMENT(.modinfo)) }
+ /* ld segfaults if we give it --build-id and then discard this section */
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+
+ /* rw, data */
+
+ .data : {
+ *(SORT_BY_ALIGNMENT(.cacheline_aligned.data))
+ *(SORT_BY_ALIGNMENT(.data*))
+ *(SORT_BY_ALIGNMENT(.read_mostly.data))
+ }
+ /* from *.mod.c: struct module __this_module */
+ .gnu.linkonce.this_module : { *(.gnu.linkonce.this_module) }
+
+ /* only if CONFIG_SMP */
+ .percpu.data : { *(SORT_BY_ALIGNMENT(.percpu.data)) }
+ /* end CONFIG_SMP */
+
+ /* only if CONFIG_MODULE_UNLOAD */
+ .exit.data : { *(SORT_BY_ALIGNMENT(.exit.data)) }
+ /* end CONFIG_MODULE_UNLOAD */
+
+ /* rw, data initialized to 0 */
+
+ .bss : { *(SORT_BY_ALIGNMENT(.bss*)) }
+
+ /* init code/data. discarded at the end of sys_init_module() */
+
+ .init.text : { *(SORT_BY_ALIGNMENT(.init.text)) }
+ .init.data : { *(SORT_BY_ALIGNMENT(.init.data)) }
+
+ /* Be bold and resist the temptation to pull junk "by default" */
+
+ /DISCARD/ : { *(*) }
+
+ /* If you are going to revive these, please add comment why it is needed */
+ /* .debug : { *(.debug) } */
+ /* .comment : { *(.comment) } */
+ /* .note.GNU-stack : { *(.note.GNU-stack) } */
+}
diff -urpN linux-2.6.gc2/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.gc3/arch/x86/kernel/vmlinux_32.lds.S
--- linux-2.6.gc2/arch/x86/kernel/vmlinux_32.lds.S 2007-11-23 22:00:09.000000000 -0800
+++ linux-2.6.gc3/arch/x86/kernel/vmlinux_32.lds.S 2007-11-23 21:48:58.000000000 -0800
@@ -2,14 +2,7 @@
* Written by Martin Mares <mj@xxxxxxxxxxxxxxxxxxxxxxxx>;
*
* Don't define absolute symbols until and unless you know that symbol
- * value is should remain constant even if kernel image is relocated
- * at run time. Absolute symbols are not relocated. If symbol value should
- * change if kernel is relocated, make the symbol section relative and
- * put it inside the section definition.
- */
-
-/* Don't define absolute symbols until and unless you know that symbol
- * value is should remain constant even if kernel image is relocated
+ * value should remain constant even if kernel image is relocated
* at run time. Absolute symbols are not relocated. If symbol value should
* change if kernel is relocated, make the symbol section relative and
* put it inside the section definition.
@@ -39,7 +32,7 @@ SECTIONS

.head.text : AT(ADDR(.head.text) - LOAD_OFFSET) {
_text = .; /* Text and read-only data */
- *(.head.text)
+ KEEP(*(.head.text))
} :text = 0x9090

/* read-only */
@@ -48,16 +41,17 @@ SECTIONS
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
- *(.fixup)
+ *(.fixup) /* no need to KEEP, every .fixup is referenced by __ex_table */
*(.gnu.warning)
_etext = .; /* End of text section */
} :text = 0x9090

. = ALIGN(16); /* Exception table */
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
- __start___ex_table = .;
- *(__ex_table)
- __stop___ex_table = .;
+ /* Points to potentially-faulting insns and corresponding .fixups */
+ __start___ex_table = .;
+ KEEP(*(__ex_table))
+ __stop___ex_table = .;
}

NOTES :text :note
@@ -67,7 +61,7 @@ SECTIONS
. = ALIGN(4);
.tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
__tracedata_start = .;
- *(.tracedata)
+ KEEP(*(.tracedata)) /* really need to KEEP? */
__tracedata_end = .;
}

@@ -83,7 +77,7 @@ SECTIONS
. = ALIGN(4096);
.data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
__nosave_begin = .;
- *(.nosave.data)
+ *(.nosave.data) /* not saved by suspend */
. = ALIGN(4096);
__nosave_end = .;
}
@@ -115,7 +109,7 @@ SECTIONS
. = ALIGN(4096);
.smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
__smp_locks = .;
- *(.smp_locks)
+ KEEP(*(.smp_locks)) /* points to lock prefixes */
__smp_locks_end = .;
}
/* will be freed after init
@@ -134,11 +128,11 @@ SECTIONS
*(.init.text)
_einittext = .;
}
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } /* no need to KEEP */
. = ALIGN(16);
.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
__setup_start = .;
- *(.init.setup)
+ KEEP(*(.init.setup)) /* obsolete_checksetup() walks it */
__setup_end = .;
}
.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
@@ -148,26 +142,26 @@ SECTIONS
}
.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
__con_initcall_start = .;
- *(.con_initcall.init)
+ KEEP(*(.con_initcall.init)) /* console_init() walks it */
__con_initcall_end = .;
}
SECURITY_INIT
. = ALIGN(4);
.altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
__alt_instructions = .;
- *(.altinstructions)
+ KEEP(*(.altinstructions)) /* alternative_instructions() walks it */
__alt_instructions_end = .;
}
.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
- *(.altinstr_replacement)
+ KEEP(*(.altinstr_replacement))
}
. = ALIGN(4);
.parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
__parainstructions = .;
- *(.parainstructions)
+ KEEP(*(.parainstructions)) /* really need to KEEP? */
__parainstructions_end = .;
}
- /* .exit.text is discard at runtime, not link time, to deal with references
+ /* .exit.text is discarded at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
@@ -175,7 +169,7 @@ SECTIONS
. = ALIGN(4096);
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
__initramfs_start = .;
- *(.init.ramfs)
+ KEEP(*(.init.ramfs))
__initramfs_end = .;
}
#endif
@@ -192,8 +186,17 @@ SECTIONS
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
__init_end = .;
__bss_start = .; /* BSS */
+
+ /* Why such strage name - .bss.k.page_aligned?
+ * .bss.page_aligned may clash with a section produced by gcc -fdata_sections.
+ * .bss_page_aligned, .page_aligned_bss will not work because
+ * we must use .bss.xxx section names for zero-initialized sections
+ * we want to combine into bss, otherwise gcc does not set
+ * 'nobits' flag for the section, and it cannot be merged into bss.
+ */
*(.bss.k.page_aligned)
*(.bss)
+ *(SORT_BY_ALIGNMENT(.bss.*))
. = ALIGN(4);
__bss_stop = .;
_end = . ;
diff -urpN linux-2.6.gc2/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.gc3/arch/x86/kernel/vmlinux_64.lds.S
--- linux-2.6.gc2/arch/x86/kernel/vmlinux_64.lds.S 2007-11-23 22:00:09.000000000 -0800
+++ linux-2.6.gc3/arch/x86/kernel/vmlinux_64.lds.S 2007-11-23 21:49:45.000000000 -0800
@@ -28,14 +28,14 @@ SECTIONS
_text = .; /* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
/* First the code that has to be first for bootstrapping */
- *(.head.text)
+ KEEP(*(.head.text))
_stext = .;
/* Then the rest */
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
- *(.fixup)
+ *(.fixup) /* no need to KEEP, every .fixup is referenced by __ex_table */
*(.gnu.warning)
} :text = 0x9090
/* out-of-line lock text */
@@ -45,7 +45,8 @@ SECTIONS

. = ALIGN(16); /* Exception table */
__start___ex_table = .;
- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
+ /* Points to potentially-faulting insns and corresponding .fixups */
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { KEEP(*(__ex_table)) }
__stop___ex_table = .;

NOTES :text :note
@@ -57,7 +58,7 @@ SECTIONS
. = ALIGN(4);
.tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
__tracedata_start = .;
- *(.tracedata)
+ KEEP(*(.tracedata)) /* really need to KEEP? */
__tracedata_end = .;
}

@@ -91,24 +92,24 @@ SECTIONS
#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)

. = VSYSCALL_ADDR;
- .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
+ .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { KEEP(*(.vsyscall_0)) } :user
__vsyscall_0 = VSYSCALL_VIRT_ADDR;

. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { *(.vsyscall_fn) }
+ .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { KEEP(*(.vsyscall_fn)) }
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
.vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data))
- { *(.vsyscall_gtod_data) }
+ { KEEP(*(.vsyscall_gtod_data)) }
vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
.vsyscall_clock : AT(VLOAD(.vsyscall_clock))
- { *(.vsyscall_clock) }
+ { KEEP(*(.vsyscall_clock)) }
vsyscall_clock = VVIRT(.vsyscall_clock);


.vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
- { *(.vsyscall_1) }
+ { KEEP(*(.vsyscall_1)) }
.vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
- { *(.vsyscall_2) }
+ { KEEP(*(.vsyscall_2)) }

.vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
vgetcpu_mode = VVIRT(.vgetcpu_mode);
@@ -118,7 +119,7 @@ SECTIONS
jiffies = VVIRT(.jiffies);

.vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
- { *(.vsyscall_3) }
+ { KEEP(*(.vsyscall_3)) }

. = VSYSCALL_VIRT_ADDR + 4096;

@@ -145,7 +146,7 @@ SECTIONS
__smp_alt_begin = .;
__smp_locks = .;
.smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
- *(.smp_locks)
+ KEEP(*(.smp_locks)) /* points to lock prefixes */
}
__smp_locks_end = .;
. = ALIGN(4096);
@@ -159,11 +160,11 @@ SECTIONS
_einittext = .;
}
__initdata_begin = .;
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } /* no need to KEEP */
__initdata_end = .;
. = ALIGN(16);
__setup_start = .;
- .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
+ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { KEEP(*(.init.setup)) } /* obsolete_checksetup() walks it */
__setup_end = .;
__initcall_start = .;
.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
@@ -172,18 +173,18 @@ SECTIONS
__initcall_end = .;
__con_initcall_start = .;
.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
- *(.con_initcall.init)
+ KEEP(*(.con_initcall.init)) /* console_init() walks it */
}
__con_initcall_end = .;
SECURITY_INIT
. = ALIGN(8);
__alt_instructions = .;
.altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
- *(.altinstructions)
+ KEEP(*(.altinstructions)) /* alternative_instructions() walks it */
}
__alt_instructions_end = .;
.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
- *(.altinstr_replacement)
+ KEEP(*(.altinstr_replacement))
}
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
@@ -192,14 +193,14 @@ SECTIONS

/* vdso blob that is mapped into user space */
vdso_start = . ;
- .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { *(.vdso) }
+ .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { KEEP(*(.vdso)) }
. = ALIGN(4096);
vdso_end = .;

#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(4096);
__initramfs_start = .;
- .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
+ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { KEEP(*(.init.ramfs)) }
__initramfs_end = .;
#endif

@@ -210,14 +211,23 @@ SECTIONS

. = ALIGN(4096);
__nosave_begin = .;
- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.nosave.data) }
+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.nosave.data) } /* not saved by suspend */
. = ALIGN(4096);
__nosave_end = .;

__bss_start = .; /* BSS */
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+
+ /* Why such strage name - .bss.k.page_aligned?
+ * .bss.page_aligned may clash with a section produced by gcc -fdata_sections.
+ * .bss_page_aligned, .page_aligned_bss will not work because
+ * we must use .bss.xxx section names for zero-initialized sections
+ * we want to combine into bss, otherwise gcc does not set
+ * 'nobits' flag for the section, and it cannot be merged into bss.
+ */
*(.bss.k.page_aligned)
*(.bss)
+ *(SORT_BY_ALIGNMENT(.bss.*))
}
__bss_stop = .;

diff -urpN linux-2.6.gc2/arch/x86/kernel/vsyscall_32.lds.S linux-2.6.gc3/arch/x86/kernel/vsyscall_32.lds.S
--- linux-2.6.gc2/arch/x86/kernel/vsyscall_32.lds.S 2007-11-23 18:55:10.000000000 -0800
+++ linux-2.6.gc3/arch/x86/kernel/vsyscall_32.lds.S 2007-11-23 22:05:37.000000000 -0800
@@ -23,10 +23,10 @@ SECTIONS
is insufficient, ld -shared will barf. Just increase it here. */
. = VDSO_PRELINK_asm + 0x400;

- .text : { *(.text) } :text =0x90909090
+ .text : { *(.text .text.*) } :text =0x90909090
.note : { *(.note.*) } :text :note
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .eh_frame : { KEEP(*(.eh_frame)) } :text
.dynamic : { *(.dynamic) } :text :dynamic
.useless : {
*(.got.plt) *(.got)
diff -urpN linux-2.6.gc2/arch/xtensa/kernel/vmlinux.lds.S linux-2.6.gc3/arch/xtensa/kernel/vmlinux.lds.S
--- linux-2.6.gc2/arch/xtensa/kernel/vmlinux.lds.S 2007-11-23 22:00:09.000000000 -0800
+++ linux-2.6.gc3/arch/xtensa/kernel/vmlinux.lds.S 2007-11-23 21:33:37.000000000 -0800
@@ -255,7 +255,15 @@ SECTIONS

/* BSS section */
_bss_start = .;
- .bss : { *(.bss.k.page_aligned) *(.bss) }
+
+ /* Why such strage name - .bss.k.page_aligned?
+ * .bss.page_aligned may clash with a section produced by gcc -fdata_sections.
+ * .bss_page_aligned, .page_aligned_bss will not work because
+ * we must use .bss.xxx section names for zero-initialized sections
+ * we want to combine into bss, otherwise gcc does not set
+ * 'nobits' flag for the section, and it cannot be merged into bss.
+ */
+ .bss : { *(.bss.k.page_aligned) *(.bss) *(.bss.*) }
_bss_end = .;

_end = .;
diff -urpN linux-2.6.gc2/include/asm-generic/vmlinux.lds.h linux-2.6.gc3/include/asm-generic/vmlinux.lds.h
--- linux-2.6.gc2/include/asm-generic/vmlinux.lds.h 2007-11-23 20:55:54.000000000 -0800
+++ linux-2.6.gc3/include/asm-generic/vmlinux.lds.h 2007-11-23 21:15:24.000000000 -0800
@@ -6,12 +6,19 @@
#define VMLINUX_SYMBOL(_sym_) _sym_
#endif

+#ifndef CONFIG_DISCARD_UNUSED_SECTIONS
+/* Don't confuse old ld with new stuff */
+#define KEEP(x) x
+#define SORT_BY_ALIGNMENT(x) x
+#endif
+
/* Align . to a 8 byte boundary equals to maximum function alignment. */
#define ALIGN_FUNCTION() . = ALIGN(8)

/* .data section */
#define DATA_DATA \
*(.data) \
+ *(SORT_BY_ALIGNMENT(.data.*)) \
*(.init.refok.data) \
. = ALIGN(8); \
VMLINUX_SYMBOL(__start___markers) = .; \
@@ -22,7 +29,7 @@
. = ALIGN((align)); \
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rodata) = .; \
- *(.rodata) *(.rodata.*) \
+ *(.rodata) *(SORT_BY_ALIGNMENT(.rodata.*)) \
*(__vermagic) /* Kernel version magic */ \
*(__markers_strings) /* Markers: strings */ \
} \
@@ -33,109 +40,110 @@
\
/* PCI quirks */ \
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
+ /* walked by pci_fixup_device() */ \
VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
- *(.pci_fixup_early) \
+ KEEP(*(.pci_fixup_early)) \
VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
- *(.pci_fixup_header) \
+ KEEP(*(.pci_fixup_header)) \
VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \
- *(.pci_fixup_final) \
+ KEEP(*(.pci_fixup_final)) \
VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
- *(.pci_fixup_enable) \
+ KEEP(*(.pci_fixup_enable)) \
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
- *(.pci_fixup_resume) \
+ KEEP(*(.pci_fixup_resume)) \
VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
} \
\
/* RapidIO route ops */ \
.rio_route : AT(ADDR(.rio_route) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rio_route_ops) = .; \
- *(.rio_route_ops) \
+ KEEP(*(.rio_route_ops)) \
VMLINUX_SYMBOL(__end_rio_route_ops) = .; \
} \
\
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab) = .; \
- *(__ksymtab) \
+ KEEP(*(__ksymtab)) \
VMLINUX_SYMBOL(__stop___ksymtab) = .; \
} \
\
/* Kernel symbol table: GPL-only symbols */ \
__ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
- *(__ksymtab_gpl) \
+ KEEP(*(__ksymtab_gpl)) \
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
} \
\
/* Kernel symbol table: Normal unused symbols */ \
__ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
- *(__ksymtab_unused) \
+ KEEP(*(__ksymtab_unused)) \
VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
} \
\
/* Kernel symbol table: GPL-only unused symbols */ \
__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
- *(__ksymtab_unused_gpl) \
+ KEEP(*(__ksymtab_unused_gpl)) \
VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
} \
\
/* Kernel symbol table: GPL-future-only symbols */ \
__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
- *(__ksymtab_gpl_future) \
+ KEEP(*(__ksymtab_gpl_future)) \
VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
} \
\
/* Kernel symbol table: Normal symbols */ \
__kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___kcrctab) = .; \
- *(__kcrctab) \
+ KEEP(*(__kcrctab)) \
VMLINUX_SYMBOL(__stop___kcrctab) = .; \
} \
\
/* Kernel symbol table: GPL-only symbols */ \
__kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
- *(__kcrctab_gpl) \
+ KEEP(*(__kcrctab_gpl)) \
VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
} \
\
/* Kernel symbol table: Normal unused symbols */ \
__kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \
- *(__kcrctab_unused) \
+ KEEP(*(__kcrctab_unused)) \
VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \
} \
\
/* Kernel symbol table: GPL-only unused symbols */ \
__kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
- *(__kcrctab_unused_gpl) \
+ KEEP(*(__kcrctab_unused_gpl)) \
VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
} \
\
/* Kernel symbol table: GPL-future-only symbols */ \
__kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
- *(__kcrctab_gpl_future) \
+ KEEP(*(__kcrctab_gpl_future)) \
VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \
} \
\
/* Kernel symbol table: strings */ \
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
- *(__ksymtab_strings) \
+ KEEP(*(__ksymtab_strings)) \
} \
\
/* Built-in module parameters. */ \
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___param) = .; \
- *(__param) \
+ KEEP(*(__param)) \
VMLINUX_SYMBOL(__stop___param) = .; \
VMLINUX_SYMBOL(__end_rodata) = .; \
} \
@@ -149,7 +157,7 @@
#define SECURITY_INIT \
.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__security_initcall_start) = .; \
- *(.security_initcall.init) \
+ KEEP(*(.security_initcall.init)) \
VMLINUX_SYMBOL(__security_initcall_end) = .; \
}

@@ -158,6 +166,7 @@
#define TEXT_TEXT \
ALIGN_FUNCTION(); \
*(.text) \
+ *(SORT_BY_ALIGNMENT(.text.*)) \
*(.init.refok.text) \
*(.exit.text.refok)

@@ -166,6 +175,7 @@
#define SCHED_TEXT \
ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__sched_text_start) = .; \
+ /* No need to KEEP */ \
*(.sched.text) \
VMLINUX_SYMBOL(__sched_text_end) = .;

@@ -174,12 +184,14 @@
#define LOCK_TEXT \
ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__lock_text_start) = .; \
+ /* No need to KEEP */ \
*(.spinlock.text) \
VMLINUX_SYMBOL(__lock_text_end) = .;

#define KPROBES_TEXT \
ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__kprobes_text_start) = .; \
+ /* No need to KEEP */ \
*(.kprobes.text) \
VMLINUX_SYMBOL(__kprobes_text_end) = .;

@@ -225,35 +237,37 @@
. = ALIGN(8); \
__bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \
__start___bug_table = .; \
- *(__bug_table) \
+ /* Support for BUG() */ \
+ KEEP(*(__bug_table)) \
__stop___bug_table = .; \
}

#define NOTES \
.notes : AT(ADDR(.notes) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_notes) = .; \
- *(.note.*) \
+ /* For /sys/kernel/notes */ \
+ KEEP(*(.note.*)) \
VMLINUX_SYMBOL(__stop_notes) = .; \
}

#define INITCALLS \
- *(.initcall0.init) \
- *(.initcall0s.init) \
- *(.initcall1.init) \
- *(.initcall1s.init) \
- *(.initcall2.init) \
- *(.initcall2s.init) \
- *(.initcall3.init) \
- *(.initcall3s.init) \
- *(.initcall4.init) \
- *(.initcall4s.init) \
- *(.initcall5.init) \
- *(.initcall5s.init) \
- *(.initcallrootfs.init) \
- *(.initcall6.init) \
- *(.initcall6s.init) \
- *(.initcall7.init) \
- *(.initcall7s.init)
+ KEEP(*(.initcall0.init)) /* do_initcalls() walks them */ \
+ KEEP(*(.initcall0s.init)) \
+ KEEP(*(.initcall1.init)) \
+ KEEP(*(.initcall1s.init)) \
+ KEEP(*(.initcall2.init)) \
+ KEEP(*(.initcall2s.init)) \
+ KEEP(*(.initcall3.init)) \
+ KEEP(*(.initcall3s.init)) \
+ KEEP(*(.initcall4.init)) \
+ KEEP(*(.initcall4s.init)) \
+ KEEP(*(.initcall5.init)) \
+ KEEP(*(.initcall5s.init)) \
+ KEEP(*(.initcallrootfs.init)) \
+ KEEP(*(.initcall6.init)) \
+ KEEP(*(.initcall6s.init)) \
+ KEEP(*(.initcall7.init)) \
+ KEEP(*(.initcall7s.init))

#define PERCPU(align) \
. = ALIGN(align); \
diff -urpN linux-2.6.gc2/init/Kconfig linux-2.6.gc3/init/Kconfig
--- linux-2.6.gc2/init/Kconfig 2007-11-23 18:55:26.000000000 -0800
+++ linux-2.6.gc3/init/Kconfig 2007-11-23 22:22:31.000000000 -0800
@@ -425,6 +425,23 @@ config CC_OPTIMIZE_FOR_SIZE

If unsure, say N.

+config DISCARD_UNUSED_SECTIONS
+ bool "Discard unused code/data sections (DANGEROUS)"
+ default n
+ depends on EXPERIMENTAL
+ help
+ Enabling this option will pass --ffunction-sections -fdata-sections
+ to gcc and --gc-sections to ld, resulting in a smaller kernel.
+
+ WARNING: --gc-sections support is very new and considered highly
+ experimental for now. You need at least binutils 2.18,
+ and even then surprises are likely.
+
+ This option also requires architecture-specific changes.
+ Currently working architectures: x86
+
+ If unsure, say N.
+
config SYSCTL
bool

diff -urpN linux-2.6.gc2/scripts/Makefile.modpost linux-2.6.gc3/scripts/Makefile.modpost
--- linux-2.6.gc2/scripts/Makefile.modpost 2007-11-23 18:55:26.000000000 -0800
+++ linux-2.6.gc3/scripts/Makefile.modpost 2007-11-24 14:46:38.000000000 -0800
@@ -97,9 +97,15 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c
targets += $(modules:.ko=.mod.o)

# Step 6), final link of the modules
+ifdef CONFIG_DISCARD_UNUSED_SECTIONS
+quiet_cmd_ld_ko_o = LD [M] $@
+ cmd_ld_ko_o = $(LD) -r -T arch/$(SRCARCH)/kernel/modules.lds $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ -Map $@.map \
+ $(filter-out FORCE,$^)
+else
quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = $(LD) -r $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \
$(filter-out FORCE,$^)
+endif

$(modules): %.ko :%.o %.mod.o FORCE
$(call if_changed,ld_ko_o)