Introduce ARM version for the target architecture in order to determine if blx instruction can be used or not. Availability of blx instruction allows for more scenarii supported in R_ARM_CALL relocation. It should also be useful when introducing support for the R_ARM_THM_CALL relocation.
Unified · Split
| @@ -105,6 +105,14 @@ · 104 unmodified lines | ||
| 105 | 105 | #define TCC_TARGET_I386 |
| 106 | 106 | #endif |
| 107 | 107 | |
| 108 | +#if defined (TCC_TARGET_ARM) && !defined(TCC_ARM_VERSION) | |
| 109 | + #ifdef TCC_ARM_HARDFLOAT | |
| 110 | + #define TCC_ARM_VERSION 7 | |
| 111 | + #else | |
| 112 | + #define TCC_ARM_VERSION 4 | |
| 113 | + #endif | |
| 114 | +#endif | |
| 115 | + | |
| 108 | 116 | #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ |
| 109 | 117 | !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) |
| 110 | 118 | #define CONFIG_TCC_BCHECK /* enable bound checking code */ |
| @@ -601,27 +601,30 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 600 unmodified lines | ||
| 601 | 601 | case R_ARM_JUMP24: |
| 602 | 602 | case R_ARM_PLT32: |
| 603 | 603 | { |
| 604 | − int x, is_thumb, is_call, h; | |
| 604 | + int x, is_thumb, is_call, h, blx_avail; | |
| 605 | 605 | x = (*(int *)ptr)&0xffffff; |
| 606 | 606 | (*(int *)ptr) &= 0xff000000; |
| 607 | 607 | if (x & 0x800000) |
| 608 | 608 | x -= 0x1000000; |
| 609 | 609 | x <<= 2; |
| 610 | + blx_avail = (TCC_ARM_VERSION >= 5); | |
| 610 | 611 | is_thumb = val & 1; |
| 611 | 612 | is_call = (type == R_ARM_CALL); |
| 612 | − x += (val & -2) - addr; | |
| 613 | + x += val - addr; | |
| 613 | 614 | h = x & 2; |
| 614 | 615 | #ifndef TCC_TARGET_PE |
| 615 | − if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) | |
| 616 | − if (s1->output_type == TCC_OUTPUT_MEMORY) | |
| 617 | − x += add_jmp_table(s1, val) - val; /* add veneer */ | |
| 616 | + if ((x & 3) || x >= 0x4000000 || x < -0x4000000) | |
| 617 | + if (!(x & 3) || !blx_avail || !is_call) | |
| 618 | + if (s1->output_type == TCC_OUTPUT_MEMORY) | |
| 619 | + x += add_jmp_table(s1, val) - val; /* add veneer */ | |
| 618 | 620 | #endif |
| 619 | − if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) | |
| 620 | − if (!(h && is_call && is_thumb)) | |
| 621 | + if ((x & 3) || x >= 0x4000000 || x < -0x4000000) | |
| 622 | + if (!(x & 3) || !blx_avail || !is_call) | |
| 621 | 623 | tcc_error("can't relocate value at %x",addr); |
| 622 | 624 | x >>= 2; |
| 623 | 625 | x &= 0xffffff; |
| 624 | − if (is_call && is_thumb) { | |
| 626 | + /* Only reached if blx is avail and it is a call */ | |
| 627 | + if (is_thumb) { | |
| 625 | 628 | x |= h << 24; |
| 626 | 629 | (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ |
| 627 | 630 | } |