diff mbox

x86/kallsyms: fix GOLD link failure with new relative kallsyms table format

Message ID 1458291877-26313-1-git-send-email-ard.biesheuvel@linaro.org
State Accepted
Commit 142b9e6c9de0fd7c0dff9a1d4a25390de46abf5e
Headers show

Commit Message

Ard Biesheuvel March 18, 2016, 9:04 a.m. UTC
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.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
 arch/x86/kernel/vmlinux.lds.S | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

-- 
2.5.0

Comments

Ard Biesheuvel March 18, 2016, 9:31 a.m. UTC | #1
(+ Markus)

On 18 March 2016 at 10:04, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 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.

>

> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>


BTW,

Reported-by: Markus Trippelsdorf <markus@trippelsdorf.de>

> ---

>  arch/x86/kernel/vmlinux.lds.S | 8 ++++----

>  1 file changed, 4 insertions(+), 4 deletions(-)

>

> diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S

> index 5af9958cbdb6..6bb070e54fda 100644

> --- a/arch/x86/kernel/vmlinux.lds.S

> +++ b/arch/x86/kernel/vmlinux.lds.S

> @@ -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 */

> --

> 2.5.0

>
diff mbox

Patch

diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 5af9958cbdb6..6bb070e54fda 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -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 */