Re: [PATCH] x86/kallsyms: fix GOLD link failure with new relative kallsyms table format

From: Ard Biesheuvel
Date: Fri Mar 18 2016 - 05:31:40 EST


(+ Markus)

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

BTW,

Reported-by: Markus Trippelsdorf <markus@xxxxxxxxxxxxxxx>

> ---
> 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
>