Skip to content

Commit a82a126

Browse files
committed
[ARM,ELF] Fix access to dso_preemptable __stack_chk_guard with static relocation model
The ELF code from https://reviews.llvm.org/D112811 emits LDRLIT_ga_pcrel when `TM.isPositionIndependent()` but uses a different condition `Subtarget.isGVIndirectSymbol(GV)` (aka dso_preemptable on ELF targets). This would cause incorrect access for dso_preemptable `__stack_chk_guard` with the static relocation model. Regarding whether `__stack_chk_guard` gets the dso_local specifier, https://reviews.llvm.org/D150841 switched to `M.getDirectAccessExternalData()` (implied by "PIC Level") instead of `TM.getRelocationModel() == Reloc::Static`. The result is that when non-zero "PIC Level" is used with static relocation model (e.g. -fPIE/-fPIC LTO compiles with -no-pie linking), `__stack_chk_guard` accesses are incorrect. ``` ldr r0, .LCPI0_0 ldr r0, [r0] ldr r0, [r0] // incorrectly dereferences __stack_chk_guard ... .LCPI0_0: .long __stack_chk_guard ``` To fix this, for dso_preemptable `__stack_chk_guard`, emit a GOT PIC code sequence like for -fpic using `LDRLIT_ga_pcrel`: ``` ldr r0, .LCPI0_0 .LPC0_0: add r0, pc, r0 ldr r0, [r0] ldr r0, [r0] ... LCPI0_0: .Ltmp0: .long __stack_chk_guard(GOT_PREL)-((.LPC0_0+8)-.Ltmp0) ``` Technically, `LDRLIT_ga_abs` with `R_ARM_GOT_ABS` could be used, but `R_ARM_GOT_ABS` does not have GNU or integrated assembler support. (Note, `.LCPI0_0: .long __stack_chk_guard@GOT` produces an `R_ARM_GOT_BREL`, which is not desired). This patch fixes #6499 while not changing behavior for the following configurations: ``` run arm.linux.nopic --target=arm-linux-gnueabi -fno-pic run arm.linux.pie --target=arm-linux-gnueabi -fpie run arm.linux.pic --target=arm-linux-gnueabi -fpic run armv6.darwin.nopic --target=armv6-apple-darwin -fno-pic run armv6.darwin.dynamicnopic --target=armv6-apple-darwin -mdynamic-no-pic run armv6.darwin.pic --target=armv6-apple-darwin -fpic run armv7.darwin.nopic --target=armv7-apple-darwin -mcpu=cortex-a8 -fno-pic run armv7.darwin.dynamicnopic --target=armv7-apple-darwin -mcpu=cortex-a8 -mdynamic-no-pic run armv7.darwin.pic --target=armv7-apple-darwin -mcpu=cortex-a8 -fpic run arm64.darwin.pic --target=arm64-apple-darwin ```
1 parent 6ae7b73 commit a82a126

File tree

3 files changed

+24
-7
lines changed

3 files changed

+24
-7
lines changed

llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4978,7 +4978,7 @@ void ARMBaseInstrInfo::expandLoadStackGuardBase(MachineBasicBlock::iterator MI,
49784978
TargetFlags |= ARMII::MO_DLLIMPORT;
49794979
else if (IsIndirect)
49804980
TargetFlags |= ARMII::MO_COFFSTUB;
4981-
} else if (Subtarget.isGVInGOT(GV)) {
4981+
} else if (IsIndirect) {
49824982
TargetFlags |= ARMII::MO_GOT;
49834983
}
49844984

llvm/lib/Target/ARM/ARMInstrInfo.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,11 @@ void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const {
104104
const GlobalValue *GV =
105105
cast<GlobalValue>((*MI->memoperands_begin())->getValue());
106106

107-
if (!Subtarget.useMovt() || Subtarget.isGVInGOT(GV)) {
108-
if (TM.isPositionIndependent())
107+
bool ForceELFGOTPIC = Subtarget.isTargetELF() && !GV->isDSOLocal();
108+
if (!Subtarget.useMovt() || ForceELFGOTPIC) {
109+
// For ELF non-PIC, use GOT PIC code sequence as well because R_ARM_GOT_ABS
110+
// does not have assembler support.
111+
if (TM.isPositionIndependent() || ForceELFGOTPIC)
109112
expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12);
110113
else
111114
expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12);

llvm/test/CodeGen/ARM/stack-guard-elf.ll

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
2+
;; direct-access-external-data is false due to PIC Level, so __stack_chk_guard
3+
;; is dso_preemtable. Check that we use GOT PIC code sequence as well because
4+
;; R_ARM_GOT_ABS does not have assembler support.
25
; RUN: llc -relocation-model=static < %s | FileCheck %s
6+
; RUN: llc -relocation-model=pic < %s | FileCheck %s
37

48
target triple = "armv7a-linux-gnueabi"
59

@@ -9,16 +13,18 @@ define i32 @test1() #0 {
913
; CHECK-NEXT: push {r11, lr}
1014
; CHECK-NEXT: sub sp, sp, #8
1115
; CHECK-NEXT: sub sp, sp, #1024
12-
; CHECK-NEXT: movw r0, :lower16:__stack_chk_guard
13-
; CHECK-NEXT: movt r0, :upper16:__stack_chk_guard
16+
; CHECK-NEXT: ldr r0, .LCPI0_0
17+
; CHECK-NEXT: .LPC0_0:
18+
; CHECK-NEXT: add r0, pc, r0
1419
; CHECK-NEXT: ldr r0, [r0]
1520
; CHECK-NEXT: ldr r0, [r0]
1621
; CHECK-NEXT: str r0, [sp, #1028]
1722
; CHECK-NEXT: add r0, sp, #4
1823
; CHECK-NEXT: bl foo
19-
; CHECK-NEXT: movw r1, :lower16:__stack_chk_guard
2024
; CHECK-NEXT: ldr r0, [sp, #1028]
21-
; CHECK-NEXT: movt r1, :upper16:__stack_chk_guard
25+
; CHECK-NEXT: ldr r1, .LCPI0_1
26+
; CHECK-NEXT: .LPC0_1:
27+
; CHECK-NEXT: add r1, pc, r1
2228
; CHECK-NEXT: ldr r1, [r1]
2329
; CHECK-NEXT: ldr r1, [r1]
2430
; CHECK-NEXT: cmp r1, r0
@@ -28,6 +34,14 @@ define i32 @test1() #0 {
2834
; CHECK-NEXT: popeq {r11, pc}
2935
; CHECK-NEXT: .LBB0_1:
3036
; CHECK-NEXT: bl __stack_chk_fail
37+
; CHECK-NEXT: .p2align 2
38+
; CHECK-NEXT: @ %bb.2:
39+
; CHECK-NEXT: .LCPI0_0:
40+
; CHECK-NEXT: .Ltmp0:
41+
; CHECK-NEXT: .long __stack_chk_guard(GOT_PREL)-((.LPC0_0+8)-.Ltmp0)
42+
; CHECK-NEXT: .LCPI0_1:
43+
; CHECK-NEXT: .Ltmp1:
44+
; CHECK-NEXT: .long __stack_chk_guard(GOT_PREL)-((.LPC0_1+8)-.Ltmp1)
3145
%a1 = alloca [256 x i32], align 4
3246
call void @foo(ptr %a1) #3
3347
ret i32 0

0 commit comments

Comments
 (0)