Allow thumb transition for R_ARM_PC24

Allow bl -> blx conversion in the case of R_ARM_PC24 relocation with
instruction being an unconditional bl. Also make spacing more uniform.
This commit is contained in:
Thomas Preud'homme 2013-11-18 00:03:38 +08:00
parent 0c40bc8982
commit 1b606d1884

View file

@ -603,28 +603,29 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
case R_ARM_JUMP24: case R_ARM_JUMP24:
case R_ARM_PLT32: case R_ARM_PLT32:
{ {
int x, is_thumb, is_call, h, blx_avail; int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
x = (*(int *)ptr)&0xffffff; x = (*(int *) ptr) & 0xffffff;
(*(int *)ptr) &= 0xff000000; (*(int *)ptr) &= 0xff000000;
if (x & 0x800000) if (x & 0x800000)
x -= 0x1000000; x -= 0x1000000;
x <<= 2; x <<= 2;
blx_avail = (TCC_ARM_VERSION >= 5); blx_avail = (TCC_ARM_VERSION >= 5);
is_thumb = val & 1; is_thumb = val & 1;
is_call = (type == R_ARM_CALL); is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
x += val - addr; x += val - addr;
h = x & 2; h = x & 2;
th_ko = (x & 3) && (!blx_avail || !is_call);
#ifdef TCC_HAS_RUNTIME_PLTGOT #ifdef TCC_HAS_RUNTIME_PLTGOT
if (s1->output_type == TCC_OUTPUT_MEMORY) { if (s1->output_type == TCC_OUTPUT_MEMORY) {
if ((x & 3) || x >= 0x2000000 || x < -0x2000000) if (th_ko || x >= 0x2000000 || x < -0x2000000) {
if (!(x & 3) || !blx_avail || !is_call) {
x += add_jmp_table(s1, val) - val; /* add veneer */ x += add_jmp_table(s1, val) - val; /* add veneer */
th_ko = (x & 3) && (!blx_avail || !is_call);
is_thumb = 0; /* Veneer uses ARM instructions */ is_thumb = 0; /* Veneer uses ARM instructions */
} }
} }
#endif #endif
if ((x & 3) || x >= 0x2000000 || x < -0x2000000) if (th_ko || x >= 0x2000000 || x < -0x2000000)
if (!(x & 3) || !blx_avail || !is_call)
tcc_error("can't relocate value at %x",addr); tcc_error("can't relocate value at %x",addr);
x >>= 2; x >>= 2;
x &= 0xffffff; x &= 0xffffff;
@ -633,7 +634,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
x |= h << 24; x |= h << 24;
(*(int *)ptr) = 0xfa << 24; /* bl -> blx */ (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
} }
(*(int *)ptr) |= x; (*(int *) ptr) |= x;
} }
break; break;
/* Since these relocations only concern Thumb-2 and blx instruction was /* Since these relocations only concern Thumb-2 and blx instruction was