Add thumb stubs switching from thumb mode to arm mode to *all* PLT entries so that R_ARM_THM_JUMP24 relocations to PLT entries can be satisfied.
Unified · Split
| @@ -638,7 +638,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 637 unmodified lines | |||
| 638 | case R_ARM_THM_JUMP24: | 638 | case R_ARM_THM_JUMP24: |
| 639 | { | 639 | { |
| 640 | int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11; | 640 | int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11; |
| 641 | int to_thumb, is_call, blx_bit = 1 << 12; | 641 | int to_thumb, is_call, to_plt, blx_bit = 1 << 12; |
| 642 | Section *plt; | ||
| 642 | 643 | ||
| 643 | /* weak reference */ | 644 | /* weak reference */ |
| 644 | if (sym->st_shndx == SHN_UNDEF && | 645 | if (sym->st_shndx == SHN_UNDEF && |
| @@ -662,9 +663,14 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 17 unmodified lines | |||
| 662 | 663 | ||
| 663 | /* Relocation infos */ | 664 | /* Relocation infos */ |
| 664 | to_thumb = val & 1; | 665 | to_thumb = val & 1; |
| 666 | plt = s1->plt; | ||
| 667 | to_plt = (val >= plt->sh_addr) && | ||
| 668 | (val < plt->sh_addr + plt->data_offset); | ||
| 665 | is_call = (type == R_ARM_THM_CALL); | 669 | is_call = (type == R_ARM_THM_CALL); |
| 666 | 670 | ||
| 667 | /* Compute final offset */ | 671 | /* Compute final offset */ |
| 672 | if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */ | ||
| 673 | x -= 4; | ||
| 668 | x += val - addr; | 674 | x += val - addr; |
| 669 | if (!to_thumb && is_call) { | 675 | if (!to_thumb && is_call) { |
| 670 | blx_bit = 0; /* bl -> blx */ | 676 | blx_bit = 0; /* bl -> blx */ |
| @@ -675,9 +681,9 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 4 unmodified lines | |||
| 675 | * offset must not be out of range | 681 | * offset must not be out of range |
| 676 | * if target is to be entered in arm mode: | 682 | * if target is to be entered in arm mode: |
| 677 | - bit 1 must not set | 683 | - bit 1 must not set |
| 678 | - instruction must be a call (bl) */ | 684 | - instruction must be a call (bl) or a jump to PLT */ |
| 679 | if (!to_thumb || x >= 0x1000000 || x < -0x1000000) | 685 | if (!to_thumb || x >= 0x1000000 || x < -0x1000000) |
| 680 | if (to_thumb || (val & 2) || !is_call) | 686 | if (to_thumb || (val & 2) || (!is_call && !to_plt)) |
| 681 | tcc_error("can't relocate value at %x",addr); | 687 | tcc_error("can't relocate value at %x",addr); |
| 682 | 688 | ||
| 683 | /* Compute and store final offset */ | 689 | /* Compute and store final offset */ |
| @@ -1096,10 +1102,13 @@ static void put_got_entry(TCCState *s1, · 412 unmodified lines | |||
| 1096 | put32(p + 12, 0xe5bef008); | 1102 | put32(p + 12, 0xe5bef008); |
| 1097 | } | 1103 | } |
| 1098 | 1104 | ||
| 1099 | p = section_ptr_add(plt, 16); | 1105 | p = section_ptr_add(plt, 20); |
| 1100 | put32(p , 0xe59fc004); | 1106 | put32(p , 0x4778); // bx pc |
| 1101 | put32(p+4, 0xe08fc00c); | 1107 | put32(p+2, 0x46c0); // nop |
| 1102 | put32(p+8, 0xe59cf000); | 1108 | p += 4; |
| 1109 | put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT | ||
| 1110 | put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset | ||
| 1111 | put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset | ||
| 1103 | put32(p+12, s1->got->data_offset); | 1112 | put32(p+12, s1->got->data_offset); |
| 1104 | 1113 | ||
| 1105 | /* the symbol is modified so that it will be relocated to | 1114 | /* the symbol is modified so that it will be relocated to |
| @@ -2057,8 +2066,9 @@ static int elf_output_file(TCCState *s1, const char *filename) · 951 unmodified lines | |||
| 2057 | #elif defined(TCC_TARGET_ARM) | 2066 | #elif defined(TCC_TARGET_ARM) |
| 2058 | int x; | 2067 | int x; |
| 2059 | x=s1->got->sh_addr - s1->plt->sh_addr - 12; | 2068 | x=s1->got->sh_addr - s1->plt->sh_addr - 12; |
| 2060 | p +=16; | 2069 | p += 16; |
| 2061 | while (p < p_end) { | 2070 | while (p < p_end) { |
| 2071 | p += 4; | ||
| 2062 | put32(p + 12, x + get32(p + 12) + s1->plt->data - p); | 2072 | put32(p + 12, x + get32(p + 12) + s1->plt->data - p); |
| 2063 | p += 16; | 2073 | p += 16; |
| 2064 | } | 2074 | } |