aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tcc.h2
-rw-r--r--tccelf.c16
-rw-r--r--tccrun.c4
3 files changed, 19 insertions, 3 deletions
diff --git a/tcc.h b/tcc.h
index 313214c..29953a6 100644
--- a/tcc.h
+++ b/tcc.h
@@ -547,7 +547,7 @@ struct TCCState {
#endif
#ifndef TCC_TARGET_PE
-#ifdef TCC_TARGET_X86_64
+#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
/* write PLT and GOT here */
char *runtime_plt_and_got;
unsigned int runtime_plt_and_got_offset;
diff --git a/tccelf.c b/tccelf.c
index 4ea8dc8..037615a 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -504,6 +504,17 @@ static uplong add_got_table(TCCState *s1, uplong val)
*p = val;
return (uplong)p;
}
+#elif defined TCC_TARGET_ARM
+#define JMP_TABLE_ENTRY_SIZE 8
+static int add_jmp_table(TCCState *s1, int val)
+{
+ uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
+ s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
+ /* ldr pc, [pc, #-4] */
+ p[0] = 0xE51FF004;
+ p[1] = val;
+ return (int)p;
+}
#endif
#endif
@@ -611,6 +622,11 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
x -= 0x1000000;
x *= 4;
x += val - addr;
+#ifndef TCC_TARGET_PE
+ if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
+ if (s1->output_type == TCC_OUTPUT_MEMORY)
+ x += add_jmp_table(s1, val) - val; /* add veneer */
+#endif
if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
error("can't relocate value at %x",addr);
x >>= 2;
diff --git a/tccrun.c b/tccrun.c
index f04412c..264b8a7 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -150,7 +150,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
if (s1->nb_errors)
return -1;
-#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
+#if (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM) && !defined TCC_TARGET_PE
s1->runtime_plt_and_got_offset = 0;
s1->runtime_plt_and_got = (char *)(mem + offset);
/* double the size of the buffer for got and plt entries
@@ -184,7 +184,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
set_pages_executable(ptr, length);
}
-#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
+#if (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM) && !defined TCC_TARGET_PE
set_pages_executable(s1->runtime_plt_and_got,
s1->runtime_plt_and_got_offset);
#endif