aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tccelf.c')
-rw-r--r--tccelf.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/tccelf.c b/tccelf.c
index 73f84cc..a3c9aee 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -532,6 +532,8 @@ static void relocate_section(TCCState *s1, Section *s)
break;
#elif defined(TCC_TARGET_ARM)
case R_ARM_PC24:
+ case R_ARM_CALL:
+ case R_ARM_JUMP24:
case R_ARM_PLT32:
{
int x;
@@ -548,13 +550,27 @@ static void relocate_section(TCCState *s1, Section *s)
(*(int *)ptr) |= x;
}
break;
+ case R_ARM_PREL31:
+ {
+ int x;
+ x = (*(int *)ptr) & 0x7fffffff;
+ (*(int *)ptr) &= 0x80000000;
+ x = (x * 2) / 2;
+ x += val - addr;
+ if((x^(x>>1))&0x40000000)
+ error("can't relocate value at %x",addr);
+ (*(int *)ptr) |= x & 0x7fffffff;
+ }
case R_ARM_ABS32:
*(int *)ptr += val;
break;
- case R_ARM_GOTPC:
+ case R_ARM_BASE_PREL:
*(int *)ptr += s1->got->sh_addr - addr;
break;
- case R_ARM_GOT32:
+ case R_ARM_GOTOFF32:
+ *(int *)ptr += val - s1->got->sh_addr;
+ break;
+ case R_ARM_GOT_BREL:
/* we load the got offset */
*(int *)ptr += s1->got_offsets[sym_index];
break;
@@ -856,17 +872,17 @@ static void build_got_entries(TCCState *s1)
}
break;
#elif defined(TCC_TARGET_ARM)
- case R_ARM_GOT32:
- case R_ARM_GOTOFF:
- case R_ARM_GOTPC:
+ case R_ARM_GOT_BREL:
+ case R_ARM_GOTOFF32:
+ case R_ARM_BASE_PREL:
case R_ARM_PLT32:
if (!s1->got)
build_got(s1);
- if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
+ if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
sym_index = ELF32_R_SYM(rel->r_info);
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
/* look at the symbol got offset. If none, then add one */
- if (type == R_ARM_GOT32)
+ if (type == R_ARM_GOT_BREL)
reloc_type = R_ARM_GLOB_DAT;
else
reloc_type = R_ARM_JUMP_SLOT;
@@ -1081,8 +1097,12 @@ static void tcc_add_linker_symbols(TCCState *s1)
#ifdef __FreeBSD__
static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
#else
+#ifdef TCC_ARM_EABI
+static char elf_interp[] = "/lib/ld-linux.so.3";
+#else
static char elf_interp[] = "/lib/ld-linux.so.2";
#endif
+#endif
static void tcc_output_binary(TCCState *s1, FILE *f,
const int *section_order)
@@ -1661,8 +1681,13 @@ int tcc_output_file(TCCState *s1, const char *filename)
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
#endif
#ifdef TCC_TARGET_ARM
+#ifdef TCC_ARM_EABI
+ ehdr.e_ident[EI_OSABI] = 0;
+ ehdr.e_flags = 4 << 24;
+#else
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
#endif
+#endif
switch(file_type) {
default:
case TCC_OUTPUT_EXE:
@@ -1833,6 +1858,9 @@ static int tcc_load_object_file(TCCState *s1,
/* ignore sections types we do not handle */
if (sh->sh_type != SHT_PROGBITS &&
sh->sh_type != SHT_REL &&
+#ifdef TCC_ARM_EABI
+ sh->sh_type != SHT_ARM_EXIDX &&
+#endif
sh->sh_type != SHT_NOBITS)
continue;
if (sh->sh_addralign < 1)