[v2] module: use relative references for __ksymtab entries

Message ID 20170806124624.22915-1-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Aug. 6, 2017, 12:46 p.m.
An ordinary arm64 defconfig build has ~64 KB worth of __ksymtab
entries, each consisting of two 64-bit fields containing absolute
references, to the symbol itself and to a char array containing
its name, respectively.

When we build the same configuration with KASLR enabled, we end
up with an additional ~192 KB of relocations in the .init section,
i.e., one 24 byte entry for each absolute reference, which all need
to be processed at boot time.

Given how the struct kernel_symbol that describes each entry is
completely local to module.c (except for the references emitted
by EXPORT_SYMBOL() itself), we can easily modify it to contain
two 32-bit relative references instead. This reduces the size of
the __ksymtab section by 50% for all 64-bit architectures, and
gets rid of the runtime relocations entirely for architectures
implementing KASLR, either via standard PIE linking (arm64) or
using custom host tools (x86).

Since EXPORT_SYMBOL() no longer refers to struct kernel_symbol,
move the definition into module.c, which is its only user.

Note that the binary search involving __ksymtab contents relies
on each section being sorted by symbol name. This is implemented
based on the input section names, not the names in the ksymtab
entries, so this patch does not interfere with that.

Cc: Jessica Yu <jeyu@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
v2: - fix error in modpost due to missing local __ksymtab_xxx symbol names

Note that ARM requires a little tweak to ensure that the unwind
info related to the discarded code is discarded as well. I'm sure
there will be an arch or two where something similar may be required.

 arch/arm/kernel/vmlinux.lds.S |  1 +
 include/asm-generic/export.h  | 10 +------
 include/linux/export.h        | 28 ++++++++++--------
 kernel/module.c               | 31 ++++++++++++++++----
 4 files changed, 43 insertions(+), 27 deletions(-)

-- 
2.11.0

Comments

