Skip to content

Commit eb7cc2f

Browse files
[PAC][AArch64] Lower ptrauth constants in data
Lower global references to ptrauth constants into `@AUTH` `MCExpr`'s. The logic is common for MachO and ELF - test both. Co-authored-by: Ahmed Bougacha <[email protected]>
1 parent f779ec7 commit eb7cc2f

File tree

4 files changed

+233
-0
lines changed

4 files changed

+233
-0
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class BasicBlock;
3838
class BlockAddress;
3939
class Constant;
4040
class ConstantArray;
41+
class ConstantPtrAuth;
4142
class DataLayout;
4243
class DIE;
4344
class DIEAbbrev;
@@ -585,6 +586,11 @@ class AsmPrinter : public MachineFunctionPass {
585586
emitGlobalConstant(DL, CV);
586587
}
587588

589+
/// Lower the specified ptrauth constant to an MCExpr.
590+
virtual const MCExpr *lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
591+
report_fatal_error("ptrauth constant lowering not implemented");
592+
}
593+
588594
/// Return true if the basic block has exactly one predecessor and the control
589595
/// transfer mechanism between the predecessor and this block is a
590596
/// fall-through.

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,9 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
31773177
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
31783178
return MCConstantExpr::create(CI->getZExtValue(), Ctx);
31793179

3180+
if (const ConstantPtrAuth *CPA = dyn_cast<ConstantPtrAuth>(CV))
3181+
return lowerConstantPtrAuth(*CPA);
3182+
31803183
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
31813184
return MCSymbolRefExpr::create(getSymbol(GV), Ctx);
31823185

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#include "llvm/CodeGen/TargetRegisterInfo.h"
4444
#include "llvm/IR/DataLayout.h"
4545
#include "llvm/IR/DebugInfoMetadata.h"
46+
#include "llvm/IR/DiagnosticInfo.h"
47+
#include "llvm/IR/DiagnosticPrinter.h"
4648
#include "llvm/MC/MCAsmInfo.h"
4749
#include "llvm/MC/MCContext.h"
4850
#include "llvm/MC/MCInst.h"
@@ -90,6 +92,8 @@ class AArch64AsmPrinter : public AsmPrinter {
9092
return MCInstLowering.lowerOperand(MO, MCOp);
9193
}
9294

95+
const MCExpr *lowerConstantPtrAuth(const ConstantPtrAuth &CPA) override;
96+
9397
void emitStartOfAsmFile(Module &M) override;
9498
void emitJumpTableInfo() override;
9599
std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
@@ -1575,6 +1579,50 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
15751579
assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4);
15761580
}
15771581

