2010-07-28 23:48:20

by Denys Vlasenko

[permalink] [raw]
Subject: [PATCH 0/4] function/data-sections

Hi Michal,

Please take this patch series onto linux-kbuild.

Most of work needed for working -ffunction-sections -fdata-sections build
is already in the mainline, but a few bits are still missing.
In order to have a working kernel with this make invocation:
make KCFLAGS="-ffunction-sections -fdata-sections"
we need these patches:

modpost: support objects with more than 64k sections
This patch is in -mm, it still did not reach mainline,
thus resending. Sam suggested some readability improvements.
module linker script: coalesce function and data sections
kernel linker stripts: accomodate function and data sections
boot linker stripts: accomodate function and data sections

Please see individual patches for more detailed changelogs.

A rough idea what sort of size savings are achievable
with section garbage collection:
Kernel:
text data bss dec hex filename
8299299 857324 785348 9941971 97b3d3 2.6.35-rc4/vmlinux
7566908 832388 717844 9117140 8b1dd4 2.6.35-rc4-fsgs/vmlinux
-9.2% -2.9% -9.0% -8.6%
The largest module in the build:
451009 54640 2224 507873 7bfe1 2.6.35-rc4/fs/xfs/xfs.ko
450521 54292 2202 507015 7bc87 2.6.35-rc4-fsgs/fs/xfs/xfs.ko
(negligible size change since section garbage collection
for modules is not done. TODO: figure out how to do it)

Signed-off-by: Denys Vlasenko <[email protected]>
Acked-by: Sam Ravnborg <[email protected]>


Denys Vlasenko (4):
modpost: support objects with more than 64k sections
module linker script: coalesce sections
kernel linker stripts: accomodate function and data sections
boot linker stripts: accomodate function and data sections

arch/alpha/boot/bootloader.lds | 6 +-
arch/arm/boot/bootp/bootp.lds | 1 +
arch/cris/boot/compressed/decompress_v10.lds | 3 +
arch/cris/boot/compressed/decompress_v32.lds | 3 +
arch/cris/boot/rescue/rescue_v10.lds | 2 +
arch/cris/boot/rescue/rescue_v32.lds | 3 +
arch/frv/kernel/vmlinux.lds.S | 1 -
arch/h8300/boot/compressed/vmlinux.lds | 2 +
arch/h8300/boot/compressed/vmlinux.scr | 1 +
arch/ia64/hp/sim/boot/bootloader.lds | 6 +-
arch/ia64/scripts/check-segrel.lds | 4 +-
arch/m32r/boot/compressed/vmlinux.lds.S | 6 +-
arch/m32r/boot/compressed/vmlinux.scr | 1 +
arch/m68knommu/kernel/vmlinux.lds.S | 1 +
arch/mips/lasat/image/romscript.normal | 1 +
arch/mn10300/boot/compressed/vmlinux.lds | 1 +
arch/parisc/kernel/vmlinux.lds.S | 1 +
arch/powerpc/boot/zImage.coff.lds.S | 2 +
arch/powerpc/boot/zImage.lds.S | 2 +
arch/powerpc/boot/zImage.ps3.lds.S | 2 +
arch/sh/boot/compressed/vmlinux.scr | 1 +
arch/sh/kernel/vsyscall/vsyscall.lds.S | 2 +-
arch/x86/boot/setup.ld | 3 +-
arch/x86/kernel/acpi/realmode/wakeup.lds.S | 1 +
arch/x86/kernel/vmlinux.lds.S | 1 +
arch/xtensa/boot/boot-elf/boot.lds.S | 5 +-
arch/xtensa/boot/boot-redboot/boot.ld | 5 +-
include/asm-generic/vmlinux.lds.h | 18 ++++-
scripts/mod/file2alias.c | 6 +-
scripts/mod/modpost.c | 102 +++++++++++++++++++-------
scripts/mod/modpost.h | 43 +++++++++++
scripts/module-common.lds | 23 ++++++
32 files changed, 213 insertions(+), 46 deletions(-)


2010-07-28 23:48:30

by Denys Vlasenko

[permalink] [raw]
Subject: [PATCH 4/4] boot linker stripts: accomodate function and data sections

gcc -ffunction-sections -fdata-sections places each function foo
into separate section .text.foo, and every data object bar into
separate section .data.bar, .rodata.bar or .bss.bar.

Boot linker scripts were not ready for this.

This fix adds *(.text.*), *(.data.*) etc patterns
directly after corresponding *(.text), *(.data) etc patterns
in all boot linker scripts.

This may be unnecessary, but I want to be
function and data section-clean in all linker scripts,
including boot ones.

Signed-off-by: Denys Vlasenko <[email protected]>
Acked-by: Sam Ravnborg <[email protected]>
---
arch/alpha/boot/bootloader.lds | 6 +++---
arch/arm/boot/bootp/bootp.lds | 1 +
arch/cris/boot/compressed/decompress_v10.lds | 3 +++
arch/cris/boot/compressed/decompress_v32.lds | 3 +++
arch/cris/boot/rescue/rescue_v10.lds | 2 ++
arch/cris/boot/rescue/rescue_v32.lds | 3 +++
arch/h8300/boot/compressed/vmlinux.lds | 2 ++
arch/h8300/boot/compressed/vmlinux.scr | 1 +
arch/ia64/hp/sim/boot/bootloader.lds | 6 +++---
arch/m32r/boot/compressed/vmlinux.lds.S | 6 +++---
arch/m32r/boot/compressed/vmlinux.scr | 1 +
arch/mn10300/boot/compressed/vmlinux.lds | 1 +
arch/powerpc/boot/zImage.coff.lds.S | 2 ++
arch/powerpc/boot/zImage.lds.S | 2 ++
arch/powerpc/boot/zImage.ps3.lds.S | 2 ++
arch/sh/boot/compressed/vmlinux.scr | 1 +
arch/x86/boot/setup.ld | 3 ++-
arch/xtensa/boot/boot-elf/boot.lds.S | 5 ++++-
arch/xtensa/boot/boot-redboot/boot.ld | 5 ++++-
19 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/arch/alpha/boot/bootloader.lds b/arch/alpha/boot/bootloader.lds
index 31c081c..ff5374d 100644
--- a/arch/alpha/boot/bootloader.lds
+++ b/arch/alpha/boot/bootloader.lds
@@ -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 --git a/arch/arm/boot/bootp/bootp.lds b/arch/arm/boot/bootp/bootp.lds
index fc54394..14be7ff 100644
--- a/arch/arm/boot/bootp/bootp.lds
+++ b/arch/arm/boot/bootp/bootp.lds
@@ -16,6 +16,7 @@ SECTIONS
_stext = .;
*(.start)
*(.text)
+ *(.text.*)
initrd_size = initrd_end - initrd_start;
_etext = .;
}
diff --git a/arch/cris/boot/compressed/decompress_v10.lds b/arch/cris/boot/compressed/decompress_v10.lds
index e80f459..d6022d9 100644
--- a/arch/cris/boot/compressed/decompress_v10.lds
+++ b/arch/cris/boot/compressed/decompress_v10.lds
@@ -13,6 +13,7 @@ SECTIONS
{
_stext = . ;
*(.text)
+ *(.text.*)
*(.rodata)
*(.rodata.*)
_etext = . ;
@@ -20,11 +21,13 @@ SECTIONS
.data :
{
*(.data)
+ *(.data.*)
_edata = . ;
} > dram
.bss :
{
*(.bss)
+ *(.bss.*)
_end = ALIGN( 0x10 ) ;
} > dram
}
diff --git a/arch/cris/boot/compressed/decompress_v32.lds b/arch/cris/boot/compressed/decompress_v32.lds
index 3c837fe..b5cfeb4 100644
--- a/arch/cris/boot/compressed/decompress_v32.lds
+++ b/arch/cris/boot/compressed/decompress_v32.lds
@@ -13,6 +13,7 @@ SECTIONS
{
_stext = . ;
*(.text)
+ *(.text.*)
*(.rodata)
*(.rodata.*)
_etext = . ;
@@ -20,11 +21,13 @@ SECTIONS
.data :
{
*(.data)
+ *(.data.*)
_edata = . ;
} > dram
.bss :
{
*(.bss)
+ *(.bss.*)
_end = ALIGN( 0x10 ) ;
} > dram
}
diff --git a/arch/cris/boot/rescue/rescue_v10.lds b/arch/cris/boot/rescue/rescue_v10.lds
index 0b52a94..42b03a3 100644
--- a/arch/cris/boot/rescue/rescue_v10.lds
+++ b/arch/cris/boot/rescue/rescue_v10.lds
@@ -10,11 +10,13 @@ SECTIONS
{
stext = . ;
*(.text)
+ *(.text.*)
etext = . ;
} > flash
.data :
{
*(.data)
+ *(.data.*)
edata = . ;
} > flash
}
diff --git a/arch/cris/boot/rescue/rescue_v32.lds b/arch/cris/boot/rescue/rescue_v32.lds
index 8ac646b..440ea40 100644
--- a/arch/cris/boot/rescue/rescue_v32.lds
+++ b/arch/cris/boot/rescue/rescue_v32.lds
@@ -17,6 +17,7 @@ SECTIONS
{
_stext = . ;
*(.text)
+ *(.text.*)
*(.init.text)
*(.rodata)
*(.rodata.*)
@@ -25,12 +26,14 @@ SECTIONS
.data :
{
*(.data)
+ *(.data.*)
_edata = . ;
} > bootblk
.bss :
{
_bss = . ;
*(.bss)
+ *(.bss.*)
_end = ALIGN( 0x10 ) ;
} > intmem

diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
index a0a3a0e..6896c9a 100644
--- a/arch/h8300/boot/compressed/vmlinux.lds
+++ b/arch/h8300/boot/compressed/vmlinux.lds
@@ -6,12 +6,14 @@ SECTIONS
__text = .;
*(.text..startup)
*(.text)
+ *(.text.*)
__etext = . ;
}

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

diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr
index a0f6962..f4cfb3f 100644
--- a/arch/h8300/boot/compressed/vmlinux.scr
+++ b/arch/h8300/boot/compressed/vmlinux.scr
@@ -4,6 +4,7 @@ SECTIONS
_input_len = .;
LONG(_input_data_end - _input_data) _input_data = .;
*(.data)
+ *(.data.*)
_input_data_end = .;
}
}
diff --git a/arch/ia64/hp/sim/boot/bootloader.lds b/arch/ia64/hp/sim/boot/bootloader.lds
index 3977f25..56bf12c 100644
--- a/arch/ia64/hp/sim/boot/bootloader.lds
+++ b/arch/ia64/hp/sim/boot/bootloader.lds
@@ -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_start = .;
.sbss : { *(.sbss) *(.scommon) }
- .bss : { *(.bss) *(COMMON) }
+ .bss : { *(.bss) *(.bss.*) *(COMMON) }
. = ALIGN(64 / 8);
__bss_stop = .;
_end = . ;
diff --git a/arch/m32r/boot/compressed/vmlinux.lds.S b/arch/m32r/boot/compressed/vmlinux.lds.S
index dd11963..d51580e 100644
--- a/arch/m32r/boot/compressed/vmlinux.lds.S
+++ b/arch/m32r/boot/compressed/vmlinux.lds.S
@@ -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 --git a/arch/m32r/boot/compressed/vmlinux.scr b/arch/m32r/boot/compressed/vmlinux.scr
index 924c799..253eff1 100644
--- a/arch/m32r/boot/compressed/vmlinux.scr
+++ b/arch/m32r/boot/compressed/vmlinux.scr
@@ -3,6 +3,7 @@ SECTIONS
.data : {
zimage_data = .;
*(.data)
+ *(.data.*)
zimage_data_end = .;
}
zimage_len = zimage_data_end - zimage_data;
diff --git a/arch/mn10300/boot/compressed/vmlinux.lds b/arch/mn10300/boot/compressed/vmlinux.lds
index a084903..3e3e043 100644
--- a/arch/mn10300/boot/compressed/vmlinux.lds
+++ b/arch/mn10300/boot/compressed/vmlinux.lds
@@ -4,6 +4,7 @@ SECTIONS
input_len = .;
LONG(input_data_end - input_data) input_data = .;
*(.data)
+ *(.data.*)
input_data_end = .;
}
}
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S
index 856dc78..504183a 100644
--- a/arch/powerpc/boot/zImage.coff.lds.S
+++ b/arch/powerpc/boot/zImage.coff.lds.S
@@ -7,6 +7,7 @@ SECTIONS
.text :
{
*(.text)
+ *(.text.*)
*(.fixup)
}
_etext = .;
@@ -41,6 +42,7 @@ SECTIONS
{
*(.sbss)
*(.bss)
+ *(.bss.*)
}
_end = . ;

diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S
index 0962d62..2815506 100644
--- a/arch/powerpc/boot/zImage.lds.S
+++ b/arch/powerpc/boot/zImage.lds.S
@@ -7,6 +7,7 @@ SECTIONS
.text :
{
*(.text)
+ *(.text.*)
*(.fixup)
}
_etext = .;
@@ -45,6 +46,7 @@ SECTIONS
{
*(.sbss)
*(.bss)
+ *(.bss.*)
}
. = ALIGN(4096);
_end = . ;
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S
index aaa469c..a29ce62 100644
--- a/arch/powerpc/boot/zImage.ps3.lds.S
+++ b/arch/powerpc/boot/zImage.ps3.lds.S
@@ -21,6 +21,7 @@ SECTIONS
.text :
{
*(.text)
+ *(.text.*)
*(.fixup)
}
_etext = .;
@@ -44,6 +45,7 @@ SECTIONS
{
*(.sbss)
*(.bss)
+ *(.bss.*)
}
. = ALIGN(4096);
_end = . ;
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
index 862d748..e7d733f 100644
--- a/arch/sh/boot/compressed/vmlinux.scr
+++ b/arch/sh/boot/compressed/vmlinux.scr
@@ -4,6 +4,7 @@ SECTIONS
input_len = .;
LONG(input_data_end - input_data) input_data = .;
*(.data)
+ *(.data.*)
output_len = . - 4;
input_data_end = .;
}
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
index 03c0683..a4af992 100644
--- a/arch/x86/boot/setup.ld
+++ b/arch/x86/boot/setup.ld
@@ -20,7 +20,7 @@ SECTIONS
.initdata : { *(.initdata) }
__end_init = .;

- .text : { *(.text) }
+ .text : { *(.text) *(.text.*) }
.text32 : { *(.text32) }

. = ALIGN(16);
@@ -46,6 +46,7 @@ SECTIONS
{
__bss_start = .;
*(.bss)
+ *(.bss.*)
__bss_end = .;
}
. = ALIGN(16);
diff --git a/arch/xtensa/boot/boot-elf/boot.lds.S b/arch/xtensa/boot/boot-elf/boot.lds.S
index 4e53b74..368d766 100644
--- a/arch/xtensa/boot/boot-elf/boot.lds.S
+++ b/arch/xtensa/boot/boot-elf/boot.lds.S
@@ -10,19 +10,21 @@ SECTIONS
{
__reloc_start = . ;
_text_start = . ;
- *(.literal .text.literal .text)
+ *(.literal .text.literal .text .text.*)
_text_end = . ;
}

