diff options
| author | Thomas Preud'homme <robotux@celest.fr> | 2012-10-10 00:09:42 +0200 |
|---|---|---|
| committer | Thomas Preud'homme <robotux@celest.fr> | 2012-10-10 00:21:26 +0200 |
| commit | c6630ef92a21ca33af08b1faa03fba578e12315f (patch) | |
| tree | 27bae6f9a927f0297904ee995d018c56e7467e67 /tccelf.c | |
| parent | 2fe7fd9e875979d0947c17609b64799219485d2d (diff) | |
| download | tinycc-c6630ef92a21ca33af08b1faa03fba578e12315f.tar.gz tinycc-c6630ef92a21ca33af08b1faa03fba578e12315f.tar.bz2 | |
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.
Diffstat (limited to 'tccelf.c')
| -rw-r--r-- | tccelf.c | 16 |
1 files changed, 12 insertions, 4 deletions
@@ -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; |
