From f846ce259af07ab522badaaee32f83b296830302 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 12 Jun 2017 18:05:01 +0000 Subject: [PATCH] Fix weak symbols on arm and aarch64. Given .weak target .global _start _start: b target The intention is that the branch goes to the instruction after the branch, effectively turning it on a nop. The branch adds the runtime PC, but we were adding it statically too. I noticed the oddity by inspection, but llvm-objdump seems to agree, since it now prints things like: b #-4 <_start+0x4> llvm-svn: 305212 --- lld/ELF/InputSection.cpp | 38 +++++++++++++-------- lld/test/ELF/aarch64-undefined-weak.s | 10 +++--- lld/test/ELF/arm-thumb-no-undefined-thunk.s | 6 ++-- lld/test/ELF/arm-thumb-undefined-weak.s | 8 ++--- lld/test/ELF/arm-undefined-weak.s | 6 ++-- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index e82f8c3016fa..9aae82bc2992 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -403,7 +403,7 @@ static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, uint32_t P) { switch (Type) { case R_ARM_THM_JUMP11: - return P + 2; + return P + 2 + A; case R_ARM_CALL: case R_ARM_JUMP24: case R_ARM_PC24: @@ -411,12 +411,12 @@ static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, case R_ARM_PREL31: case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: - return P + 4; + return P + 4 + A; case R_ARM_THM_CALL: // We don't want an interworking BLX to ARM - return P + 5; + return P + 5 + A; default: - return A; + return P + A; } } @@ -427,9 +427,9 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: - return P + 4; + return P + 4 + A; default: - return A; + return P + A; } } @@ -515,20 +515,30 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + InX::MipsGot->getTlsIndexOff() - InX::MipsGot->getGp(); case R_PAGE_PC: - case R_PLT_PAGE_PC: + case R_PLT_PAGE_PC: { + uint64_t Dest; if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) - return getAArch64Page(A); - return getAArch64Page(Body.getVA(A)) - getAArch64Page(P); - case R_PC: + Dest = getAArch64Page(A); + else + Dest = getAArch64Page(Body.getVA(A)); + return Dest - getAArch64Page(P); + } + case R_PC: { + uint64_t Dest; if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) { // On ARM and AArch64 a branch to an undefined weak resolves to the // next instruction, otherwise the place. if (Config->EMachine == EM_ARM) - return getARMUndefinedRelativeWeakVA(Type, A, P); - if (Config->EMachine == EM_AARCH64) - return getAArch64UndefinedRelativeWeakVA(Type, A, P); + Dest = getARMUndefinedRelativeWeakVA(Type, A, P); + else if (Config->EMachine == EM_AARCH64) + Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P); + else + Dest = Body.getVA(A); + } else { + Dest = Body.getVA(A); } - return Body.getVA(A) - P; + return Dest - P; + } case R_PLT: return Body.getPltVA() + A; case R_PLT_PC: diff --git a/lld/test/ELF/aarch64-undefined-weak.s b/lld/test/ELF/aarch64-undefined-weak.s index e611b6da6607..1c21213643ac 100644 --- a/lld/test/ELF/aarch64-undefined-weak.s +++ b/lld/test/ELF/aarch64-undefined-weak.s @@ -33,12 +33,12 @@ _start: // CHECK: Disassembly of section .text: // 131076 = 0x20004 -// CHECK: 20000: {{.*}} b #131076 -// CHECK-NEXT: 20004: {{.*}} bl #131080 -// CHECK-NEXT: 20008: {{.*}} b.eq #131084 -// CHECK-NEXT: 2000c: {{.*}} cbz x1, #131088 +// CHECK: 20000: {{.*}} b #4 +// CHECK-NEXT: 20004: {{.*}} bl #4 +// CHECK-NEXT: 20008: {{.*}} b.eq #4 +// CHECK-NEXT: 2000c: {{.*}} cbz x1, #4 // CHECK-NEXT: 20010: {{.*}} adr x0, #0 -// CHECK-NEXT: 20014: {{.*}} adrp x0, #0 +// CHECK-NEXT: 20014: {{.*}} adrp x0, #-131072 // CHECK: 20018: {{.*}} .word 0x00000000 // CHECK-NEXT: 2001c: {{.*}} .word 0x00000000 // CHECK-NEXT: 20020: {{.*}} .word 0x00000000 diff --git a/lld/test/ELF/arm-thumb-no-undefined-thunk.s b/lld/test/ELF/arm-thumb-no-undefined-thunk.s index af2d3eb52044..775e6fa9c0e0 100644 --- a/lld/test/ELF/arm-thumb-no-undefined-thunk.s +++ b/lld/test/ELF/arm-thumb-no-undefined-thunk.s @@ -19,6 +19,6 @@ _start: // CHECK: Disassembly of section .text: // CHECK-NEXT: _start: // 69636 = 0x11004 = next instruction -// CHECK: 11000: {{.*}} bl #69636 -// CHECK-NEXT: 11004: {{.*}} b.w #69640 -// CHECK-NEXT: 11008: {{.*}} b.w #69644 +// CHECK: 11000: {{.*}} bl #0 +// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8> +// CHECK-NEXT: 11008: {{.*}} b.w #0 <_start+0xC> diff --git a/lld/test/ELF/arm-thumb-undefined-weak.s b/lld/test/ELF/arm-thumb-undefined-weak.s index 792b81e3603a..7f481b0ddb89 100644 --- a/lld/test/ELF/arm-thumb-undefined-weak.s +++ b/lld/test/ELF/arm-thumb-undefined-weak.s @@ -29,10 +29,10 @@ _start: // CHECK: Disassembly of section .text: // 69636 = 0x11004 -// CHECK: 11000: {{.*}} beq.w #69636 -// CHECK-NEXT: 11004: {{.*}} b.w #69640 -// CHECK-NEXT: 11008: {{.*}} bl #69644 +// CHECK: 11000: {{.*}} beq.w #0 <_start+0x4> +// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8> +// CHECK-NEXT: 11008: {{.*}} bl #0 // blx is transformed into bl so we don't change state -// CHECK-NEXT: 1100c: {{.*}} bl #69648 +// CHECK-NEXT: 1100c: {{.*}} bl #0 // CHECK-NEXT: 11010: {{.*}} movt r0, #0 // CHECK-NEXT: 11014: {{.*}} movw r0, #0 diff --git a/lld/test/ELF/arm-undefined-weak.s b/lld/test/ELF/arm-undefined-weak.s index 5d77b1b4e698..57a3f57dea1b 100644 --- a/lld/test/ELF/arm-undefined-weak.s +++ b/lld/test/ELF/arm-undefined-weak.s @@ -29,10 +29,10 @@ _start: // CHECK: Disassembly of section .text: // 69636 = 0x11004 -// CHECK: 11000: {{.*}} b #69636 -// CHECK-NEXT: 11004: {{.*}} bl #69640 +// CHECK: 11000: {{.*}} b #-4 <_start+0x4> +// CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8> // blx is transformed into bl so we don't change state -// CHECK-NEXT: 11008: {{.*}} bl #69644 +// CHECK-NEXT: 11008: {{.*}} bl #-4 <_start+0xC> // CHECK-NEXT: 1100c: {{.*}} movt r0, #0 // CHECK-NEXT: 11010: {{.*}} movw r0, #0 // CHECK: 11014: {{.*}} .word 0x00000000