Use RELA relocations properly for R_DATA_PTR on x86_64.

libtcc.c: Add greloca, a generalisation of greloc that takes an addend.
tcc.h: Add greloca and put_elf_reloca.
tccelf.c: Add put_elf_reloca, a generalisation of put_elf_reloc.
tccgen.c: On x86_64, use greloca instead of greloc in init_putv.
This commit is contained in:
Edmund Grimley Evans
2015-02-21 21:29:03 +00:00
parent 86c850fc58
commit 738606dbd5
4 changed files with 46 additions and 13 deletions

View File

@ -5201,19 +5201,35 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
case VT_LLONG:
*(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
break;
case VT_PTR:
if (vtop->r & VT_SYM) {
case VT_PTR: {
addr_t val = (vtop->c.ptr_offset & bit_mask) << bit_pos;
#ifdef TCC_TARGET_X86_64
if (vtop->r & VT_SYM)
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
else
*(addr_t *)ptr |= val;
#else
if (vtop->r & VT_SYM)
greloc(sec, vtop->sym, c, R_DATA_PTR);
}
*(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos;
*(addr_t *)ptr |= val;
#endif
break;
default:
if (vtop->r & VT_SYM) {
}
default: {
int val = (vtop->c.i & bit_mask) << bit_pos;
#ifdef TCC_TARGET_X86_64
if (vtop->r & VT_SYM)
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
else
*(int *)ptr |= val;
#else
if (vtop->r & VT_SYM)
greloc(sec, vtop->sym, c, R_DATA_PTR);
}
*(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
*(int *)ptr |= val;
#endif
break;
}
}
vtop--;
} else {
vset(&dtype, VT_LOCAL|VT_LVAL, c);