x86/kallsyms: fix GOLD link failure with new relative kallsyms table format
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 18 Mar 2016 09:04:37 +0000 (10:04 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 20 Mar 2016 20:52:37 +0000 (13:52 -0700)
Commit 2213e9a66bb8 ("kallsyms: add support for relative offsets in
kallsyms address table") changed the default kallsyms symbol table
format to use relative references rather than absolute addresses.

This reduces the size of the kallsyms symbol table by 50% on 64-bit
architectures, and further reduces the size of the relocation tables
used by relocatable kernels.  Since the memory footprint of the static
kernel image is always much smaller than 4 GB, these relative references
are assumed to be representable in 32 bits, even when the native word
size is 64 bits.

On 64-bit architectures, this obviously only works if the distance
between each relative reference and the chosen anchor point is
representable in 32 bits, and so the table generation code in
scripts/kallsyms.c scans the table for the lowest value that is covered
by the kernel text, and selects it as the anchor point.

However, when using the GOLD linker rather than the default BFD linker
to build the x86_64 kernel, the symbol phys_offset_64, which is the
result of arithmetic defined in the linker script, is emitted as a 'T'
rather than an 'A' type symbol, resulting in scripts/kallsyms.c to
mistake it for a suitable anchor point, even though it is far away from
the actual kernel image in the virtual address space.  This results in
out-of-range warnings from scripts/kallsyms.c and a broken build.

So let's align with the BFD linker, and emit the phys_offset_[32|64]
symbols as absolute symbols explicitly.  Note that the out of range
issue does not exist on 32-bit x86, but this patch changes both symbols
for symmetry.

Reported-by: Markus Trippelsdorf <markus@trippelsdorf.de>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86/kernel/vmlinux.lds.S

index 5af9958cbdb6be4293b62181ffe104f435caf830..6bb070e54fda48d5841c2ebaeae8053165cc5ed4 100644 (file)
@@ -81,11 +81,11 @@ PHDRS {
 SECTIONS
 {
 #ifdef CONFIG_X86_32
-        . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
-        phys_startup_32 = startup_32 - LOAD_OFFSET;
+       . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
+       phys_startup_32 = ABSOLUTE(startup_32 - LOAD_OFFSET);
 #else
-        . = __START_KERNEL;
-        phys_startup_64 = startup_64 - LOAD_OFFSET;
+       . = __START_KERNEL;
+       phys_startup_64 = ABSOLUTE(startup_64 - LOAD_OFFSET);
 #endif
 
        /* Text and read-only data */