Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1329556 > unrolled thread

[PATCH 0/6] Trim unused exported symbols

Started byNicolas Pitre <nicolas.pitre@linaro.org>
First post2016-02-08 21:50 +0100
Last post2016-02-09 05:40 +0100
Articles 8 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/6] Trim unused exported symbols Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-02-08 21:50 +0100
    [PATCH 2/6] allow for per-symbol configurable EXPORT_SYMBOL() Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-02-08 21:50 +0100
      Re: [PATCH 2/6] allow for per-symbol configurable EXPORT_SYMBOL() Sam Ravnborg <sam@ravnborg.org> - 2016-02-08 23:20 +0100
    [PATCH 1/6] kbuild: record needed exported symbols for modules Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-02-08 21:50 +0100
      Re: [PATCH 1/6] kbuild: record needed exported symbols for modules Sam Ravnborg <sam@ravnborg.org> - 2016-02-08 23:20 +0100
        Re: [PATCH 1/6] kbuild: record needed exported symbols for modules Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-02-08 23:30 +0100
      Re: [PATCH 1/6] kbuild: record needed exported symbols for modules Al Viro <viro@ZenIV.linux.org.uk> - 2016-02-09 05:20 +0100
        Re: [PATCH 1/6] kbuild: record needed exported symbols for modules Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-02-09 05:40 +0100

#1329556 — [PATCH 0/6] Trim unused exported symbols

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-02-08 21:50 +0100
Subject[PATCH 0/6] Trim unused exported symbols
Message-ID<r00UV-1XR-3@gated-at.bofh.it>
The kernel and some modules make many symbols available for
other modules to use via EXPORT_SYMBOL() and variants. Depending
on the set of modules being selected in your kernel configuration,
many of those exported symbols might never be used.

One direct effect of EXPORT_SYMBOL() entries is to force the referenced
code and the code it references into the kernel binary with no
possibilityes for dead code elimination, eeven though the referenced
code is never executed.

This patch series provides the option to omit those exported symbols
from the kernel and modules that are never referenced by any of the
selected modules in the current kernel configuration.  In turns this
allows for optimizing the compiled code and reducing final binaryes'
size. When using LTO the binari size reduction is even more effective.

Also, by removing some entry points, it could be argued that this has
some security advantages by reducing the attack surface of the kernel.
But this is not my main motivation for doing this so I'll let security
experts judge the merit of this claim.

Here's some numbers showing the effect of this series.

Kernel v4.5-rc2 x86 defconfig:

$ size vmlinux
   text    data     bss     dec     hex filename
12362563        1856456 1101824 15320843         e9c70b vmlinux

$ wc -l Module.symvers
8806 Module.symvers

Kernel v4.5-rc2 x86 defconfig + CONFIG_TRIM_UNUSED_EXPSYMS=y:

$ size vmlinux
   text    data     bss     dec     hex filename
12059848        1856456 1101824 15018128         e52890 vmlinux

$ wc -l Module.symvers
225 Module.symvers

Because the x86 defconfig only contains 18 modules, the number of
needed exported symbols is only 225 out of a possible 8806 for this
configuration.  The kernel text size shrank by about 2.4%.

More numbers, on ARM this time.

Kernel v4.5-rc2 arm defconfig (same as multi_v7_defconfig):

$ size vmlinux
   text    data     bss     dec     hex filename
13664222        1554068  351368 15569658         ed92fa vmlinux

$ wc -l Module.symvers
10044 Module.symvers

Kernel v4.5-rc2 arm defconfig + CONFIG_TRIM_UNUSED_EXPSYMS=y:

$ size vmlinux
   text    data     bss     dec     hex filename
13255051        1554132  351240 15160423         e75467 vmlinux

$ wc -l Module.symvers
2703 Module.symvers

This time many more modules (279 of them) are part of the build
configuration. Still, only 2703 out of 10044 exported symbols are
required. And despite a smaller number of omitted exports, the kernel
shrank by 3%.

Now let's add LTO into the mix.

Kernel v4.5-rc2 arm defconfig + LTO:

$ size vmlinux
   text    data     bss     dec     hex filename
