[PATCH] D28857: [ELF] - Allow relative relocations to a absolute value defined in linker script.
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 18 06:18:43 PST 2017
George Rimar via Phabricator <reviews at reviews.llvm.org> writes:
> grimar created this revision.
>
> I faced next error during linking linux kernel:
> arch/x86/entry/vdso/vclock_gettime.c:148: relocation R_X86_64_PC32 cannot refer to absolute symbol 'vvar_vsyscall_gtod_data' defined in (internal)
>
> Symbol is defined in script:
>
> /*
> * User/kernel shared data is before the vDSO. This may be a little
> * uglier than putting it after the vDSO, but it avoids issues with
> * non-allocatable things that dangle past the end of the PT_LOAD
> * segment.
> */
> vvar_start = . - 2 * (1 << 12);
> vvar_page = vvar_start;
> /*
> <skipped>
> * These variables live in a page of kernel data that has an extra RO
> * mapping for userspace. Each variable needs a unique offset within
> * that page; specify that offset with the DECLARE_VVAR macro. (If
> * you mess up, the linker will catch it.)
> */
> /* The kernel linker script defines its own magic to put vvars in the
> * right place.
> */
> /* DECLARE_VVAR(offset, type, name) */
> vvar_vsyscall_gtod_data = vvar_page + 128;
>
> I was able to extract minimal reproducable using the original parts of code
> for demonstation of their use case.
>
> main.c:
>
> // https://github.com/torvalds/linux/blob/d33d5a6c88fcd53fec329a1521010f1bc55fa191/arch/x86/include/asm/vgtod.h
> // https://github.com/torvalds/linux/blob/5924bbecd0267d87c24110cbe2041b5075173a25/arch/x86/include/asm/vvar.h
> // https://github.com/torvalds/linux/blob/d33d5a6c88fcd53fec329a1521010f1bc55fa191/arch/x86/entry/vdso/vclock_gettime.c
>
> struct vsyscall_gtod_data {
> unsigned seq;
> };
>
> #define DECLARE_VVAR(offset, type, name) \
> extern type vvar_ ## name __attribute__((visibility("hidden")));
> DECLARE_VVAR(128, struct vsyscall_gtod_data, vsyscall_gtod_data)
>
> #define VVAR(name) (vvar_ ## name)
>
> #define gtod (&VVAR(vsyscall_gtod_data))
>
> void foo() {
> unsigned seq = gtod->seq;
> }
>
> script.lds:
>
> SECTIONS { vvar_vsyscall_gtod_data = 0x10000; }
This is an over reduction. The real problem is that we are not tracking
absoluteness correctly. In the original case vvar_vsyscall_gtod_data
should not be absolute
> --- ELF/Relocations.cpp
> +++ ELF/Relocations.cpp
> @@ -356,6 +356,10 @@
> return true;
> if (&Body == ElfSym<ELFT>::MipsGpDisp)
> return true;
> + // Sometimes code has relocations to absolute symbol defined in linker script.
> + // Example is linux kernel. Hence we allow it.
> + if (!Body.File)
> + return true;
We should not do this. It would accept broken cases too.
Cheers,
Rafael
More information about the llvm-commits
mailing list