Message ID | 1458291877-26313-1-git-send-email-ard.biesheuvel@linaro.org |
---|---|
State | Accepted |
Commit | 142b9e6c9de0fd7c0dff9a1d4a25390de46abf5e |
Headers | show |
(+ 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 --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 */
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