Build system: section garbage collection for vmlinux Newer gcc and binutils can do dead code and data removal at link time. It is achieved using combination of -ffunction-sections -fdata-sections options for gcc and --gc-sections for ld. Theory of operation: Option -ffunction-sections instructs gcc to place each function (including static ones) in it's own section named .text.function_name instead of placing all functions in one big .text section. At link time, ld normally coalesce all such sections into one output section .text again. It is achieved by having *(.text.*) spec along with *(.text) spec in built-in linker scripts. If ld is invoked with --gc-sections, it tracks references, starting from entry point and marks all input sections which are reachable from there. Then it discards all input sections which are not marked. This isn't buying much if you have one big .text section per .o module, because even one referenced function will pull in entire section. You need -ffunction-sections in order to split .text into per-function sections and make --gc-sections much more useful. -fdata-sections is analogous: it places each global or static variable into .data.variable_name, .rodata.variable_name or .bss.variable_name. How to use it in kernel: First, we need to adapt existing code for new section names. Basically, we need to stop using section names of the form .text.xxxx .data.xxxx .rodata.xxxx .bss.xxxx in the kernel for - otherwise section placement done by kernel's custom linker scripts produces broken vmlinux and vdso images. Second, kernel linker scripts need to be adapted by adding KEEP(xxx) directives around sections which are not directly referenced, but are nevertheless used (initcalls, altinstructions, etc). These patches fix section names and add CONFIG_DISCARD_UNUSED_SECTIONS. It is not enabled unconditionally because only newest binutils have ld --gc-sections which is stable enough for kernel use. IOW: this is an experimental feature ...
This patch is needed for --gc-sections to work, regardless
of which final form that support will have.
This patch renames .text.xxx and .data.xxx sections
into .xxx.text and .xxx.data, respectively.
.bss.page_aligned (the only .bss.xxx -like section we have)
is renamed .bss.k.page_aligned. ".page_aligned.bss"
wouldn't work - gcc will assign such section attributes
which make it unmergeable with .bss. In fact, binutils ld
had a bug and instead of complaining was producing
broken vmlinux. The bug is fixed in binutils. Amazingly
fast reaction from binutils folks to bug reports! Thanks!
.bss.k.page_aligned is more-or-less ok, since it cannot collide
with gcc-produced sections due to second dot in the name. However,
should we want to do this in linker script:
.bss : { *(.bss) *(.bss.*) *(.bss.k.page_aligned))
it wouldn't work. But currently we don't need that.
If patch doesn't apply to a newer kernel,
you can regenerate it by running linux-2.6.23-rc4.0.fixname.sh
in a kernel free and rediffing it against unmodified one.
Please apply.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
--
vda
This patch fixes x86_64 vdso image so that it builds with --gc-sections. Then it fixes comment in arch/i386/kernel/vmlinux.lds.S and adds comments to other linker scripts about .bss. Please apply. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> -- vda
This patch makes modpost able to process object files with more than 64k sections. Needed for huge kernel builds (allyesconfig, for example) with --gc-sections. This patch basically fixes modpost, it isn't specific for section garbage collection. Please apply. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> -- vda
This is the core patch of the series. It adds CONFIG_DISCARD_UNUSED_SECTIONS, adds KEEP() directives to linker scripts, adds custom module linker script which is needed to avoid having modules with many small sections. Modules got a bit smaller too, as a result. This patch is slighty more risky than first three, probably need to go into -mm first. It should be safe with CONFIG_DISCARD_UNUSED_SECTIONS off, though. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> -- vda
I think you'll have better luck with this if you focus on a single architecture (i386 would be best) .. Daniel -
I did exactly that. I focused on x86_64. Of course, section name fixes cannot be done per-arch, as they are scattered across entire tree. Apart from that, it was x86_64 only. By now, I also have patches for i386 in hand too. -- vda -
This is want I'm talking about .. Why can't you do this per architecture? Daniel -
With CONFIG_DISCARD_UNUSED_SECTIONS=y ld will helpfully flood you with the list of discarded stuff. I pass --print-gc-sections to it. -- vda -
This is good stuff. I had been using a ported variant of this optimization for ARM on quite an older 2.6 kernel for a while now. I derived that port from: http://lkml.org/lkml/2006/6/4/169 With some tweaks it worked for me. Could you also have a look at the mentioned link and see if that's a superset of what you're trying to achieve? -- Abhishek Sagar -
Hi Abhisshek. Could you post your tweaked version - against an older kernel is OK. Sam -
The inlined patch should apply cleanly on top of the patch posted on
the link I mentioned before. The *.S files are the ones I chose to
bring them under the purview of --ffunction-sections. My observation
remains that if a fine-grained function/data/exported-symbol level
garbage collection can be incorporated into the build environment,
then it'll be something really useful.
--
Abhishek Sagar
---
diff -upNr linux_orig-2.6.12/arch/arm/kernel/armksyms.c
linux-2.6.12/arch/arm/kernel/armksyms.c
--- linux_orig-2.6.12/arch/arm/kernel/armksyms.c 2005-06-18
01:18:29.000000000 +0530
+++ linux-2.6.12/arch/arm/kernel/armksyms.c 2007-09-14 09:00:03.000000000 +0530
@@ -44,10 +44,17 @@ extern void fp_enter(void);
* This has a special calling convention; it doesn't
* modify any of the usual registers, except for LR.
*/
+#ifndef CONFIG_GCSECTIONS
#define EXPORT_SYMBOL_ALIAS(sym,orig) \
const struct kernel_symbol __ksymtab_##sym \
__attribute__((section("__ksymtab"))) = \
{ (unsigned long)&orig, #sym };
+#else
+#define EXPORT_SYMBOL_ALIAS(sym,orig) \
+ const struct kernel_symbol __ksymtab_##sym \
+ __attribute__((section("___ksymtab_" #sym))) = \
+ { (unsigned long)&orig, #sym };
+#endif /* CONFIG_GCSECTIONS */
/*
* floating point math emulator support.
diff -upNr linux_orig-2.6.12/arch/arm/kernel/iwmmxt.S
linux-2.6.12/arch/arm/kernel/iwmmxt.S
--- linux_orig-2.6.12/arch/arm/kernel/iwmmxt.S 2005-06-18
01:18:29.000000000 +0530
+++ linux-2.6.12/arch/arm/kernel/iwmmxt.S 2007-09-14 09:21:01.000000000 +0530
@@ -55,7 +55,11 @@
*
* called from prefetch exception handler with interrupts disabled
*/
-
+#ifdef CONFIG_GCSECTIONS
+ .section ".text.iwmmxt_task_enable"
+#else
+ .text
+#endif
ENTRY(iwmmxt_task_enable)
mrc p15, 0, r2, c15, c1, 0
diff -upNr linux_orig-2.6.12/arch/arm/kernel/vmlinux.lds.S
linux-2.6.12/arch/arm/kernel/vmlinux.lds.S
--- ...