.rodata ALIGN(0x04):
{
*(.rodata)
+ *(.rodata.*)
*(.rodata1)
}

.data ALIGN(0x04):
{
*(.data)
+ *(.data.*)
*(.data1)
*(.sdata)
*(.sdata2)
@@ -58,6 +60,7 @@ SECTIONS
*(.scommon)
*(.dynbss)
*(.bss)
+ *(.bss.*)
__bss_end = .;
}
_end = .;
diff --git a/arch/xtensa/boot/boot-redboot/boot.ld b/arch/xtensa/boot/boot-redboot/boot.ld
index 774db20..8747b68 100644
--- a/arch/xtensa/boot/boot-redboot/boot.ld
+++ b/arch/xtensa/boot/boot-redboot/boot.ld
@@ -8,19 +8,21 @@ SECTIONS
{
__reloc_start = . ;
_text_start = . ;
- *(.literal .text.literal .text)
+ *(.literal .text.literal .text .text.*)
_text_end = . ;
}

.rodata ALIGN(0x04):
{
*(.rodata)
+ *(.rodata.*)
*(.rodata1)
}

.data ALIGN(0x04):
{
*(.data)
+ *(.data.*)
*(.data1)
*(.sdata)
*(.sdata2)
@@ -56,6 +58,7 @@ SECTIONS
*(.scommon)
*(.dynbss)
*(.bss)
+ *(.bss.*)
__bss_end = .;
}
_end = .;
--
1.6.2.4

2010-07-28 23:48:27

by Denys Vlasenko

[permalink] [raw]
Subject: [PATCH 3/4] kernel linker stripts: accomodate function and data sections

gcc -ffunction-sections -fdata-sections places each function foo
into separate section .text.foo, and every data object bar into
separate section .data.bar, .rodata.bar or .bss.bar.

Kernel linker scripts were not ready for this and linker heuristics
for orphaned sections were not good enough to result in bootable
kernel.

This fix adds *(.text.*), *(.data.*) etc patterns
directly after corresponding *(.text), *(.data) etc patterns
in all kernel linker scripts. Boot scripts will be handled
in the next fix.

include/asm-generic/vmlinux.lds.h is a little bit more complicated.
It needs to avoid collecting special kernel sections
by using more restrictive patterns like *(.text.[A-Za-z0-9_$^]*)
instead of simplistic *(.text.*): special kernel sections like
.text..page_aligned contain double dots and won't be accidentally
matched by them.

Signed-off-by: Denys Vlasenko <[email protected]>
Acked-by: Sam Ravnborg <[email protected]>
---
arch/frv/kernel/vmlinux.lds.S | 1 -
arch/ia64/scripts/check-segrel.lds | 4 ++--
arch/m68knommu/kernel/vmlinux.lds.S | 1 +
arch/mips/lasat/image/romscript.normal | 1 +
arch/parisc/kernel/vmlinux.lds.S | 1 +
arch/sh/kernel/vsyscall/vsyscall.lds.S | 2 +-
arch/x86/kernel/acpi/realmode/wakeup.lds.S | 1 +
arch/x86/kernel/vmlinux.lds.S | 1 +
include/asm-generic/vmlinux.lds.h | 18 +++++++++++++++++-
9 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index 8b973f3..9949f1a 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS

.sbss : { *(.sbss .sbss.*) }
.bss : { *(.bss .bss.*) }
- .bss..stack : { *(.bss) }

__bss_stop = .;
_end = . ;
diff --git a/arch/ia64/scripts/check-segrel.lds b/arch/ia64/scripts/check-segrel.lds
index 85a0d54..1e23df4 100644
--- a/arch/ia64/scripts/check-segrel.lds
+++ b/arch/ia64/scripts/check-segrel.lds
@@ -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 --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index a91b271..c095a5b 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -169,6 +169,7 @@ SECTIONS {
. = ALIGN(4);
_sbss = . ;
*(.bss)
+ *(.bss.*)
*(COMMON)
. = ALIGN(4) ;
_ebss = . ;
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
index 0864c96..408e5ad 100644
--- a/arch/mips/lasat/image/romscript.normal
+++ b/arch/mips/lasat/image/romscript.normal
@@ -12,6 +12,7 @@ SECTIONS
.data ALIGN(0x10) :
{
*(.data)
+ *(.data.*)
}
_image_start = ADDR(.data);
_image_size = SIZEOF(.data);
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index d64a6bb..56d472c 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -112,6 +112,7 @@ SECTIONS
}
.bss : {
*(.bss)
+ *(.bss.*)
*(COMMON)
}
__bss_stop = .;
diff --git a/arch/sh/kernel/vsyscall/vsyscall.lds.S b/arch/sh/kernel/vsyscall/vsyscall.lds.S
index 6d59ee7..19ee0cb 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.lds.S
+++ b/arch/sh/kernel/vsyscall/vsyscall.lds.S
@@ -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 --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
index 060fff8..38f18e8 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
@@ -42,6 +42,7 @@ SECTIONS
.bss : {
__bss_start = .;
*(.bss)
+ *(.bss.*)
__bss_end = .;
}

diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index d0bb522..eb5b2a6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -307,6 +307,7 @@ SECTIONS
__bss_start = .;
*(.bss..page_aligned)
*(.bss)
+ *(.bss.*)
. = ALIGN(4);
__bss_stop = .;
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 030a954..079895a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -146,9 +146,22 @@
#define TRACE_SYSCALLS()
#endif

+/* .data.foo are generated by gcc itself with -fdata-sections,
+ * whereas double-dot sections (like .data..percpu) are generated
+ * by kernel's magic macros.
+ *
+ * arch/.../vmlinux.lds.S decides where to place various double-dot sections
+ * as needed by its arch, here DATA_DATA needs to be careful and collect
+ * only .data and .data.foo sections, skipping .data..foo
+ *
+ * Same goes for .text, .bss and .rodata. In case of .rodata, various
+ * .rodata.foo sections are generated by gcc even without -fdata-sections
+ */
+
/* .data section */
#define DATA_DATA \
*(.data) \
+ *(.data.[A-Za-z0-9_$^]*) \
*(.ref.data) \
DEV_KEEP(init.data) \
DEV_KEEP(exit.data) \
@@ -212,7 +225,8 @@
. = ALIGN((align)); \
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rodata) = .; \
- *(.rodata) *(.rodata.*) \
+ *(.rodata) \
+ *(.rodata.[A-Za-z0-9_$^]*) \
*(__vermagic) /* Kernel version magic */ \
*(__markers_strings) /* Markers: strings */ \
*(__tracepoints_strings)/* Tracepoints: strings */ \
@@ -379,6 +393,7 @@
ALIGN_FUNCTION(); \
*(.text.hot) \
*(.text) \
+ *(.text.[A-Za-z0-9_$^]*) \
*(.ref.text) \
DEV_KEEP(init.text) \
DEV_KEEP(exit.text) \
@@ -512,6 +527,7 @@
*(.bss..page_aligned) \
*(.dynbss) \
*(.bss) \
+ *(.bss.[A-Za-z0-9_$^]*) \
*(COMMON) \
}

--
1.6.2.4

2010-07-28 23:49:06

by Denys Vlasenko

[permalink] [raw]
Subject: [PATCH 2/4] module linker script: coalesce function and data sections

gcc -ffunction-sections -fdata-sections places each function foo
into separate section .text.foo, and every data object bar into
separate section .data.bar, .rodata.bar or .bss.bar.

This fix prevents kernel modules from having unnecessarily many
sections and thus prevents module size growth when we pass
-ffunction-sections -fdata-sections to gcc.

Module linker script needs to avoid collecting special kernel sections,
therefore it uses more restrictive patterns like *(.text.[A-Za-z0-9_$^]*)
instead of simplistic *(.text.*): special kernel sections like
.text..page_aligned contain double dots and won't be accidentally
matched by them.

Signed-off-by: Denys Vlasenko <[email protected]>
Acked-by: Sam Ravnborg <[email protected]>
---
scripts/module-common.lds | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 47a1f9a..4a197e8 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -3,6 +3,29 @@
* Archs are free to supply their own linker scripts. ld will
* combine them automatically.
*/
+
+/* .data.foo are generated by gcc itself with -fdata-sections,
+ * whereas double-dot sections (like .data..percpu) are generated
+ * by kernel's magic macros.
+ *
+ * Since this script does not specify what to do with double-dot sections,
+ * ld -r will coalesce all .data..foo input sections into one .data..foo
+ * output section, all .data..bar input sections into one .data..bar
+ * output section and so on. This is exactly what we want.
+ *
+ * Same goes for .text, .bss and .rodata. In case of .rodata, various
+ * .rodata.foo sections are generated by gcc even without -fdata-sections
+ */
+
SECTIONS {
+
+ /* Coalesce sections produced by gcc -ffunction-sections */
+ .text 0 : AT(0) { *(.text .text.[A-Za-z0-9_$^]*) }
+
+ /* Coalesce sections produced by gcc -fdata-sections */
+ .rodata 0 : AT(0) { *(.rodata .rodata.[A-Za-z0-9_$^]*) }
+ .data 0 : AT(0) { *(.data .data.[A-Za-z0-9_$^]*) }
+ .bss 0 : AT(0) { *(.bss .bss.[A-Za-z0-9_$^]*) }
+
/DISCARD/ : { *(.discard) }
}
--
1.6.2.4

2010-07-28 23:49:12

by Denys Vlasenko

[permalink] [raw]
Subject: [PATCH 1/4] modpost: support objects with more than 64k sections

This patch makes modpost able to process object files with more than
64k sections. Needed for huge kernel builds (allyesconfig, for example)
with -ffunction-sections.

