diff --git a/elf.h b/elf.h index 8ecadd1..d6b1c6a 100644 --- a/elf.h +++ b/elf.h @@ -1673,6 +1673,7 @@ typedef Elf32_Addr Elf32_Conflict; #define R_ARM_PLT32 27 /* 32 bit PLT address */ #define R_ARM_CALL 28 #define R_ARM_JUMP24 29 +#define R_ARM_V4BX 40 #define R_ARM_PREL31 42 #define R_ARM_GNU_VTENTRY 100 #define R_ARM_GNU_VTINHERIT 101 diff --git a/tccelf.c b/tccelf.c index 037615a..526c513 100644 --- a/tccelf.c +++ b/tccelf.c @@ -660,6 +660,11 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) break; case R_ARM_COPY: break; + case R_ARM_V4BX: + /* trade Thumb support for ARMv4 support */ + if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10) + *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */ + break; default: fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n", type,addr,(unsigned int)(long)ptr,val); @@ -2474,7 +2479,11 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, goto invalid_reloc; sym_index = old_to_new_syms[sym_index]; /* ignore link_once in rel section. */ - if (!sym_index && !sm->link_once) { + if (!sym_index && !sm->link_once +#ifdef TCC_TARGET_ARM + && type != R_ARM_V4BX +#endif + ) { invalid_reloc: error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x", i, strsec + sh->sh_name, rel->r_offset);