1582+
const MCExpr *
1583+
AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
1584+
MCContext &Ctx = OutContext;
1585+
1586+
// Figure out the base symbol and the addend, if any.
1587+
APInt Offset(64, 0);
1588+
const Value *BaseGV = CPA.getPointer()->stripAndAccumulateConstantOffsets(
1589+
getDataLayout(), Offset, /*AllowNonInbounds=*/true);
1590+
1591+
auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
1592+
1593+
// If we can't understand the referenced ConstantExpr, there's nothing
1594+
// else we can do: emit an error.
1595+
if (!BaseGVB) {
1596+
BaseGV->getContext().emitError(
1597+
"cannot resolve target base/addend of ptrauth constant");
1598+
return nullptr;
1599+
}
1600+
1601+
// If there is an addend, turn that into the appropriate MCExpr.
1602+
const MCExpr *Sym = MCSymbolRefExpr::create(getSymbol(BaseGVB), Ctx);
1603+
if (Offset.sgt(0))
1604+
Sym = MCBinaryExpr::createAdd(
1605+
Sym, MCConstantExpr::create(Offset.getSExtValue(), Ctx), Ctx);
1606+
else if (Offset.slt(0))
1607+
Sym = MCBinaryExpr::createSub(
1608+
Sym, MCConstantExpr::create((-Offset).getSExtValue(), Ctx), Ctx);
1609+
1610+
uint64_t KeyID = CPA.getKey()->getZExtValue();
1611+
// We later rely on valid KeyID value in AArch64PACKeyIDToString call from
1612+
// AArch64AuthMCExpr::printImpl, so fail fast.
1613+
if (KeyID > AArch64PACKey::LAST)
1614+
report_fatal_error("invalid AArch64 PAC Key ID '" + Twine(KeyID) + "'");
1615+
1616+
uint64_t Disc = CPA.getDiscriminator()->getZExtValue();
1617+
if (!isUInt<16>(Disc))
1618+
report_fatal_error("invalid AArch64 PAC Discriminator '" + Twine(Disc) +
1619+
"'");
1620+
1621+
// Finally build the complete @AUTH expr.
1622+
return AArch64AuthMCExpr::create(Sym, Disc, AArch64PACKey::ID(KeyID),
1623+
CPA.hasAddressDiscriminator(), Ctx);
1624+
}
1625+
15781626
// Simple pseudo-instructions have their lowering (with expansion to real
15791627
// instructions) auto-generated.
15801628
#include "AArch64GenMCPseudoLowering.inc"
+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
; RUN: rm -rf %t && split-file %s %t && cd %t
2+
3+
;--- ok.ll
4+
5+
; RUN: llc < ok.ll -mtriple arm64e-apple-darwin \
6+
; RUN: | FileCheck %s --check-prefix=CHECK-MACHO
7+
; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth \
8+
; RUN: | FileCheck %s --check-prefix=CHECK-ELF
9+
10+
; RUN: llc < ok.ll -mtriple arm64e-apple-darwin \
11+
; RUN: -global-isel -verify-machineinstrs -global-isel-abort=1 \
12+
; RUN: | FileCheck %s --check-prefix=CHECK-MACHO
13+
; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth \
14+
; RUN: -global-isel -verify-machineinstrs -global-isel-abort=1 \
15+
; RUN: | FileCheck %s --check-prefix=CHECK-ELF
16+
17+
@g = external global i32
18+
19+
@g_weak = extern_weak global i32
20+
21+
@g_strong_def = constant i32 42
22+
23+
; CHECK-ELF-LABEL: .globl g.ref.ia.0
24+
; CHECK-ELF-NEXT: .p2align 4
25+
; CHECK-ELF-NEXT: g.ref.ia.0:
26+
; CHECK-ELF-NEXT: .xword 5
27+
; CHECK-ELF-NEXT: .xword g@AUTH(ia,0)
28+
; CHECK-ELF-NEXT: .xword 6
29+
30+
; CHECK-MACHO-LABEL: .section __DATA,__const
31+
; CHECK-MACHO-NEXT: .globl _g.ref.ia.0
32+
; CHECK-MACHO-NEXT: .p2align 4
33+
; CHECK-MACHO-NEXT: _g.ref.ia.0:
34+
; CHECK-MACHO-NEXT: .quad 5
35+
; CHECK-MACHO-NEXT: .quad _g@AUTH(ia,0)
36+
; CHECK-MACHO-NEXT: .quad 6
37+
38+
@g.ref.ia.0 = constant { i64, ptr, i64 } { i64 5, ptr ptrauth (ptr @g, i32 0), i64 6 }
39+
40+
; CHECK-ELF-LABEL: .globl g.ref.ia.42
41+
; CHECK-ELF-NEXT: .p2align 3
42+
; CHECK-ELF-NEXT: g.ref.ia.42:
43+
; CHECK-ELF-NEXT: .xword g@AUTH(ia,42)
44+
45+
; CHECK-MACHO-LABEL: .globl _g.ref.ia.42
46+
; CHECK-MACHO-NEXT: .p2align 3
47+
; CHECK-MACHO-NEXT: _g.ref.ia.42:
48+
; CHECK-MACHO-NEXT: .quad _g@AUTH(ia,42)
49+
50+
@g.ref.ia.42 = constant ptr ptrauth (ptr @g, i32 0, i64 42)
51+
52+
; CHECK-ELF-LABEL: .globl g.ref.ib.0
53+
; CHECK-ELF-NEXT: .p2align 4
54+
; CHECK-ELF-NEXT: g.ref.ib.0:
55+
; CHECK-ELF-NEXT: .xword 5
56+
; CHECK-ELF-NEXT: .xword g@AUTH(ib,0)
57+
; CHECK-ELF-NEXT: .xword 6
58+
59+
; CHECK-MACHO-LABEL: .globl _g.ref.ib.0
60+
; CHECK-MACHO-NEXT: .p2align 4
61+
; CHECK-MACHO-NEXT: _g.ref.ib.0:
62+
; CHECK-MACHO-NEXT: .quad 5
63+
; CHECK-MACHO-NEXT: .quad _g@AUTH(ib,0)
64+
; CHECK-MACHO-NEXT: .quad 6
65+
66+
@g.ref.ib.0 = constant { i64, ptr, i64 } { i64 5, ptr ptrauth (ptr @g, i32 1, i64 0), i64 6 }
67+
68+
; CHECK-ELF-LABEL: .globl g.ref.da.42.addr
69+
; CHECK-ELF-NEXT: .p2align 3
70+
; CHECK-ELF-NEXT: g.ref.da.42.addr:
71+
; CHECK-ELF-NEXT: .xword g@AUTH(da,42,addr)
72+
73+
; CHECK-MACHO-LABEL: .globl _g.ref.da.42.addr
74+
; CHECK-MACHO-NEXT: .p2align 3
75+
; CHECK-MACHO-NEXT: _g.ref.da.42.addr:
76+
; CHECK-MACHO-NEXT: .quad _g@AUTH(da,42,addr)
77+
78+
@g.ref.da.42.addr = constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr)
79+
80+
; CHECK-ELF-LABEL: .globl g.offset.ref.da.0
81+
; CHECK-ELF-NEXT: .p2align 3
82+
; CHECK-ELF-NEXT: g.offset.ref.da.0:
83+
; CHECK-ELF-NEXT: .xword (g+16)@AUTH(da,0)
84+
85+
; CHECK-MACHO-LABEL: .globl _g.offset.ref.da.0
86+
; CHECK-MACHO-NEXT: .p2align 3
87+
; CHECK-MACHO-NEXT: _g.offset.ref.da.0:
88+
; CHECK-MACHO-NEXT: .quad (_g+16)@AUTH(da,0)
89+
90+
@g.offset.ref.da.0 = constant ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 16), i32 2)
91+
92+
; CHECK-ELF-LABEL: .globl g.big_offset.ref.da.0
93+
; CHECK-ELF-NEXT: .p2align 3
94+
; CHECK-ELF-NEXT: g.big_offset.ref.da.0:
95+
; CHECK-ELF-NEXT: .xword (g+2147549185)@AUTH(da,0)
96+
97+
; CHECK-MACHO-LABEL: .globl _g.big_offset.ref.da.0
98+
; CHECK-MACHO-NEXT: .p2align 3
99+
; CHECK-MACHO-NEXT: _g.big_offset.ref.da.0:
100+
; CHECK-MACHO-NEXT: .quad (_g+2147549185)@AUTH(da,0)
101+
102+
@g.big_offset.ref.da.0 = constant ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2)
103+
104+
; CHECK-ELF-LABEL: .globl g.weird_ref.da.0
105+
; CHECK-ELF-NEXT: .p2align 3
106+
; CHECK-ELF-NEXT: g.weird_ref.da.0:
107+
; CHECK-ELF-NEXT: .xword (g+16)@AUTH(da,0)
108+
109+
; CHECK-MACHO-LABEL: .globl _g.weird_ref.da.0
110+
; CHECK-MACHO-NEXT: .p2align 3
111+
; CHECK-MACHO-NEXT: _g.weird_ref.da.0:
112+
; CHECK-MACHO-NEXT: .quad (_g+16)@AUTH(da,0)
113+
114+
@g.weird_ref.da.0 = constant i64 ptrtoint (ptr inttoptr (i64 ptrtoint (ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 16), i32 2) to i64) to ptr) to i64)
115+
116+
; CHECK-ELF-LABEL: .globl g_weak.ref.ia.42
117+
; CHECK-ELF-NEXT: .p2align 3
118+
; CHECK-ELF-NEXT: g_weak.ref.ia.42:
119+
; CHECK-ELF-NEXT: .xword g_weak@AUTH(ia,42)
120+
121+
; CHECK-MACHO-LABEL: .globl _g_weak.ref.ia.42
122+
; CHECK-MACHO-NEXT: .p2align 3
123+
; CHECK-MACHO-NEXT: _g_weak.ref.ia.42:
124+
; CHECK-MACHO-NEXT: .quad _g_weak@AUTH(ia,42)
125+
126+
@g_weak.ref.ia.42 = constant ptr ptrauth (ptr @g_weak, i32 0, i64 42)
127+
128+
; CHECK-ELF-LABEL: .globl g_strong_def.ref.da.0
129+
; CHECK-ELF-NEXT: .p2align 3
130+
; CHECK-ELF-NEXT: g_strong_def.ref.da.0:
131+
; CHECK-ELF-NEXT: .xword g_strong_def@AUTH(da,0)
132+
133+
; CHECK-MACHO-LABEL: .globl _g_strong_def.ref.da.0
134+
; CHECK-MACHO-NEXT: .p2align 3
135+
; CHECK-MACHO-NEXT: _g_strong_def.ref.da.0:
136+
; CHECK-MACHO-NEXT: .quad _g_strong_def@AUTH(da,0)
137+
138+
@g_strong_def.ref.da.0 = constant ptr ptrauth (ptr @g_strong_def, i32 2)
139+
140+
;--- err-key.ll
141+
142+
; RUN: not --crash llc < err-key.ll -mtriple arm64e-apple-darwin 2>&1 \
143+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-KEY
144+
; RUN: not --crash llc < err-key.ll -mtriple aarch64-elf -mattr=+pauth 2>&1 \
145+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-KEY
146+
147+
; RUN: not --crash llc < err-key.ll -mtriple arm64e-apple-darwin \
148+
; RUN: -global-isel -verify-machineinstrs -global-isel-abort=1 2>&1 \
149+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-KEY
150+
; RUN: not --crash llc < err-key.ll -mtriple aarch64-elf -mattr=+pauth \
151+
; RUN: -global-isel -verify-machineinstrs -global-isel-abort=1 2>&1 \
152+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-KEY
153+
154+
; CHECK-ERR-KEY: LLVM ERROR: invalid AArch64 PAC Key ID '4'
155+
156+
@g = external global i32
157+
@g.ref.4.0 = constant ptr ptrauth (ptr @g, i32 4, i64 0)
158+
159+
;--- err-disc.ll
160+
161+
; RUN: not --crash llc < err-disc.ll -mtriple arm64e-apple-darwin 2>&1 \
162+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-DISC
163+
; RUN: not --crash llc < err-disc.ll -mtriple aarch64-elf -mattr=+pauth 2>&1 \
164+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-DISC
165+
166+
; RUN: not --crash llc < err-disc.ll -mtriple arm64e-apple-darwin \
167+
; RUN: -global-isel -verify-machineinstrs -global-isel-abort=1 2>&1 \
168+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-DISC
169+
; RUN: not --crash llc < err-disc.ll -mtriple aarch64-elf -mattr=+pauth \
170+
; RUN: -global-isel -verify-machineinstrs -global-isel-abort=1 2>&1 \
171+
; RUN: | FileCheck %s --check-prefix=CHECK-ERR-DISC
172+
173+
; CHECK-ERR-DISC: LLVM ERROR: invalid AArch64 PAC Discriminator '65536'
174+
175+
@g = external global i32
176+
@g.ref.ia.65536 = constant ptr ptrauth (ptr @g, i32 0, i64 65536)

0 commit comments

Comments
 (0)