The linker avoids a GOT indirection by turning a MOV into
a LEA, but with x86-64 GCC has started emitting CMOV*
instructions which break the existing logic.
This will generate errors such as:
unexpected GOT reloc for non-dynamic symbol luaO_nilobject_
The CMOV* instructions may be emitted with normal code like:
if (o >= L->top) return cast(TValue *, luaO_nilobject);
else return o;
Which gets compiled into (relocation offset at 1b):
13: 48 3b 47 10 cmp 0x10(%rdi),%rax
17: 48 0f 43 05 00 00 00 cmovae 0x0(%rip),%rax
1e: 00
This change will allow the indirection through the GOT to
avoid the problem in those cases.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/
4071044
case 256 + R_X86_64_GOTPCREL:
if(targ->dynimpname == nil || targ->dynexport) {
// have symbol
- // turn MOVQ of GOT entry into LEAQ of symbol itself
- if(r->off < 2 || s->p[r->off-2] != 0x8b) {
- diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ->name);
+ if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
+ // turn MOVQ of GOT entry into LEAQ of symbol itself
+ s->p[r->off-2] = 0x8d;
+ r->type = D_PCREL;
+ r->add += 4;
return;
}
- s->p[r->off-2] = 0x8d;
- r->type = D_PCREL;
- r->add += 4;
- return;
+ // unknown instruction (CMOV* maybe), use GOT
+ targ->dynimpname = targ->name;
}
addgotsym(targ);
r->type = D_PCREL;