kbuild test robot Aug. 6, 2017, 2:05 p.m. | #1
Hi Ard,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.13-rc3 next-20170804]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Ard-Biesheuvel/module-use-relative-references-for-__ksymtab-entries/20170806-205309
config: x86_64-allyesdebian (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   In file included from include/asm-generic/percpu.h:6:0,
                    from arch/x86/include/asm/percpu.h:542,
                    from arch/x86/include/asm/current.h:5,
                    from include/linux/mutex.h:13,
                    from kernel//locking/lockdep.c:29:
>> include/linux/percpu-defs.h:92:26: error: __pcpu_unique_cpu_lock_stats causes a section type conflict with __discard_lockdep_off

     __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;   \
                             ^
   include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION'
     DEFINE_PER_CPU_SECTION(type, name, "")
     ^~~~~~~~~~~~~~~~~~~~~~
   kernel//locking/lockdep.c:156:8: note: in expansion of macro 'DEFINE_PER_CPU'
    static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
           ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from arch/x86/include/asm/percpu.h:44,
                    from arch/x86/include/asm/current.h:5,
                    from include/linux/mutex.h:13,
                    from kernel//locking/lockdep.c:29:
   include/linux/export.h:71:4: note: '__discard_lockdep_off' was declared here
       __discard_##sym(void) { return (void *)&sym; } \
       ^
   include/linux/export.h:104:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:108:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
   kernel//locking/lockdep.c:329:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(lockdep_off);
    ^~~~~~~~~~~~~
--
   In file included from include/asm-generic/percpu.h:6:0,
                    from arch/x86/include/asm/percpu.h:542,
                    from arch/x86/include/asm/current.h:5,
                    from include/linux/mutex.h:13,
                    from kernel///locking/lockdep.c:29:
>> include/linux/percpu-defs.h:92:26: error: __pcpu_unique_cpu_lock_stats causes a section type conflict with __discard_lockdep_off

     __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;   \
                             ^
   include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION'
     DEFINE_PER_CPU_SECTION(type, name, "")
     ^~~~~~~~~~~~~~~~~~~~~~
   kernel///locking/lockdep.c:156:8: note: in expansion of macro 'DEFINE_PER_CPU'
    static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
           ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from arch/x86/include/asm/percpu.h:44,
                    from arch/x86/include/asm/current.h:5,
                    from include/linux/mutex.h:13,
                    from kernel///locking/lockdep.c:29:
   include/linux/export.h:71:4: note: '__discard_lockdep_off' was declared here
       __discard_##sym(void) { return (void *)&sym; } \
       ^
   include/linux/export.h:104:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:108:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
   kernel///locking/lockdep.c:329:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(lockdep_off);
    ^~~~~~~~~~~~~

vim +92 include/linux/percpu-defs.h

62fde541 Tejun Heo     2014-06-17   37  
5028eaa9 David Howells 2009-04-21   38  /*
5028eaa9 David Howells 2009-04-21   39   * Base implementations of per-CPU variable declarations and definitions, where
5028eaa9 David Howells 2009-04-21   40   * the section in which the variable is to be placed is provided by the
7c756e6e Tejun Heo     2009-06-24   41   * 'sec' argument.  This may be used to affect the parameters governing the
5028eaa9 David Howells 2009-04-21   42   * variable's storage.
5028eaa9 David Howells 2009-04-21   43   *
5028eaa9 David Howells 2009-04-21   44   * NOTE!  The sections for the DECLARE and for the DEFINE must match, lest
5028eaa9 David Howells 2009-04-21   45   * linkage errors occur due the compiler generating the wrong code to access
5028eaa9 David Howells 2009-04-21   46   * that section.
5028eaa9 David Howells 2009-04-21   47   */
7c756e6e Tejun Heo     2009-06-24   48  #define __PCPU_ATTRS(sec)						\
e0fdb0e0 Rusty Russell 2009-10-29   49  	__percpu __attribute__((section(PER_CPU_BASE_SECTION sec)))	\
7c756e6e Tejun Heo     2009-06-24   50  	PER_CPU_ATTRIBUTES
7c756e6e Tejun Heo     2009-06-24   51  
7c756e6e Tejun Heo     2009-06-24   52  #define __PCPU_DUMMY_ATTRS						\
7c756e6e Tejun Heo     2009-06-24   53  	__attribute__((section(".discard"), unused))
7c756e6e Tejun Heo     2009-06-24   54  
7c756e6e Tejun Heo     2009-06-24   55  /*
7c756e6e Tejun Heo     2009-06-24   56   * s390 and alpha modules require percpu variables to be defined as
7c756e6e Tejun Heo     2009-06-24   57   * weak to force the compiler to generate GOT based external
7c756e6e Tejun Heo     2009-06-24   58   * references for them.  This is necessary because percpu sections
7c756e6e Tejun Heo     2009-06-24   59   * will be located outside of the usually addressable area.
7c756e6e Tejun Heo     2009-06-24   60   *
7c756e6e Tejun Heo     2009-06-24   61   * This definition puts the following two extra restrictions when
7c756e6e Tejun Heo     2009-06-24   62   * defining percpu variables.
7c756e6e Tejun Heo     2009-06-24   63   *
7c756e6e Tejun Heo     2009-06-24   64   * 1. The symbol must be globally unique, even the static ones.
7c756e6e Tejun Heo     2009-06-24   65   * 2. Static percpu variables cannot be defined inside a function.
7c756e6e Tejun Heo     2009-06-24   66   *
7c756e6e Tejun Heo     2009-06-24   67   * Archs which need weak percpu definitions should define
7c756e6e Tejun Heo     2009-06-24   68   * ARCH_NEEDS_WEAK_PER_CPU in asm/percpu.h when necessary.
7c756e6e Tejun Heo     2009-06-24   69   *
7c756e6e Tejun Heo     2009-06-24   70   * To ensure that the generic code observes the above two
7c756e6e Tejun Heo     2009-06-24   71   * restrictions, if CONFIG_DEBUG_FORCE_WEAK_PER_CPU is set weak
7c756e6e Tejun Heo     2009-06-24   72   * definition is used for all cases.
7c756e6e Tejun Heo     2009-06-24   73   */
7c756e6e Tejun Heo     2009-06-24   74  #if defined(ARCH_NEEDS_WEAK_PER_CPU) || defined(CONFIG_DEBUG_FORCE_WEAK_PER_CPU)
7c756e6e Tejun Heo     2009-06-24   75  /*
7c756e6e Tejun Heo     2009-06-24   76   * __pcpu_scope_* dummy variable is used to enforce scope.  It
7c756e6e Tejun Heo     2009-06-24   77   * receives the static modifier when it's used in front of
7c756e6e Tejun Heo     2009-06-24   78   * DEFINE_PER_CPU() and will trigger build failure if
7c756e6e Tejun Heo     2009-06-24   79   * DECLARE_PER_CPU() is used for the same variable.
7c756e6e Tejun Heo     2009-06-24   80   *
7c756e6e Tejun Heo     2009-06-24   81   * __pcpu_unique_* dummy variable is used to enforce symbol uniqueness
7c756e6e Tejun Heo     2009-06-24   82   * such that hidden weak symbol collision, which will cause unrelated
7c756e6e Tejun Heo     2009-06-24   83   * variables to share the same address, can be detected during build.
7c756e6e Tejun Heo     2009-06-24   84   */
7c756e6e Tejun Heo     2009-06-24   85  #define DECLARE_PER_CPU_SECTION(type, name, sec)			\
7c756e6e Tejun Heo     2009-06-24   86  	extern __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;		\
dd17c8f7 Rusty Russell 2009-10-29   87  	extern __PCPU_ATTRS(sec) __typeof__(type) name
7c756e6e Tejun Heo     2009-06-24   88  
7c756e6e Tejun Heo     2009-06-24   89  #define DEFINE_PER_CPU_SECTION(type, name, sec)				\
7c756e6e Tejun Heo     2009-06-24   90  	__PCPU_DUMMY_ATTRS char __pcpu_scope_##name;			\
0f5e4816 Tejun Heo     2009-10-29   91  	extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;		\
7c756e6e Tejun Heo     2009-06-24  @92  	__PCPU_DUMMY_ATTRS char __pcpu_unique_##name;			\
b1a0fbfd Tejun Heo     2013-12-04   93  	extern __PCPU_ATTRS(sec) __typeof__(type) name;			\
c43768cb Tejun Heo     2009-07-04   94  	__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak			\
dd17c8f7 Rusty Russell 2009-10-29   95  	__typeof__(type) name
7c756e6e Tejun Heo     2009-06-24   96  #else
7c756e6e Tejun Heo     2009-06-24   97  /*
7c756e6e Tejun Heo     2009-06-24   98   * Normal declaration and definition macros.
7c756e6e Tejun Heo     2009-06-24   99   */
7c756e6e Tejun Heo     2009-06-24  100  #define DECLARE_PER_CPU_SECTION(type, name, sec)			\
dd17c8f7 Rusty Russell 2009-10-29  101  	extern __PCPU_ATTRS(sec) __typeof__(type) name
7c756e6e Tejun Heo     2009-06-24  102  

:::::: The code at line 92 was first introduced by commit
:::::: 7c756e6e19e71f0327760d8955f7077118ebb2b1 percpu: implement optional weak percpu definitions

:::::: TO: Tejun Heo <tj@kernel.org>
:::::: CC: Tejun Heo <tj@kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kbuild test robot Aug. 6, 2017, 3:10 p.m. | #2
Hi Ard,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.13-rc3 next-20170804]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Ard-Biesheuvel/module-use-relative-references-for-__ksymtab-entries/20170806-205309
config: x86_64-allyesdebian (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   In file included from include/asm-generic/percpu.h:6:0,
                    from arch/x86/include/asm/percpu.h:542,
                    from arch/x86/include/asm/preempt.h:5,
                    from include/linux/preempt.h:80,
                    from include/linux/spinlock.h:50,
                    from include/linux/mmzone.h:7,
                    from include/linux/gfp.h:5,
                    from include/linux/slab.h:14,
                    from kernel/fork.c:14:
>> include/linux/percpu-defs.h:92:26: error: __pcpu_unique_cached_stacks causes a section type conflict with __discard_lockdep_tasklist_lock_is_held

     __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;   \
                             ^
   include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION'
     DEFINE_PER_CPU_SECTION(type, name, "")
     ^~~~~~~~~~~~~~~~~~~~~~
   kernel/fork.c:181:8: note: in expansion of macro 'DEFINE_PER_CPU'
    static DEFINE_PER_CPU(struct vm_struct *, cached_stacks[NR_CACHED_STACKS]);
           ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:15,
                    from arch/x86/include/asm/bug.h:81,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/gfp.h:4,
                    from include/linux/slab.h:14,
                    from kernel/fork.c:14:
   include/linux/export.h:71:4: note: '__discard_lockdep_tasklist_lock_is_held' was declared here
       __discard_##sym(void) { return (void *)&sym; } \
       ^
   include/linux/export.h:104:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:111:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "_gpl")
     ^~~~~~~~~~~~~~~
   kernel/fork.c:131:1: note: in expansion of macro 'EXPORT_SYMBOL_GPL'
    EXPORT_SYMBOL_GPL(lockdep_tasklist_lock_is_held);
    ^~~~~~~~~~~~~~~~~
