From patchwork Tue Sep 20 20:06:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lyon X-Patchwork-Id: 76631 Delivered-To: patch@linaro.org Received: by 10.140.106.72 with SMTP id d66csp1665046qgf; Tue, 20 Sep 2016 13:07:25 -0700 (PDT) X-Received: by 10.98.147.195 with SMTP id r64mr24462249pfk.32.1474402045304; Tue, 20 Sep 2016 13:07:25 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id ce5si36467425pad.132.2016.09.20.13.07.25 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Sep 2016 13:07:25 -0700 (PDT) Received-SPF: pass (google.com: domain of binutils-return-93879-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of binutils-return-93879-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=binutils-return-93879-patch=linaro.org@sourceware.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:from:date:message-id:subject:to :content-type; q=dns; s=default; b=AQ9q26vZiz2bFU6jWkVvQor5tGzEL hJmgJJJiHth56lIFM+VTZwQaOcmFqkivCBV90C1t0XR73I3OO0ysGFPh0dYu5ECa XBYixTgh0c+TVsrqPF5sqpxX2Ucx6YRvgo7VbJijnTnY7/kT4mPLe8n6Az+8KvUe CuzIn95jsvW7wo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:from:date:message-id:subject:to :content-type; s=default; bh=xjz0AaOddn6WLswWQQQYS2RfLok=; b=YmD 30zllAe4mqfZwKpfhXCGJgDVVwCMSHuMGmP1DAtA2ltMN1gh/a/TCn1tag8YvNxE U2vf3dmeS7A30454NftOWKurlJ/wrjIwByyx8Z52j98dNBDdOPH1E9Z9cTw03rBn wMPaMhJxH9JaYay76mbTJUh0TNZEwHsI3fZio6PY= Received: (qmail 18816 invoked by alias); 20 Sep 2016 20:07:08 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Delivered-To: mailing list binutils@sourceware.org Received: (qmail 18799 invoked by uid 89); 20 Sep 2016 20:07:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=9000, UD:r, bw, f400 X-HELO: mail-qk0-f176.google.com Received: from mail-qk0-f176.google.com (HELO mail-qk0-f176.google.com) (209.85.220.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 Sep 2016 20:06:57 +0000 Received: by mail-qk0-f176.google.com with SMTP id w204so26308862qka.0 for ; Tue, 20 Sep 2016 13:06:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=HJb73KLkXYt+vHb/FumHSw6hhkrLLsvAp2h1zF8Vndw=; b=HDgmsaSM+MHznzc2LUXbkDtEGCxDH4v76z3tX2CY++AgGrs+pKahKgBIsa4eNp4BK5 EccAJpMTmJbNCXUFG6TD6LJJfYMNGrx0bqwydKEoDvr6uHwUDHdK22Nc1XwUKR7SC3Va BJCT2rFJBmIOvV9MhqOQRpU5B59BlpRKhFosIPC61emsOxVVHtFCG7B8qfbenf0353Up 4QKj0cYoOalAZvjwknl6P70TqSD8XCk/uRNjlqX4Sr3dUzSTB2i8zdsu/zfSZJTrPflv Ey+S8bge9vE2oTRn6Gc+KjdNipIlFD5j3v9E4EFpON3HUpfbzrPXW1jb1fm/NHvgh8wG hE0Q== X-Gm-Message-State: AE9vXwOaThfRLM8yiWHA1oo5V/QwNJWbaweAH1PiwiP2OEiMw2QQ1FcMWQitM0UNN8de/Ys4IPFzWPpDIQtRJqXf X-Received: by 10.55.36.131 with SMTP id k3mr36535191qkk.86.1474402015263; Tue, 20 Sep 2016 13:06:55 -0700 (PDT) MIME-Version: 1.0 Received: by 10.140.21.80 with HTTP; Tue, 20 Sep 2016 13:06:54 -0700 (PDT) From: Christophe Lyon Date: Tue, 20 Sep 2016 22:06:54 +0200 Message-ID: Subject: [ARM] PR ld/20608 To: binutils@sourceware.org X-IsSubscribed: yes Hi, In PR 20608, we have a case where a Thumb2 branch to PLT using b.w targets the pre-PLT Thumb-ARM stub that is too far away. Indeed, the linker is able to insert a pre-PLT Thumb->ARM stub to handle Thumb mode calls through a PLT, but the check if a farcall stub is needed doesn't take this into account correctly. Depending on the branch-target distance, there is a 4 bytes windows that is not handled properly: the closer range is handled by a direct branch to the pre-PLT stub, while the further range is handle by a farcall stub directly targeting the PLT. Between the 2 ranges, there are 2 possible distances where a b.w instruction would result in a "relocation truncated" error. The attached patch fixes that by taking into account the actual final distance when checking if a farcall stub is needed. I hope I updated my comments in a clear way :-) Regarding the testcase, I have added farcall-mixed-app2, which is a copy of farcall-mixed-app with a new mid-range section right at the offending frontier. I added a new testcase instead of updating this existing one because adding b.w instructions enabled the linker to replace bl by blx when needed, implying necessary modifications to the expected results, and in effect removing tests for old architectures. So now, we have farcall-mixed-app, farcall-mixed-app-v5 (the same one, linked with --use-blx to allow the linker to replace bl with blx) and farcall-mixed-app2 which uses b.w. It seems this problem has been causing numerous random failures in LLVM buildbots. OK? Thanks, Christophe 2016-09-20 Christophe Lyon 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. diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 6e68be1..8c0d716 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -3945,17 +3945,44 @@ 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 +4018,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. */ diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 24d0b4c..02a35f4 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -559,6 +559,12 @@ set armeabitests_nonacl { {readelf -Ds farcall-mixed-app.sym}} "farcall-mixed-app-v5"} + {"Mixed ARM/Thumb2 dynamic application with farcalls" "tmpdir/mixed-lib.so -T arm-dyn.ld --section-start .mid_thumb=0x10081c0 --section-start .far_arm=0x2100000 --section-start .far_thumb=0x2200000" "" "" + {farcall-mixed-app2.s} + {{objdump -fdw farcall-mixed-app2.d} {objdump -Rw farcall-mixed-app2.r} + {readelf -Ds farcall-mixed-app2.sym}} + "farcall-mixed-app2"} + {"Mixed ARM/Thumb shared library with long branches (v4t)" "-shared -T arm-lib.ld" "" "-march=armv4t" {farcall-mixed-lib1.s farcall-mixed-lib2.s} {{objdump -fdw farcall-mixed-lib-v4t.d}} diff --git a/ld/testsuite/ld-arm/farcall-mixed-app2.d b/ld/testsuite/ld-arm/farcall-mixed-app2.d new file mode 100644 index 0000000..54338d0 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app2.d @@ -0,0 +1,99 @@ + +tmpdir/farcall-mixed-app2: file format elf32-(little|big)arm +architecture: arm.*, flags 0x00000112: +EXEC_P, HAS_SYMS, D_PAGED +start address 0x.* + +Disassembly of section .plt: + +.* : + .*: e52de004 push {lr} ; \(str lr, \[sp, #-4\]!\) + .*: e59fe004 ldr lr, \[pc, #4\] ; .* + .*: e08fe00e add lr, pc, lr + .*: e5bef008 ldr pc, \[lr, #8\]! + .*: .* +.* : + .*: 4778 bx pc + .*: 46c0 nop ; \(mov r8, r8\) + .*: e28fc6.* add ip, pc, #.* + .*: e28cca.* add ip, ip, #.* ; 0x.* + .*: e5bcf.* ldr pc, \[ip, #.*\]!.* +.* : + .*: e28fc6.* add ip, pc, #.* + .*: e28cca.* add ip, ip, #.* ; 0x.* + .*: e5bcf.* ldr pc, \[ip, #.*\]!.* + +Disassembly of section .text: + +.* <_start>: + .*: e1a0c00d mov ip, sp + .*: e92dd800 push {fp, ip, lr, pc} + .*: eb000008 bl .* <__app_func_veneer> + .*: ebfffff6 bl .* + .*: ebfffff2 bl .* + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop ; \(mov r0, r0\) + +.* : + .*: b500 push {lr} + .*: f7ff efde blx 81e0 + .*: bd00 pop {pc} + .*: 4770 bx lr + .*: 46c0 nop ; \(mov r8, r8\) +#... + +.* <__app_func_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; 8234 <__app_func_veneer\+0x4> + .*: 02100000 .word 0x02100000 + +Disassembly of section .mid_thumb: + +.* : +#... + .*: f400 9000 b.w .* + .*: f000 b800 b.w .* <__lib_func2_from_thumb> + +.* <__lib_func2_from_thumb>: + .*: 4778 bx pc + .*: 46c0 nop ; \(mov r8, r8\) + .*: e51ff004 ldr pc, \[pc, #-4\] ; 10081e8 <__lib_func2_from_thumb\+0x8> + .*: 000081e0 .word 0x000081e0 + .*: 00000000 .word 0x00000000 + +Disassembly of section .far_arm: + +.* : + .*: e1a0c00d mov ip, sp + .*: e92dd800 push {fp, ip, lr, pc} + .*: eb000006 bl .* <__lib_func1_veneer> + .*: eb000007 bl .* <__lib_func2_veneer> + .*: e89d6800 ldm sp, {fp, sp, lr} + .*: e12fff1e bx lr + .*: e1a00000 nop ; \(mov r0, r0\) + .*: e1a00000 nop ; \(mov r0, r0\) + +.* : + .*: e12fff1e bx lr +#... + +.* <__lib_func1_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func1_veneer\+0x4> + .*: 000081ec .word 0x000081ec +.* <__lib_func2_veneer>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func2_veneer\+0x4> + .*: 000081e0 .word 0x000081e0 + +Disassembly of section .far_thumb: + +.* : + .*: b500 push {lr} + .*: f000 e806 blx .* <__lib_func2_from_thumb> + .*: bd00 pop {pc} + .*: 4770 bx lr + .*: 46c0 nop ; \(mov r8, r8\) +#... + +.* <__lib_func2_from_thumb>: + .*: e51ff004 ldr pc, \[pc, #-4\] ; 2200014 <__lib_func2_from_thumb\+0x4> + .*: 000081e0 .word 0x000081e0 diff --git a/ld/testsuite/ld-arm/farcall-mixed-app2.r b/ld/testsuite/ld-arm/farcall-mixed-app2.r new file mode 100644 index 0000000..910a361 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app2.r @@ -0,0 +1,10 @@ + +tmpdir/farcall-mixed-app.*: file format elf32-(little|big)arm + +DYNAMIC RELOCATION RECORDS +OFFSET TYPE VALUE +.* R_ARM_COPY data_obj +.* R_ARM_JUMP_SLOT lib_func2 +.* R_ARM_JUMP_SLOT lib_func1 + + diff --git a/ld/testsuite/ld-arm/farcall-mixed-app2.s b/ld/testsuite/ld-arm/farcall-mixed-app2.s new file mode 100644 index 0000000..ee315e9 --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app2.s @@ -0,0 +1,76 @@ + .text + .p2align 4 + .globl _start +_start: + mov ip, sp + stmdb sp!, {r11, ip, lr, pc} + bl app_func + bl lib_func1 + bl lib_func2 + ldmia sp, {r11, sp, lr} + bx lr + + .p2align 4 + .globl app_tfunc_close + .type app_tfunc_close,%function + .thumb_func + .code 16 +app_tfunc_close: + push {lr} + bl lib_func2 + pop {pc} + bx lr + +@ We will place the section .mid_thumb at 0xFFFEF8. +@ Just far enough for XXXX + .section .mid_thumb, "xa" + + .p2align 4 + .globl mid_tfunc + .type mid_tfunc,%function + .thumb_func + .code 16 +mid_tfunc: + .syntax unified + .space 24 + b.w lib_func2 + b.w lib_func2 + +@ We will place the section .far_arm at 0x2100000. + .section .far_arm, "xa" + + .arm + .p2align 4 + .globl app_func + .type app_func,%function +app_func: + mov ip, sp + stmdb sp!, {r11, ip, lr, pc} + bl lib_func1 + bl lib_func2 + ldmia sp, {r11, sp, lr} + bx lr + + .arm + .p2align 4 + .globl app_func2 + .type app_func2,%function +app_func2: + bx lr + +@ We will place the section .far_thumb at 0x2200000. + .section .far_thumb, "xa" + + .p2align 4 + .globl app_tfunc + .type app_tfunc,%function + .thumb_func + .code 16 +app_tfunc: + push {lr} + bl lib_func2 + pop {pc} + bx lr + + .data + .long data_obj diff --git a/ld/testsuite/ld-arm/farcall-mixed-app2.sym b/ld/testsuite/ld-arm/farcall-mixed-app2.sym new file mode 100644 index 0000000..1d3bd1d --- /dev/null +++ b/ld/testsuite/ld-arm/farcall-mixed-app2.sym @@ -0,0 +1,15 @@ + +Symbol table for image: + +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end + +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__ + +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__ + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start + +.. +..: .......0 +0 +FUNC +GLOBAL +DEFAULT +15 app_func2 + +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2 + +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__