Signed-off-by: Denys Vlasenko <[email protected]>
Signed-off-by: Anders Kaseorg <[email protected]>
Acked-by: Sam Ravnborg <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Andi Kleen <[email protected]>
---
scripts/mod/file2alias.c | 6 +-
scripts/mod/modpost.c | 102 ++++++++++++++++++++++++++++++++++------------
scripts/mod/modpost.h | 43 +++++++++++++++++++
3 files changed, 122 insertions(+), 29 deletions(-)

diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 5758aab..88f3f07 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -884,16 +884,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
char *zeros = NULL;

/* We're looking for a section relative symbol */
- if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
+ if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
return;

/* Handle all-NULL symbols allocated into .bss */
- if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
+ if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
zeros = calloc(1, sym->st_size);
symval = zeros;
} else {
symval = (void *)info->hdr
- + info->sechdrs[sym->st_shndx].sh_offset
+ + info->sechdrs[get_secindex(info, sym)].sh_offset
+ sym->st_value;
}

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index f6127b9..c827309 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -253,7 +253,7 @@ static enum export export_no(const char *s)
return export_unknown;
}

-static enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
+static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
{
if (sec == elf->export_sec)
return export_plain;
@@ -373,6 +373,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
Elf_Sym *sym;
+ const char *secstrings;
+ unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;

hdr = grab_file(filename, &info->size);
if (!hdr) {
@@ -417,8 +419,27 @@ static int parse_elf(struct elf_info *info, const char *filename)
return 0;
}

+ if (hdr->e_shnum == 0) {
+ /*
+ * There are more than 64k sections,
+ * read count from .sh_size.
+ * note: it doesn't need shndx2secindex()
+ */
+ info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
+ }
+ else {
+ info->num_sections = hdr->e_shnum;
+ }
+ if (hdr->e_shstrndx == SHN_XINDEX) {
+ info->secindex_strings =
+ shndx2secindex(TO_NATIVE(sechdrs[0].sh_link));
+ }
+ else {
+ info->secindex_strings = hdr->e_shstrndx;
+ }
+
/* Fix endianness in section headers */
- for (i = 0; i < hdr->e_shnum; i++) {
+ for (i = 0; i < info->num_sections; i++) {
sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
@@ -431,9 +452,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
}
/* Find symbol table. */
- for (i = 1; i < hdr->e_shnum; i++) {
- const char *secstrings
- = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
+ for (i = 1; i < info->num_sections; i++) {
const char *secname;
int nobits = sechdrs[i].sh_type == SHT_NOBITS;

@@ -461,14 +481,26 @@ static int parse_elf(struct elf_info *info, const char *filename)
else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
info->export_gpl_future_sec = i;

- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ unsigned int sh_link_idx;
+ symtab_idx = i;
+ info->symtab_start = (void *)hdr +
+ sechdrs[i].sh_offset;
+ info->symtab_stop = (void *)hdr +
+ sechdrs[i].sh_offset + sechdrs[i].sh_size;
+ sh_link_idx = shndx2secindex(sechdrs[i].sh_link);
+ info->strtab = (void *)hdr +
+ sechdrs[sh_link_idx].sh_offset;
+ }

- info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
- info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
- + sechdrs[i].sh_size;
- info->strtab = (void *)hdr +
- sechdrs[sechdrs[i].sh_link].sh_offset;
+ /* 32bit section no. table? ("more than 64k sections") */
+ if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {
+ symtab_shndx_idx = i;
+ info->symtab_shndx_start = (void *)hdr +
+ sechdrs[i].sh_offset;
+ info->symtab_shndx_stop = (void *)hdr +
+ sechdrs[i].sh_offset + sechdrs[i].sh_size;
+ }
}
if (!info->symtab_start)
fatal("%s has no symtab?\n", filename);
@@ -480,6 +512,21 @@ static int parse_elf(struct elf_info *info, const char *filename)
sym->st_value = TO_NATIVE(sym->st_value);
sym->st_size = TO_NATIVE(sym->st_size);
}
+
+ if (symtab_shndx_idx != ~0U) {
+ Elf32_Word *p;
+ if (symtab_idx !=
+ shndx2secindex(sechdrs[symtab_shndx_idx].sh_link))
+ fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
+ filename,
+ shndx2secindex(sechdrs[symtab_shndx_idx].sh_link),
+ symtab_idx);
+ /* Fix endianness */
+ for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
+ p++)
+ *p = TO_NATIVE(*p);
+ }
+
return 1;
}