--
   In file included from include/asm-generic/percpu.h:6:0,
                    from arch/x86/include/asm/percpu.h:542,
                    from arch/x86/include/asm/preempt.h:5,
                    from include/linux/preempt.h:80,
                    from include/linux/spinlock.h:50,
                    from include/linux/mmzone.h:7,
                    from include/linux/gfp.h:5,
                    from include/linux/slab.h:14,
                    from mm/slab.c:89:
>> include/linux/percpu-defs.h:92:26: error: __pcpu_unique_slab_reap_node causes a section type conflict with __discard_kmem_cache_alloc

     __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;   \
                             ^
   include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION'
     DEFINE_PER_CPU_SECTION(type, name, "")
     ^~~~~~~~~~~~~~~~~~~~~~
>> mm/slab.c:524:8: note: in expansion of macro 'DEFINE_PER_CPU'

    static DEFINE_PER_CPU(unsigned long, slab_reap_node);
           ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:15,
                    from arch/x86/include/asm/bug.h:81,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/gfp.h:4,
                    from include/linux/slab.h:14,
                    from mm/slab.c:89:
   include/linux/export.h:71:4: note: '__discard_kmem_cache_alloc' was declared here
       __discard_##sym(void) { return (void *)&sym; } \
       ^
   include/linux/export.h:104:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:108:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
   mm/slab.c:3567:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(kmem_cache_alloc);
    ^~~~~~~~~~~~~

