Both relocations have the same effect and the calculations are the same, but R_386_GOT32X
relocations allow the linker to optimize the instructions used for the calculation, using immediate operands instead of memory operands under certain conditions.
H. J. Lu (Intel engineer who introduced R_386_GOT32X
) explains it in the IA32 System V ABI mailing list:
X86 instruction encoding supports converting some instructions on
memory operand with GOT32 relocation against symbol, foo, into a
different form on immediate operand if foo is defined locally. Those
instructions are:
call *foo@GOT[(%reg)] => nop call foo or call foo nop
jmp *foo@GOT[(%reg)] => jmp foo nop
mov foo@GOT[(%reg1)], %reg2 => lea foo[@GOTOFF(%reg1)], %reg2
When osition-independent code is disable,
test %reg1, foo@GOT[(%reg2)] => test $foo, %reg1 binop
foo@GOT[(%reg1)], %reg2 => binop $foo, %reg2
where binop is one of adc, add, and, cmp, or, sbb, sub, xor
instructions.
I am proposing to add a new relocation, R_386_GOT32X, to i386 psABI.
Instead of generating R_386_GOT32 relocation agasint foo for
foo@GOT(%reg), we generate R_386_GOT32X. R_386_GOT32X relocation can
also be used without the base register for the global offset table,
foo@GOT, when position-independent code is disable. In this case, the
static base address of the global offset table will be used instead.
Linker can treat R_386_GOT32X the same as R_386_GOT32 or it can
perform the transformations listed above.
Indeed, according to the IA32 System V ABI document you linked (section A.2):
Optimize R_386_GOT32X Relocation
The Intel386 instruction encoding supports converting certain
instructions on memory operand with R_386_GOT32X
relocation against
symbol, foo
, into a different form on immediate operand if foo
is
defined locally:
Convert call, jmp and mov Convert memory operand
of call
, jmp
and mov
into immediate operand.
Memory Operand |
Immediate Operand |
call *foo@GOT(%reg) |
nop call foo |
call *foo@GOT(%reg) |
call foo nop |
jmp *foo@GOT(%reg) |
jmp foo nop |
mov foo@GOT(%reg1), %reg2 |
lea foo@GOTOFF(%reg1), %reg2 |
Convert Test and Binop Convert memory operand of call
, jmp
, mov
, test
and binop
into immediate operand, where binop
is one of adc
, add
,
and
, cmp
, or
, sbb
, sub
, xor
instructions, when position-independent
code is disabled.
Memory Operand |
Immediate Operand |
call *foo@GOT |
nop call foo |
call *foo@GOT |
call foo nop |
jmp *foo@GOT |
jmp foo nop |
mov foo@GOT, %reg |
mov $foo, %reg |
test %reg, foo@GOT |
test $foo, %reg |
binop foo@GOT, %reg |
binop $foo, %reg |
call *foo@GOT(%reg) |
nop call foo |
call *foo@GOT(%reg) |
call foo nop |
jmp *foo@GOT(%reg) |
jmp foo nop |
mov foo@GOT(%reg1), %reg2 |
mov $foo, %reg2 |
test %reg1, name@GOT(%reg2) |
test $foo, %reg1 |
binop name@GOT(%reg1), %reg2 |
binop $foo, %reg2 |