12813766        1538324  344356 14696446         e03ffe vmlinux

$ wc -l Module.symvers
8415 Module.symvers

Kernel v4.5-rc2 arm defconfig + LTO + CONFIG_TRIM_UNUSED_EXPSYMS=y:

$ size vmlinux
   text    data     bss     dec     hex filename
12197437        1536052  338660 14072149         d6b955 vmlinux

$ wc -l Module.symvers
1742 Module.symvers

This time the kernel shrank by 5%.

Finally, let's have a look at a configuration that is potentially more
representative of an embedded target.

Kernel v4.5-rc2 arm realview_defconfig + LTO:

$ size vmlinux
   text    data     bss     dec     hex filename
4422942  209640  126880 4759462  489fa6 vmlinux

$ wc -l Module.symvers
5597 Module.symvers

Kernel v4.5-rc2 arm realview_defconfig + LTO + CONFIG_TRIM_UNUSED_EXPSYMS=y:

$ size vmlinux
   text    data     bss     dec     hex filename
3823485  205416  125800 4154701  3f654d vmlinux

$ wc -l Module.symvers
52 Module.symvers

Here we reduced the kernel text by about 13.6%. Disabling module
support altogether would reduce it by 13.9% i.e. only 0.3% difference.
This means the overhead of using modules on embedded targets is greatly
reduced.

I know that Viro posted a series allowing for assembly code to declare
exported symbols but this doesn't conflict (we don't touch the same
files) and making this work with his series is very trivial.

diffstat:


 Makefile                  | 14 +++++++
 include/linux/export.h    | 22 ++++++++++-
 init/Kconfig              | 16 ++++++++
 scripts/Kbuild.include    |  3 +-
 scripts/Makefile.build    | 16 ++++++--
 scripts/adjust_expsyms.sh | 97 +++++++++++++++++++++++++++++++++++++++++++++++
 scripts/basic/fixdep.c    | 80 +++++++++++++++++++++++++++++---------
 7 files changed, 224 insertions(+), 24 deletions(-)

[toc] | [next] | [standalone]


#1329558 — [PATCH 2/6] allow for per-symbol configurable EXPORT_SYMBOL()

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-02-08 21:50 +0100
Subject[PATCH 2/6] allow for per-symbol configurable EXPORT_SYMBOL()
Message-ID<r00UX-1XR-41@gated-at.bofh.it>
In reply to#1329556
Similar to include/generated/autoconf.h, include/generated/expsyms.h will
contain a list of defines for each EXPORT_SYMBOL() that we want active.
The format is:

  #define __EXPSYM_<symbol_name> 1

This list will be auto-generated with another patch.  For now we only
include the preprocessor magic to automatically create or omit the
corresponding struct kernel_symbol declaration.

Given the content of include/generated/expsyms.h may not be known in
advance, an empty file is created early on to let the build proceed.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 Makefile               |  1 +
 include/linux/export.h | 22 ++++++++++++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 6c1a3c2479..3a264129f8 100644
--- a/Makefile
+++ b/Makefile
@@ -986,6 +986,7 @@ prepare2: prepare3 outputmakefile asm-generic
 prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
                    include/config/auto.conf
 	$(cmd_crmodverdir)
+	$(Q)touch include/generated/expsyms.h
 
 archprepare: archheaders archscripts prepare1 scripts_basic
 
diff --git a/include/linux/export.h b/include/linux/export.h
index 96e45ea463..f8e4d9da35 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -38,7 +38,7 @@ extern struct module __this_module;
 
 #ifdef CONFIG_MODULES
 
-#ifndef __GENKSYMS__
+#if defined(__KERNEL__) && !defined(__GENKSYMS__)
 #ifdef CONFIG_MODVERSIONS
 /* Mark the CRC weak since genksyms apparently decides not to
  * generate a checksums for some symbols */
@@ -53,7 +53,7 @@ extern struct module __this_module;
 #endif
 
 /* For every exported symbol, place a struct in the __ksymtab section */
-#define __EXPORT_SYMBOL(sym, sec)				\
+#define ___EXPORT_SYMBOL(sym, sec)				\
 	extern typeof(sym) sym;					\
 	__CRC_SYMBOL(sym, sec)					\
 	static const char __kstrtab_##sym[]			\