vim +92 include/linux/percpu-defs.h

62fde541 Tejun Heo     2014-06-17   37  
5028eaa9 David Howells 2009-04-21   38  /*
5028eaa9 David Howells 2009-04-21   39   * Base implementations of per-CPU variable declarations and definitions, where
5028eaa9 David Howells 2009-04-21   40   * the section in which the variable is to be placed is provided by the
7c756e6e Tejun Heo     2009-06-24   41   * 'sec' argument.  This may be used to affect the parameters governing the
5028eaa9 David Howells 2009-04-21   42   * variable's storage.
5028eaa9 David Howells 2009-04-21   43   *
5028eaa9 David Howells 2009-04-21   44   * NOTE!  The sections for the DECLARE and for the DEFINE must match, lest
5028eaa9 David Howells 2009-04-21   45   * linkage errors occur due the compiler generating the wrong code to access
5028eaa9 David Howells 2009-04-21   46   * that section.
5028eaa9 David Howells 2009-04-21   47   */
7c756e6e Tejun Heo     2009-06-24   48  #define __PCPU_ATTRS(sec)						\
e0fdb0e0 Rusty Russell 2009-10-29   49  	__percpu __attribute__((section(PER_CPU_BASE_SECTION sec)))	\
7c756e6e Tejun Heo     2009-06-24   50  	PER_CPU_ATTRIBUTES
7c756e6e Tejun Heo     2009-06-24   51  
7c756e6e Tejun Heo     2009-06-24   52  #define __PCPU_DUMMY_ATTRS						\
7c756e6e Tejun Heo     2009-06-24   53  	__attribute__((section(".discard"), unused))
7c756e6e Tejun Heo     2009-06-24   54  
7c756e6e Tejun Heo     2009-06-24   55  /*
7c756e6e Tejun Heo     2009-06-24   56   * s390 and alpha modules require percpu variables to be defined as
7c756e6e Tejun Heo     2009-06-24   57   * weak to force the compiler to generate GOT based external
7c756e6e Tejun Heo     2009-06-24   58   * references for them.  This is necessary because percpu sections
7c756e6e Tejun Heo     2009-06-24   59   * will be located outside of the usually addressable area.
7c756e6e Tejun Heo     2009-06-24   60   *
7c756e6e Tejun Heo     2009-06-24   61   * This definition puts the following two extra restrictions when
7c756e6e Tejun Heo     2009-06-24   62   * defining percpu variables.
7c756e6e Tejun Heo     2009-06-24   63   *
7c756e6e Tejun Heo     2009-06-24   64   * 1. The symbol must be globally unique, even the static ones.
7c756e6e Tejun Heo     2009-06-24   65   * 2. Static percpu variables cannot be defined inside a function.
7c756e6e Tejun Heo     2009-06-24   66   *
7c756e6e Tejun Heo     2009-06-24   67   * Archs which need weak percpu definitions should define
7c756e6e Tejun Heo     2009-06-24   68   * ARCH_NEEDS_WEAK_PER_CPU in asm/percpu.h when necessary.
7c756e6e Tejun Heo     2009-06-24   69   *
7c756e6e Tejun Heo     2009-06-24   70   * To ensure that the generic code observes the above two
7c756e6e Tejun Heo     2009-06-24   71   * restrictions, if CONFIG_DEBUG_FORCE_WEAK_PER_CPU is set weak
7c756e6e Tejun Heo     2009-06-24   72   * definition is used for all cases.
7c756e6e Tejun Heo     2009-06-24   73   */
7c756e6e Tejun Heo     2009-06-24   74  #if defined(ARCH_NEEDS_WEAK_PER_CPU) || defined(CONFIG_DEBUG_FORCE_WEAK_PER_CPU)
7c756e6e Tejun Heo     2009-06-24   75  /*
7c756e6e Tejun Heo     2009-06-24   76   * __pcpu_scope_* dummy variable is used to enforce scope.  It
7c756e6e Tejun Heo     2009-06-24   77   * receives the static modifier when it's used in front of
7c756e6e Tejun Heo     2009-06-24   78   * DEFINE_PER_CPU() and will trigger build failure if
7c756e6e Tejun Heo     2009-06-24   79   * DECLARE_PER_CPU() is used for the same variable.
7c756e6e Tejun Heo     2009-06-24   80   *
7c756e6e Tejun Heo     2009-06-24   81   * __pcpu_unique_* dummy variable is used to enforce symbol uniqueness
7c756e6e Tejun Heo     2009-06-24   82   * such that hidden weak symbol collision, which will cause unrelated
7c756e6e Tejun Heo     2009-06-24   83   * variables to share the same address, can be detected during build.
7c756e6e Tejun Heo     2009-06-24   84   */
7c756e6e Tejun Heo     2009-06-24   85  #define DECLARE_PER_CPU_SECTION(type, name, sec)			\
7c756e6e Tejun Heo     2009-06-24   86  	extern __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;		\
dd17c8f7 Rusty Russell 2009-10-29   87  	extern __PCPU_ATTRS(sec) __typeof__(type) name
7c756e6e Tejun Heo     2009-06-24   88  
7c756e6e Tejun Heo     2009-06-24   89  #define DEFINE_PER_CPU_SECTION(type, name, sec)				\
7c756e6e Tejun Heo     2009-06-24   90  	__PCPU_DUMMY_ATTRS char __pcpu_scope_##name;			\
0f5e4816 Tejun Heo     2009-10-29   91  	extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;		\
7c756e6e Tejun Heo     2009-06-24  @92  	__PCPU_DUMMY_ATTRS char __pcpu_unique_##name;			\
b1a0fbfd Tejun Heo     2013-12-04   93  	extern __PCPU_ATTRS(sec) __typeof__(type) name;			\
c43768cb Tejun Heo     2009-07-04   94  	__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak			\
dd17c8f7 Rusty Russell 2009-10-29   95  	__typeof__(type) name
7c756e6e Tejun Heo     2009-06-24   96  #else
7c756e6e Tejun Heo     2009-06-24   97  /*
7c756e6e Tejun Heo     2009-06-24   98   * Normal declaration and definition macros.
7c756e6e Tejun Heo     2009-06-24   99   */
7c756e6e Tejun Heo     2009-06-24  100  #define DECLARE_PER_CPU_SECTION(type, name, sec)			\
dd17c8f7 Rusty Russell 2009-10-29  101  	extern __PCPU_ATTRS(sec) __typeof__(type) name
7c756e6e Tejun Heo     2009-06-24  102  

