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 | case R_ARM_JUMP24: | 601 | case R_ARM_JUMP24: |
| 602 | case R_ARM_PLT32: | 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 | x = (*(int *)ptr)&0xffffff; | 605 | x = (*(int *)ptr)&0xffffff; |
| 606 | (*(int *)ptr) &= 0xff000000; | 606 | (*(int *)ptr) &= 0xff000000; |
| 607 | if (x & 0x800000) | 607 | if (x & 0x800000) |
| 608 | x -= 0x1000000; | 608 | x -= 0x1000000; |
| 609 | x <<= 2; | 609 | x <<= 2; |
| 610 | blx_avail = (TCC_ARM_VERSION >= 5); | ||
| 610 | is_thumb = val & 1; | 611 | is_thumb = val & 1; |
| 611 | is_call = (type == R_ARM_CALL); | 612 | is_call = (type == R_ARM_CALL); |
| 612 | x += (val & -2) - addr; | 613 | x += val - addr; |
| 613 | h = x & 2; | 614 | h = x & 2; |
| 614 | #ifndef TCC_TARGET_PE | 615 | #ifndef TCC_TARGET_PE |
| 615 | if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) | 616 | if ((x & 3) || x >= 0x4000000 || x < -0x4000000) |
| 616 | if (s1->output_type == TCC_OUTPUT_MEMORY) | 617 | if (!(x & 3) || !blx_avail || !is_call) |
| 617 | x += add_jmp_table(s1, val) - val; /* add veneer */ | 618 | if (s1->output_type == TCC_OUTPUT_MEMORY) |
| 619 | x += add_jmp_table(s1, val) - val; /* add veneer */ | ||
| 618 | #endif | 620 | #endif |
| 619 | if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) | 621 | if ((x & 3) || x >= 0x4000000 || x < -0x4000000) |
| 620 | if (!(h && is_call && is_thumb)) | 622 | if (!(x & 3) || !blx_avail || !is_call) |
| 621 | tcc_error("can't relocate value at %x",addr); | 623 | tcc_error("can't relocate value at %x",addr); |
| 622 | x >>= 2; | 624 | x >>= 2; |
| 623 | x &= 0xffffff; | 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 | x |= h << 24; | 628 | x |= h << 24; |
| 626 | (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ | 629 | (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ |
| 627 | } | 630 | } |