aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorEdmund Grimley Evans <Edmund.Grimley.Evans@gmail.com>2015-02-21 21:29:03 +0000
committerEdmund Grimley Evans <Edmund.Grimley.Evans@gmail.com>2015-02-21 21:29:03 +0000
commit738606dbd5608cb2ed6789beecea40712809c397 (patch)
tree5905c3fa381607f962f2cc75d68c280ab5d03eba /tccgen.c
parent86c850fc58a70ff4b77c37d91e33ce6c812b04c4 (diff)
downloadtinycc-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.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/tccgen.c b/tccgen.c
index 510051a..ae07563 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -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);