aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tccelf.c')
-rw-r--r--tccelf.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/tccelf.c b/tccelf.c
index 093f18d..56ee75a 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -502,6 +502,25 @@ static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
*(unsigned long *)(p + 6) = val;
return (unsigned long)p;
}
+
+#define GOT_TABLE_ENTRY_MAX_NUM 4096
+static unsigned long add_got_table(TCCState *s1, unsigned long val)
+{
+ unsigned long *p;
+ if (!s1->got_table) {
+ int size = sizeof(void *) * GOT_TABLE_ENTRY_MAX_NUM;
+ s1->got_table_num = 0;
+ s1->got_table = (char *)tcc_malloc(size);
+ }
+ if (s1->got_table_num == GOT_TABLE_ENTRY_MAX_NUM) {
+ error("relocating >%d symbols are not supported",
+ GOT_TABLE_ENTRY_MAX_NUM);
+ }
+ p = s1->got_table + s1->got_table_num;
+ s1->got_table_num++;
+ *p = val;
+ return (unsigned long)p;
+}
#endif
/* relocate a given section (CPU dependent) */
@@ -727,11 +746,13 @@ static void relocate_section(TCCState *s1, Section *s)
*(int *)ptr = val;
break;
case R_X86_64_GOTPCREL:
- *(int *)ptr += s1->got->sh_addr - addr;
- /* XXX: is this OK? */
- if (s1->output_type == TCC_OUTPUT_DLL) {
- *(int *)ptr += s1->got_offsets[sym_index] - 4;
+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
+ val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
+ *(int *)ptr += val - addr;
+ break;
}
+ *(int *)ptr += (s1->got->sh_addr - addr +
+ s1->got_offsets[sym_index] - 4);
break;
case R_X86_64_GOTTPOFF:
*(int *)ptr += val - s1->got->sh_addr;