All of lore.kernel.org
 help / color / mirror / Atom feed
From: Denys Vlasenko <vda.linux@googlemail.com>
To: Sam Ravnborg <sam@ravnborg.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 3/3] build system: section garbage collection - main part
Date: Sat, 24 Nov 2007 15:18:31 -0800	[thread overview]
Message-ID: <200711241518.31371.vda.linux@googlemail.com> (raw)
In-Reply-To: <200711241514.26451.vda.linux@googlemail.com>

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

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@googlemail.com>
-- 
vda

[-- Attachment #2: linux-2.6-linus_git.3.gc.patch --]
[-- Type: text/x-diff, Size: 47497 bytes --]

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@atrey.karlin.mff.cuni.cz>;
  *
  * 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)

      parent reply	other threads:[~2007-11-24 23:18 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-11 20:05 [PATCH 0/4] build system: section garbage collection for vmlinux Denys Vlasenko
2007-09-11 20:07 ` [PATCH 1/4] " Denys Vlasenko
2007-09-11 20:10   ` [PATCH 2/4] " Denys Vlasenko
2007-09-11 20:11     ` [PATCH 3/4] " Denys Vlasenko
2007-09-11 20:22       ` [PATCH 4/4] " Denys Vlasenko
2007-09-11 21:47   ` [PATCH 1/4] " Daniel Walker
2007-09-12 20:18     ` Denys Vlasenko
2007-09-12 20:52       ` Daniel Walker
2007-09-11 21:03 ` [PATCH 0/4] " Andi Kleen
2007-09-12 20:19   ` Denys Vlasenko
2007-09-13 18:26 ` Abhishek Sagar
2007-09-13 18:35   ` Sam Ravnborg
2007-09-14 18:06     ` Abhishek Sagar
     [not found] ` <20071118230057.GA6303@uranus.ravnborg.org>
2007-11-24 23:14   ` [PATCH 0/3] build system: section garbage collection Denys Vlasenko
2007-11-24 23:17     ` [PATCH 1/3] build system: section garbage collection - rename sections Denys Vlasenko
2008-06-24  7:29       ` Matthieu CASTET
2007-11-24 23:17     ` [PATCH 2/3] build system: section garbage collection - modpost fix Denys Vlasenko
2007-11-24 23:18     ` Denys Vlasenko [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200711241518.31371.vda.linux@googlemail.com \
    --to=vda.linux@googlemail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sam@ravnborg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.