diff --git a/tcc.h b/tcc.h index 8bca9ae8..4e88782c 100644 --- a/tcc.h +++ b/tcc.h @@ -105,6 +105,14 @@ #define TCC_TARGET_I386 #endif +#if defined (TCC_TARGET_ARM) && !defined(TCC_ARM_VERSION) + #ifdef TCC_ARM_HARDFLOAT + #define TCC_ARM_VERSION 7 + #else + #define TCC_ARM_VERSION 4 + #endif +#endif + #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) #define CONFIG_TCC_BCHECK /* enable bound checking code */ diff --git a/tccelf.c b/tccelf.c index 79437632..f46a7423 100644 --- a/tccelf.c +++ b/tccelf.c @@ -601,27 +601,30 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) case R_ARM_JUMP24: case R_ARM_PLT32: { - int x, is_thumb, is_call, h; + int x, is_thumb, is_call, h, blx_avail; x = (*(int *)ptr)&0xffffff; (*(int *)ptr) &= 0xff000000; if (x & 0x800000) x -= 0x1000000; x <<= 2; + blx_avail = (TCC_ARM_VERSION >= 5); is_thumb = val & 1; is_call = (type == R_ARM_CALL); - x += (val & -2) - addr; + x += val - addr; h = x & 2; #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 */ + if ((x & 3) || x >= 0x4000000 || x < -0x4000000) + if (!(x & 3) || !blx_avail || !is_call) + 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) - if (!(h && is_call && is_thumb)) + if ((x & 3) || x >= 0x4000000 || x < -0x4000000) + if (!(x & 3) || !blx_avail || !is_call) tcc_error("can't relocate value at %x",addr); x >>= 2; x &= 0xffffff; - if (is_call && is_thumb) { + /* Only reached if blx is avail and it is a call */ + if (is_thumb) { x |= h << 24; (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ }