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.
Showing the changes to tccelf.c (1 of 2 files). Show all
Unified · Split
| @@ -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 | } |