From c6630ef92a21ca33af08b1faa03fba578e12315f Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Wed, 10 Oct 2012 00:09:42 +0200 Subject: [PATCH] Fix R_ARM_CALL when target fonction is Thumb With R_ARM_CALL, if target function is to be entered in Thumb mode, the relocation is supposed to transform bl in blx. This is not the case actually so this commit is there to fix it. --- tccelf.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tccelf.c b/tccelf.c index 5e1a64e7..79437632 100644 --- a/tccelf.c +++ b/tccelf.c @@ -601,22 +601,30 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) case R_ARM_JUMP24: case R_ARM_PLT32: { - int x; + int x, is_thumb, is_call, h; x = (*(int *)ptr)&0xffffff; (*(int *)ptr) &= 0xff000000; if (x & 0x800000) x -= 0x1000000; - x *= 4; - x += val - addr; + x <<= 2; + is_thumb = val & 1; + is_call = (type == R_ARM_CALL); + x += (val & -2) - 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 */ #endif if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) - tcc_error("can't relocate value at %x",addr); + if (!(h && is_call && is_thumb)) + tcc_error("can't relocate value at %x",addr); x >>= 2; x &= 0xffffff; + if (is_call && is_thumb) { + x |= h << 24; + (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ + } (*(int *)ptr) |= x; } break;