:::::: The code at line 92 was first introduced by commit
:::::: 7c756e6e19e71f0327760d8955f7077118ebb2b1 percpu: implement optional weak percpu definitions

:::::: TO: Tejun Heo <tj@kernel.org>
:::::: CC: Tejun Heo <tj@kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Patch

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index c83a7ba737d6..4bdba75e510c 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -89,6 +89,7 @@  SECTIONS
 #endif
 		*(.discard)
 		*(.discard.*)
+		*(.ARM.exidx.discard)
 	}
 
 	. = PAGE_OFFSET + TEXT_OFFSET;
diff --git a/include/asm-generic/export.h b/include/asm-generic/export.h
index 719db1968d81..fac5b2e6df37 100644
--- a/include/asm-generic/export.h
+++ b/include/asm-generic/export.h
@@ -4,17 +4,9 @@ 
 #ifndef KSYM_FUNC
 #define KSYM_FUNC(x) x
 #endif
-#ifdef CONFIG_64BIT
-#define __put .quad
 #ifndef KSYM_ALIGN
 #define KSYM_ALIGN 8
 #endif
-#else
-#define __put .long
-#ifndef KSYM_ALIGN
-#define KSYM_ALIGN 4
-#endif
-#endif
 #ifndef KCRC_ALIGN
 #define KCRC_ALIGN 4
 #endif
