This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Allow relative relocations to a absolute value defined in linker script.
AbandonedPublic

Authored by grimar on Jan 18 2017, 5:43 AM.

Details

Reviewers
ruiu
rafael
Summary

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

Run:

gcc -shared main.c -S -o main_gcc.s
llvm-mc -filetype=obj -triple=x86_64-pc-linux main_gcc.s -o main.o
ld -shared main.o --script script.lds -o out.lld

bfd accepts this inputs fine, LLD fails with "cannot refer to absolute symbol..." error.
Patch allows to have such relocations.

Diff Detail