@@ -519,7 +566,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname)
{
unsigned int crc;
- enum export export = export_from_sec(info, sym->st_shndx);
+ enum export export = export_from_sec(info, get_secindex(info, sym));

switch (sym->st_shndx) {
case SHN_COMMON:
@@ -661,19 +708,19 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
return "(unknown)";
}

-static const char *sec_name(struct elf_info *elf, int shndx)
+static const char *sec_name(struct elf_info *elf, int secindex)
{
Elf_Shdr *sechdrs = elf->sechdrs;
return (void *)elf->hdr +
- elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
- sechdrs[shndx].sh_name;
+ elf->sechdrs[elf->secindex_strings].sh_offset +
+ sechdrs[secindex].sh_name;
}

static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
{
return (void *)elf->hdr +
- elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
- sechdr->sh_name;
+ elf->sechdrs[elf->secindex_strings].sh_offset +
+ sechdr->sh_name;
}

/* if sym is empty or point to a string
@@ -1052,11 +1099,14 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
Elf_Sym *near = NULL;
Elf64_Sword distance = 20;
Elf64_Sword d;
+ unsigned int relsym_secindex;

if (relsym->st_name != 0)
return relsym;
+
+ relsym_secindex = get_secindex(elf, relsym);
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
- if (sym->st_shndx != relsym->st_shndx)
+ if (get_secindex(elf, sym) != relsym_secindex)
continue;
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
continue;
@@ -1118,9 +1168,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
const char *symsec;

- if (sym->st_shndx >= SHN_LORESERVE)
+ if (is_shndx_special(sym->st_shndx))
continue;
- symsec = sec_name(elf, sym->st_shndx);
+ symsec = sec_name(elf, get_secindex(elf, sym));
if (strcmp(symsec, sec) != 0)
continue;
if (!is_valid_name(elf, sym))
@@ -1316,7 +1366,7 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
const char *tosec;
const struct sectioncheck *mismatch;

- tosec = sec_name(elf, sym->st_shndx);
+ tosec = sec_name(elf, get_secindex(elf, sym));
mismatch = section_mismatch(fromsec, tosec);
if (mismatch) {
Elf_Sym *to;
@@ -1344,7 +1394,7 @@ static unsigned int *reloc_location(struct elf_info *elf,
Elf_Shdr *sechdr, Elf_Rela *r)
{
Elf_Shdr *sechdrs = elf->sechdrs;
- int section = sechdr->sh_info;
+ int section = shndx2secindex(sechdr->sh_info);

return (void *)elf->hdr + sechdrs[section].sh_offset +
r->r_offset - sechdrs[section].sh_addr;
@@ -1452,7 +1502,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
r.r_addend = TO_NATIVE(rela->r_addend);
sym = elf->symtab_start + r_sym;
/* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
+ if (is_shndx_special(sym->st_shndx))
continue;
check_section_mismatch(modname, elf, &r, sym, fromsec);
}
@@ -1510,7 +1560,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
}
sym = elf->symtab_start + r_sym;
/* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
+ if (is_shndx_special(sym->st_shndx))
continue;
check_section_mismatch(modname, elf, &r, sym, fromsec);
}
@@ -1535,7 +1585,7 @@ static void check_sec_ref(struct module *mod, const char *modname,
Elf_Shdr *sechdrs = elf->sechdrs;

/* Walk through all sections */
- for (i = 0; i < elf->hdr->e_shnum; i++) {
+ for (i = 0; i < elf->num_sections; i++) {
check_section(modname, elf, &elf->sechdrs[i]);
/* We want to process only relocation sections and not .init */
if (sechdrs[i].sh_type == SHT_RELA)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index be987a4..0388cfc 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -129,8 +129,51 @@ struct elf_info {
const char *strtab;
char *modinfo;
unsigned int modinfo_len;
+
+ /* support for 32bit section numbers */
+
+ unsigned int num_sections; /* max_secindex + 1 */
+ unsigned int secindex_strings;
+ /* if Nth symbol table entry has .st_shndx = SHN_XINDEX,
+ * take shndx from symtab_shndx_start[N] instead */
+ Elf32_Word *symtab_shndx_start;
+ Elf32_Word *symtab_shndx_stop;
};

+static inline int is_shndx_special(unsigned int i)
+{
+ return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
+}
+
+/* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus:
+ * shndx == 0 <=> sechdrs[0]
+ * ......
+ * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1]
+ * shndx == SHN_HIRESERVE+1 <=> sechdrs[SHN_LORESERVE]
+ * shndx == SHN_HIRESERVE+2 <=> sechdrs[SHN_LORESERVE+1]
+ * ......
+ * fyi: sym->st_shndx is uint16, SHN_LORESERVE = ff00, SHN_HIRESERVE = ffff,
+ * so basically we map 0000..feff -> 0000..feff
+ * ff00..ffff -> (you are a bad boy, dont do it)
+ * 10000..xxxx -> ff00..(xxxx-0x100)
+ */
+static inline unsigned int shndx2secindex(unsigned int i)
+{
+ if (i <= SHN_HIRESERVE)
+ return i;
+ return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE);
+}
+
+/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
+static inline unsigned int get_secindex(const struct elf_info *info,
+ const Elf_Sym *sym)
+{
+ if (sym->st_shndx != SHN_XINDEX)
+ return sym->st_shndx;
+ return shndx2secindex(info->symtab_shndx_start[sym -
+ info->symtab_start]);
+}
+
/* file2alias.c */
extern unsigned int cross_build;
void handle_moddevtable(struct module *mod, struct elf_info *info,
--
1.6.2.4

2010-07-29 00:25:43

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 2/4] module linker script: coalesce function and data sections

Denys Vlasenko <[email protected]> wrote:

> + .data 0 : AT(0) { *(.data .data.[A-Za-z0-9_$^]*) }
> + .bss 0 : AT(0) { *(.bss .bss.[A-Za-z0-9_$^]*) }

What about .sdata and .sbss sections produced by arches that support small
data sections?

David

2010-07-29 01:24:47

by Denys Vlasenko

[permalink] [raw]
Subject: Re: [PATCH 2/4] module linker script: coalesce function and data sections

On Thursday 29 July 2010 02:25, David Howells wrote:
> Denys Vlasenko <[email protected]> wrote:
>
> > + .data 0 : AT(0) { *(.data .data.[A-Za-z0-9_$^]*) }
> > + .bss 0 : AT(0) { *(.bss .bss.[A-Za-z0-9_$^]*) }
>
> What about .sdata and .sbss sections produced by arches that support small
> data sections?

linker groups all similarly-named input sections into one output section
with the same name, if the name does not match any rule in the linker
script.

Basically, it should work as if there is a rule:

.sbss 0 : AT(0) { *(.sbss) }

--
vda

2010-07-29 09:10:32

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 2/4] module linker script: coalesce function and data sections

Denys Vlasenko <[email protected]> wrote:

> linker groups all similarly-named input sections into one output section
> with the same name, if the name does not match any rule in the linker
> script.
>
> Basically, it should work as if there is a rule:
>
> .sbss 0 : AT(0) { *(.sbss) }

Okay, thanks.

David

2010-08-03 13:48:55

by Michal Marek

[permalink] [raw]
Subject: Re: [PATCH 2/4] module linker script: coalesce function and data sections

On 29.7.2010 01:47, Denys Vlasenko wrote:
> SECTIONS {
> +
> + /* Coalesce sections produced by gcc -ffunction-sections */
> + .text 0 : AT(0) { *(.text .text.[A-Za-z0-9_$^]*) }
> +
> + /* Coalesce sections produced by gcc -fdata-sections */
> + .rodata 0 : AT(0) { *(.rodata .rodata.[A-Za-z0-9_$^]*) }
> + .data 0 : AT(0) { *(.data .data.[A-Za-z0-9_$^]*) }
> + .bss 0 : AT(0) { *(.bss .bss.[A-Za-z0-9_$^]*) }
> +
> /DISCARD/ : { *(.discard) }
> }

I'm now getting

ld:/home/mmarek/linux-2.6/scripts/module-common.lds:23: ignoring invalid
character `^' in script
ld:/home/mmarek/linux-2.6/scripts/module-common.lds:26: ignoring invalid
character `^' in script
ld:/home/mmarek/linux-2.6/scripts/module-common.lds:27: ignoring invalid
character `^' in script
ld:/home/mmarek/linux-2.6/scripts/module-common.lds:28: ignoring invalid
character `^' in script

when linking modules and a similar warning when linking vmlinux (caused
by the next patch in series). I tried writing the carets as \^, but that
doesn't help at all...

$ ld --version
GNU ld (GNU Binutils; openSUSE Factory) 2.20.0.20100122-7

Michal

2010-08-06 02:18:21

by Denys Vlasenko

[permalink] [raw]
Subject: Re: [PATCH 2/4] module linker script: coalesce function and data sections

On Tuesday 03 August 2010 15:47, Michal Marek wrote:
> On 29.7.2010 01:47, Denys Vlasenko wrote:
> > SECTIONS {
> > +
> > + /* Coalesce sections produced by gcc -ffunction-sections */
> > + .text 0 : AT(0) { *(.text .text.[A-Za-z0-9_$^]*) }
> > +
> > + /* Coalesce sections produced by gcc -fdata-sections */
> > + .rodata 0 : AT(0) { *(.rodata .rodata.[A-Za-z0-9_$^]*) }
> > + .data 0 : AT(0) { *(.data .data.[A-Za-z0-9_$^]*) }
> > + .bss 0 : AT(0) { *(.bss .bss.[A-Za-z0-9_$^]*) }
> > +
> > /DISCARD/ : { *(.discard) }
> > }
>
> I'm now getting
>
> ld:/home/mmarek/linux-2.6/scripts/module-common.lds:23: ignoring invalid
> character `^' in script
> ld:/home/mmarek/linux-2.6/scripts/module-common.lds:26: ignoring invalid
> character `^' in script
> ld:/home/mmarek/linux-2.6/scripts/module-common.lds:27: ignoring invalid
> character `^' in script
> ld:/home/mmarek/linux-2.6/scripts/module-common.lds:28: ignoring invalid
> character `^' in script
>
> when linking modules and a similar warning when linking vmlinux (caused
> by the next patch in series). I tried writing the carets as \^, but that
> doesn't help at all...

Yep, I can confirm it. The binutils fix to allow caret might be trivial,
and will allow us to use much better pattern: [^.]*

I created a Fedora bug for it:

https://bugzilla.redhat.com/show_bug.cgi?id=621742

So far, please remove these three patches from kbuild tree.

(I see that modpost patch is in Linus tree. Thanks!)

--
vda