@@ -35,7 +27,7 @@ 
 	.section ___ksymtab\sec+\name,"a"
 	.balign KSYM_ALIGN
 KSYM(__ksymtab_\name):
-	__put \val, KSYM(__kstrtab_\name)
+	.long \val - ., KSYM(__kstrtab_\name) - .
 	.previous
 	.section __ksymtab_strings,"a"
 KSYM(__kstrtab_\name):
diff --git a/include/linux/export.h b/include/linux/export.h
index 1a1dfdb2a5c6..943656d74f0c 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -24,12 +24,6 @@ 
 #define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
 
 #ifndef __ASSEMBLY__
-struct kernel_symbol
-{
-	unsigned long value;
-	const char *name;
-};
-
 #ifdef MODULE
 extern struct module __this_module;
 #define THIS_MODULE (&__this_module)
@@ -60,17 +54,27 @@  extern struct module __this_module;
 #define __CRC_SYMBOL(sym, sec)
 #endif
 
-/* For every exported symbol, place a struct in the __ksymtab section */
+/*
+ * For every exported symbol, place a struct in the __ksymtab section.
+ * Note that we have to visibly take the address of sym, so the compiler
+ * is forced to emit it, rather than inlining it or removing it
+ * altogether. Do so in a way that avoids taking the address statically,
+ * and emit that code into a section that is discarded by the linker.
+ */
 #define ___EXPORT_SYMBOL(sym, sec)					\
 	extern typeof(sym) sym;						\
 	__CRC_SYMBOL(sym, sec)						\
 	static const char __kstrtab_##sym[]				\