@@ -65,6 +65,24 @@ extern struct module __this_module;
 	__attribute__((section("___ksymtab" sec "+" #sym), unused))	\
 	= { (unsigned long)&sym, __kstrtab_##sym }
 
+#ifdef CONFIG_TRIM_UNUSED_EXPSYMS
+
+#include <linux/kconfig.h>
+#include <generated/expsyms.h>
+
+#define __EXPORT_SYMBOL(sym, sec)				\
+	__cond_export_sym(sym, sec, config_enabled(__EXPSYM_##sym))
+#define __cond_export_sym(sym, sec, conf)			\
+	___cond_export_sym(sym, sec, conf)
+#define ___cond_export_sym(sym, sec, enabled)			\
+	__cond_export_sym_##enabled(sym, sec)
+#define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec)
+#define __cond_export_sym_0(sym, sec) /* nothing */
+
+#else
+#define __EXPORT_SYMBOL ___EXPORT_SYMBOL
+#endif
+
 #define EXPORT_SYMBOL(sym)					\
 	__EXPORT_SYMBOL(sym, "")
 
-- 
2.5.0

[toc] | [prev] | [next] | [standalone]


#1329628 — Re: [PATCH 2/6] allow for per-symbol configurable EXPORT_SYMBOL()

FromSam Ravnborg <sam@ravnborg.org>
Date2016-02-08 23:20 +0100
SubjectRe: [PATCH 2/6] allow for per-symbol configurable EXPORT_SYMBOL()
Message-ID<r02k2-2Zq-3@gated-at.bofh.it>
In reply to#1329558
On Mon, Feb 08, 2016 at 03:28:31PM -0500, Nicolas Pitre wrote:
> Similar to include/generated/autoconf.h, include/generated/expsyms.h will
> contain a list of defines for each EXPORT_SYMBOL() that we want active.
> The format is:
> 
>   #define __EXPSYM_<symbol_name> 1

Please spell it out.
EXP could be EXPECT...


> +	$(Q)touch include/generated/expsyms.h

Same goes here. Make it explicit what this is about.
It is obvious today that "exp" is synonym for export_symbol.
But in one year less so.

Same goes for CONFIG_ symbol etc.

	Sam
> 

[toc] | [prev] | [next] | [standalone]


#1329559 — [PATCH 1/6] kbuild: record needed exported symbols for modules

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-02-08 21:50 +0100
Subject[PATCH 1/6] kbuild: record needed exported symbols for modules
Message-ID<r00UX-1XR-43@gated-at.bofh.it>
In reply to#1329556
Kernel modules are partially linked object files with some undefined
symbols that are expected to be matched with EXPORT_SYMBOL() entries
from elsewhere.

Each .tmp_versions/*.mod file currently contains two line of text
separated by a newline character. The first line has the actual module
file name while the second line has a list of object files constituting
that module. Those files are parsed by modpost (scripts/mod/sumversion.c),
scripts/Makefile.modpost, scripts/Makefile.modsign, etc.  Only the
modpost utility cares about the second line while the others retrieve
only the first line.

Therefore we can add a third line to record the list of undefined symbols
aka required EXPORT_SYMBOL() entries for each module into that file
without breaking anything. Like for the second line, symbols are separated
by a blank and the list is terminated with a newline character.

To avoid needless build overhead, the undefined symbols extraction is
performed only when CONFIG_TRIM_UNUSED_EXPSYMS is selected.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 scripts/Makefile.build | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 2c47f9c305..1d8b07ea3e 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -253,6 +253,13 @@ define rule_cc_o_c
 	mv -f $(dot-target).tmp $(dot-target).cmd
 endef
 
+# List module undefined symbols
+ifdef CONFIG_TRIM_UNUSED_EXPSYMS
+cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U \(.*\)/\1/p' | xargs echo
+else
+cmd_undef_syms = echo
+endif
+
 # Built-in and composite module parts
 $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
 	$(call cmd,force_checksrc)
@@ -263,7 +270,8 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
 $(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
 	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
-	@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
+	@{ echo $(@:.o=.ko); echo $@; \
+	   $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
 
 quiet_cmd_cc_lst_c = MKLST   $@
       cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
@@ -393,7 +401,8 @@ $(call multi_depend, $(multi-used-y), .o, -objs -y)
 
 $(multi-used-m): FORCE
 	$(call if_changed,link_multi-m)
-	@{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
+	@{ echo $(@:.o=.ko); echo $(link_multi_deps); \
+	   $(cmd_undef_syms); } > $(MODVERDIR)/$(@F:.o=.mod)
 $(call multi_depend, $(multi-used-m), .o, -objs -y -m)
 
 targets += $(multi-used-y) $(multi-used-m)
-- 
2.5.0

[toc] | [prev] | [next] | [standalone]


#1329633 — Re: [PATCH 1/6] kbuild: record needed exported symbols for modules

FromSam Ravnborg <sam@ravnborg.org>
Date2016-02-08 23:20 +0100
SubjectRe: [PATCH 1/6] kbuild: record needed exported symbols for modules
Message-ID<r02k2-2Zq-21@gated-at.bofh.it>
In reply to#1329559
>  
> +# List module undefined symbols
> +ifdef CONFIG_TRIM_UNUSED_EXPSYMS
> +cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U \(.*\)/\1/p' | xargs echo
> +else
> +cmd_undef_syms = echo
> +endif
Use ":" as a "do nothing" cammand. Then you do not emit an empty line.

	Sam

[toc] | [prev] | [next] | [standalone]


#1329645 — Re: [PATCH 1/6] kbuild: record needed exported symbols for modules

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-02-08 23:30 +0100
SubjectRe: [PATCH 1/6] kbuild: record needed exported symbols for modules
Message-ID<r02tJ-33a-19@gated-at.bofh.it>
In reply to#1329633
On Mon, 8 Feb 2016, Sam Ravnborg wrote:

> >  
> > +# List module undefined symbols
> > +ifdef CONFIG_TRIM_UNUSED_EXPSYMS
> > +cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U \(.*\)/\1/p' | xargs echo
> > +else
> > +cmd_undef_syms = echo
> > +endif
> Use ":" as a "do nothing" cammand. Then you do not emit an empty line.

I wanted to emit that empty line though. This way it is less likely that 
it'll be reused for other purposes.


Nicolas

[toc] | [prev] | [next] | [standalone]


#1329896 — Re: [PATCH 1/6] kbuild: record needed exported symbols for modules

FromAl Viro <viro@ZenIV.linux.org.uk>
Date2016-02-09 05:20 +0100
SubjectRe: [PATCH 1/6] kbuild: record needed exported symbols for modules
Message-ID<r07Wp-76h-3@gated-at.bofh.it>
In reply to#1329559
On Mon, Feb 08, 2016 at 03:28:30PM -0500, Nicolas Pitre wrote:
> +ifdef CONFIG_TRIM_UNUSED_EXPSYMS
> +cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U \(.*\)/\1/p' | xargs echo

Umm...  sed -nre 's/^ +U //p', perhaps?

[toc] | [prev] | [next] | [standalone]


#1329902 — Re: [PATCH 1/6] kbuild: record needed exported symbols for modules

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-02-09 05:40 +0100
SubjectRe: [PATCH 1/6] kbuild: record needed exported symbols for modules
Message-ID<r08fM-7if-7@gated-at.bofh.it>
In reply to#1329896
On Tue, 9 Feb 2016, Al Viro wrote:

> On Mon, Feb 08, 2016 at 03:28:30PM -0500, Nicolas Pitre wrote:
> > +ifdef CONFIG_TRIM_UNUSED_EXPSYMS
> > +cmd_undef_syms = $(NM) $@ | sed -n 's/^ \+U \(.*\)/\1/p' | xargs echo
> 
> Umm...  sed -nre 's/^ +U //p', perhaps?

Yep, I like it better.

Although I might be tempted by sed -n 's/^ \+U //p' to avoid the "non 
portable" mention that comes with -r (do we actually care?).


Nicolas

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web