diff options
author | Christophe Lyon <christophe.lyon@linaro.org> | 2016-09-28 01:37:52 +0200 |
---|---|---|
committer | Christophe Lyon <christophe.lyon@linaro.org> | 2016-09-28 01:41:00 +0200 |
commit | 2df2751d1927e1231bbe7d548139da98d6ca9b9a (patch) | |
tree | 1e45c7016513152008d40e25f574862ac390e5bf /bfd/elf32-arm.c | |
parent | e3f07b5b750554bbbbee1bddc34bb77fd7d31eeb (diff) | |
download | gdb-2df2751d1927e1231bbe7d548139da98d6ca9b9a.zip gdb-2df2751d1927e1231bbe7d548139da98d6ca9b9a.tar.gz gdb-2df2751d1927e1231bbe7d548139da98d6ca9b9a.tar.bz2 |
[ARM] PR ld/20608 Relocation truncated to fit: R_ARM_THM_JUMP24 for relocation to PLT entry
2016-09-28 Christophe Lyon <christophe.lyon@linaro.org>
PR ld/20608
bfd/
* elf32-arm.c (arm_type_of_stub): Handle the case when the pre-PLT
Thumb-ARM stub is too far.
ld
* testsuite/ld-arm/arm-elf.exp: Handle new testcase.
* testsuite/ld-arm/farcall-mixed-app2.d: New file.
* testsuite/ld-arm/farcall-mixed-app2.r: Likewise.
* testsuite/ld-arm/farcall-mixed-app2.s: Likewise.
* testsuite/ld-arm/farcall-mixed-app2.sym: Likewise.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r-- | bfd/elf32-arm.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index c58b65d..2386a8c 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -3945,17 +3945,43 @@ arm_type_of_stub (struct bfd_link_info *info, /* Note when dealing with PLT entries: the main PLT stub is in ARM mode, so if the branch is in Thumb mode, another Thumb->ARM stub will be inserted later just before the ARM - PLT stub. We don't take this extra distance into account - here, because if a long branch stub is needed, we'll add a - Thumb->Arm one and branch directly to the ARM PLT entry - because it avoids spreading offset corrections in several - places. */ + PLT stub. If a long branch stub is needed, we'll add a + Thumb->Arm one and branch directly to the ARM PLT entry. + Here, we have to check if a pre-PLT Thumb->ARM stub + is needed and if it will be close enough. */ destination = (splt->output_section->vma + splt->output_offset + root_plt->offset); st_type = STT_FUNC; - branch_type = ST_BRANCH_TO_ARM; + + /* Thumb branch/call to PLT: it can become a branch to ARM + or to Thumb. We must perform the same checks and + corrections as in elf32_arm_final_link_relocate. */ + if ((r_type == R_ARM_THM_CALL) + || (r_type == R_ARM_THM_JUMP24)) + { + if (globals->use_blx + && r_type == R_ARM_THM_CALL + && !thumb_only) + { + /* If the Thumb BLX instruction is available, convert + the BL to a BLX instruction to call the ARM-mode + PLT entry. */ + branch_type = ST_BRANCH_TO_ARM; + } + else + { + if (!thumb_only) + /* Target the Thumb stub before the ARM PLT entry. */ + destination -= PLT_THUMB_STUB_SIZE; + branch_type = ST_BRANCH_TO_THUMB; + } + } + else + { + branch_type = ST_BRANCH_TO_ARM; + } } } /* Calls to STT_GNU_IFUNC symbols should go through a PLT. */ @@ -3991,6 +4017,15 @@ arm_type_of_stub (struct bfd_link_info *info, || (r_type == R_ARM_THM_JUMP19)) && !use_plt)) { + /* If we need to insert a Thumb-Thumb long branch stub to a + PLT, use one that branches directly to the ARM PLT + stub. If we pretended we'd use the pre-PLT Thumb->ARM + stub, undo this now. */ + if ((branch_type == ST_BRANCH_TO_THUMB) && use_plt && !thumb_only) { + branch_type = ST_BRANCH_TO_ARM; + branch_offset += PLT_THUMB_STUB_SIZE; + } + if (branch_type == ST_BRANCH_TO_THUMB) { /* Thumb to thumb. */ |