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 ; * * 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)