Amd64 relocation R_X86_64_32S in a static lib
tg at gmplib.org
Tue Nov 5 18:03:45 CET 2013
nisse at lysator.liu.se (Niels Möller) writes:
I don't understand the fine details of which reloc types make sense in
pic code, but if I understand Philip correctly, the main problem is not
a ABI change, but changed compiler default. And then you get link errors
when linking together pic objects created by the compiler, with non-pic
objects created from the gmp assembly files.
Let's look at a (non-GMP) example:
typedef int (*jumpent_t)(int);
int foo (int i)
On OpenBSD pre-5.3 using the system compiler, one gets
movl $17, %edi
for the call through jumptab.
On OpenBSD 5.3 again with the system compiler, one gets
movl $17, %edi
movq jumptab at GOTPCREL(%rip), %rdx
for the same code. I didn't pass any PIC options in either case. (On
any *BSD or GNU/Linux system, passing -fpic presumably causes the latter
code to be generated.)
The former is implicitly an R_X86_64_32S reloc and the latter is quite
explicitly an R_X86_64_GOTPCREL.
If one tries to assemble and link the former code on a 5.3/5.4 system,
one gets again the error "relocation R_X86_64_32S can not be used when
making a shared object; recompile with -fPIC".
I'd call this an ABI change since code valid under the AMD64 ELF ABI as
well as on older OpenBSD releases is no longer supported.
Using another S + A type reloc works, as demonstrated by code like
movl $17, %edi
movabsq $jumptab, %rcx
and this makes no sense since this is not position independent without
ugly load-time patching.
I think you'd get similar problems as if a user configures gmp with,
e.g., --disable-shared CFLAGS=-fpic. Do you agree with this analysis?
I'd expect that to work on all present systems, actually. Since -fpic
does not reserve any register, mixing in some PIC code will not hurt
(except perhaps performance).
To figure out if an invocation $(CC) $(CFLAGS) generates pic code or
not, one needs a configure test like
Using the result of that test when deciding whether or not assembly
files should use pic mode should give the correct behavior, both with
compilers doing pic by default, and users enabling it explicitly.
That might work, but I wouldn't bet on that such a test would be as
resilient as one could hope for. It is certainly not hard to make a gcc
configuration which generates PIC code always without setting __PIC__,
intensionally or unintensionally.
A more resilient test might use a few non-PIC relocs such as S + A and
(There are pros and cons with feature tests, though. I consider the
free software OSes out there to be primary targets for GMP, and I'd like
to avoid creating GMP objects that cannot be moved between FooBSD x.y
and FooBSD x.y+k. Knowing the ABIs and complying to them, using a
greatest common denominator of working code, might be better. Then
compiled GMP and linked GMP application will move between OS releases.)
For reference, the AMD64 ABI document is here:
The relocs are summarised on page 71 with explanation of the various
symbols like A (addend) and S (symbol) on page 70.
More information about the gmp-devel