[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