diff options
| author | Edmund Grimley Evans <Edmund.Grimley.Evans@gmail.com> | 2015-02-21 21:29:03 +0000 |
|---|---|---|
| committer | Edmund Grimley Evans <Edmund.Grimley.Evans@gmail.com> | 2015-02-21 21:29:03 +0000 |
| commit | 738606dbd5608cb2ed6789beecea40712809c397 (patch) | |
| tree | 5905c3fa381607f962f2cc75d68c280ab5d03eba /tccgen.c | |
| parent | 86c850fc58a70ff4b77c37d91e33ce6c812b04c4 (diff) | |
| download | tinycc-738606dbd5608cb2ed6789beecea40712809c397.tar.gz tinycc-738606dbd5608cb2ed6789beecea40712809c397.tar.bz2 | |
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.
Diffstat (limited to 'tccgen.c')
| -rw-r--r-- | tccgen.c | 32 |
1 files changed, 24 insertions, 8 deletions
@@ -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); |