-	__attribute__((section("__ksymtab_strings"), aligned(1)))	\
+	__attribute__((section("__ksymtab_strings"), used, aligned(1)))	\
 	= VMLINUX_SYMBOL_STR(sym);					\
-	static const struct kernel_symbol __ksymtab_##sym		\
-	__used								\
-	__attribute__((section("___ksymtab" sec "+" #sym), used))	\
-	= { (unsigned long)&sym, __kstrtab_##sym }
+	static void * __attribute__((section(".discard"), used))	\
+			__discard_##sym(void) { return (void *)&sym; }	\
+	asm("	.section \"___ksymtab" sec "+" #sym "\", \"a\"	\n"	\
+	    "	.balign	8					\n"	\
+	    VMLINUX_SYMBOL_STR(__ksymtab_##sym) ":		\n"	\
+	    "	.long "	VMLINUX_SYMBOL_STR(sym) "- .		\n"	\
+	    "	.long "	VMLINUX_SYMBOL_STR(__kstrtab_##sym) "- .\n"	\
+	    "	.previous					\n")
 
 #if defined(__KSYM_DEPS__)
 
diff --git a/kernel/module.c b/kernel/module.c
index 40f983cbea81..f09529f695f9 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -88,6 +88,12 @@ 
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
+struct kernel_symbol
+{
+	signed int value_offset;
+	signed int name_offset;
+};
+
 /*
  * Mutex protects:
  * 1) List of modules (also safely readable with preempt_disable),
@@ -539,12 +545,23 @@  static bool check_symbol(const struct symsearch *syms,
 	return true;
 }
 
+static unsigned long kernel_symbol_value(const struct kernel_symbol *sym)
+{
+	return (unsigned long)&sym->value_offset + sym->value_offset;
+}
+
+static const char *kernel_symbol_name(const struct kernel_symbol *sym)
+{
+	return (const char *)((unsigned long)&sym->name_offset +
+			      sym->name_offset);
+}
+
 static int cmp_name(const void *va, const void *vb)
 {
 	const char *a;
 	const struct kernel_symbol *b;
 	a = va; b = vb;
-	return strcmp(a, b->name);
+	return strcmp(a, kernel_symbol_name(b));
 }
 
 static bool find_symbol_in_section(const struct symsearch *syms,
@@ -2190,7 +2207,7 @@  void *__symbol_get(const char *symbol)
 		sym = NULL;
 	preempt_enable();
 
-	return sym ? (void *)sym->value : NULL;
+	return sym ? (void *)kernel_symbol_value(sym) : NULL;
 }
 EXPORT_SYMBOL_GPL(__symbol_get);
 
@@ -2220,10 +2237,12 @@  static int verify_export_symbols(struct module *mod)
 
 	for (i = 0; i < ARRAY_SIZE(arr); i++) {
 		for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
-			if (find_symbol(s->name, &owner, NULL, true, false)) {
+			if (find_symbol(kernel_symbol_name(s), &owner, NULL,
+					true, false)) {
 				pr_err("%s: exports duplicate symbol %s"
 				       " (owned by %s)\n",
-				       mod->name, s->name, module_name(owner));
+				       mod->name, kernel_symbol_name(s),
+				       module_name(owner));
 				return -ENOEXEC;
 			}
 		}
@@ -2272,7 +2291,7 @@  static int simplify_symbols(struct module *mod, const struct load_info *info)
 			ksym = resolve_symbol_wait(mod, info, name);
 			/* Ok if resolved.  */
 			if (ksym && !IS_ERR(ksym)) {
-				sym[i].st_value = ksym->value;
+				sym[i].st_value = kernel_symbol_value(ksym);
 				break;
 			}
 
@@ -2532,7 +2551,7 @@  static int is_exported(const char *name, unsigned long value,
 		ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
 	else
 		ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
-	return ks != NULL && ks->value == value;
+	return ks != NULL && kernel_symbol_value(ks) == value;
 }
 
 /* As per nm */