Skip to content

Commit 70efb00

Browse files
committed
[AArch64][PAC][ELF] Lower constant and code references
1 parent ff95e04 commit 70efb00

File tree

13 files changed

+476
-84
lines changed

13 files changed

+476
-84
lines changed

llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,18 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
8383
/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
8484
/// for ELF targets.
8585
class MachineModuleInfoELF : public MachineModuleInfoImpl {
86+
public:
87+
struct AuthStubInfo {
88+
const MCExpr *AuthPtrRef;
89+
};
90+
91+
private:
8692
/// GVStubs - These stubs are used to materialize global addresses in PIC
8793
/// mode.
8894
DenseMap<MCSymbol *, StubValueTy> GVStubs;
8995

96+
DenseMap<MCSymbol *, AuthStubInfo> AuthPtrStubs;
97+
9098
virtual void anchor(); // Out of line virtual method.
9199

92100
public:
@@ -97,9 +105,19 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
97105
return GVStubs[Sym];
98106
}
99107

108+
AuthStubInfo &getAuthPtrStubEntry(MCSymbol *Sym) {
109+
assert(Sym && "Key cannot be null");
110+
return AuthPtrStubs[Sym];
111+
}
112+
100113
/// Accessor methods to return the set of stubs in sorted order.
101114

102115
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
116+
117+
typedef std::pair<MCSymbol *, AuthStubInfo> AuthStubPairTy;
118+
typedef std::vector<AuthStubPairTy> AuthStubListTy;
119+
120+
AuthStubListTy getAuthGVStubList();
103121
};
104122

105123
/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation

llvm/lib/CodeGen/MachineModuleInfoImpls.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,29 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs(
4242
return List;
4343
}
4444

45-
MachineModuleInfoMachO::AuthStubListTy
46-
MachineModuleInfoMachO::getAuthGVStubList() {
47-
AuthStubListTy List(AuthPtrStubs.begin(), AuthPtrStubs.end());
45+
template <typename MachineModuleInfoTarget>
46+
static typename MachineModuleInfoTarget::AuthStubListTy getAuthGVStubListHelper(
47+
DenseMap<MCSymbol *, typename MachineModuleInfoTarget::AuthStubInfo>
48+
&AuthPtrStubs) {
49+
typename MachineModuleInfoTarget::AuthStubListTy List(AuthPtrStubs.begin(),
50+
AuthPtrStubs.end());
4851

4952
if (!List.empty())
5053
std::sort(List.begin(), List.end(),
51-
[](const AuthStubPairTy &LHS, const AuthStubPairTy &RHS) {
52-
return LHS.first->getName() < RHS.first->getName();
54+
[](const typename MachineModuleInfoTarget::AuthStubPairTy &LHS,
55+
const typename MachineModuleInfoTarget::AuthStubPairTy &RHS) {
56+
return LHS.first->getName() < RHS.first->getName();
5357
});
5458

5559
AuthPtrStubs.clear();
5660
return List;
5761
}
62+
63+
MachineModuleInfoMachO::AuthStubListTy
64+
MachineModuleInfoMachO::getAuthGVStubList() {
65+
return getAuthGVStubListHelper<MachineModuleInfoMachO>(AuthPtrStubs);
66+
}
67+
68+
MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() {
69+
return getAuthGVStubListHelper<MachineModuleInfoELF>(AuthPtrStubs);
70+
}

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -860,9 +860,10 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
860860
}
861861
}
862862

863-
static void
864-
emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
865-
const MachineModuleInfoMachO::AuthStubInfo &StubInfo) {
863+
template <typename MachineModuleInfoTarget>
864+
static void emitAuthenticatedPointer(
865+
MCStreamer &OutStreamer, MCSymbol *StubLabel,
866+
const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo) {
866867
// L_foo$addend$auth_ptr$ib$23:
867868
OutStreamer.emitLabel(StubLabel);
868869
OutStreamer.emitValue(StubInfo.AuthPtrRef, /*size=*/8);
@@ -888,7 +889,8 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
888889
emitAlignment(Align(8));
889890

890891
for (auto &Stub : Stubs)
891-
emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);
892+
emitAuthenticatedPointer<MachineModuleInfoMachO>(
893+
*OutStreamer, Stub.first, Stub.second);
892894

893895
OutStreamer->addBlankLine();
894896
}
@@ -901,9 +903,27 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
901903
OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
902904
}
903905

906+
if (TT.isOSBinFormatELF()) {
907+
// Output authenticated pointers as indirect symbols, if we have any.
908+
MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
909+
910+
auto Stubs = MMIELF.getAuthGVStubList();
911+
912+
if (!Stubs.empty()) {
913+
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
914+
OutStreamer->switchSection(TLOF.getDataSection());
915+
emitAlignment(Align(8));
916+
917+
for (auto &Stub : Stubs)
918+
emitAuthenticatedPointer<MachineModuleInfoELF>(*OutStreamer, Stub.first,
919+
Stub.second);
920+
921+
OutStreamer->addBlankLine();
922+
}
923+
}
924+
904925
// Emit stack and fault map information.
905926
FM.serializeToFaultMapSection();
906-
907927
}
908928

909929
void AArch64AsmPrinter::emitLOHs() {
@@ -1877,8 +1897,8 @@ AArch64AsmPrinter::lowerPtrAuthGlobalConstant(const GlobalPtrAuthInfo &PAI) {
18771897

18781898
std::string Buf;
18791899
raw_string_ostream OS(Buf);
1880-
OS << "Couldn't resolve target base/addend of llvm.ptrauth global '"
1881-
<< *BaseGVB << "'";
1900+
OS << "couldn't resolve target base/addend of llvm.ptrauth global '"
1901+
<< *BaseGVB << "'";
18821902
BaseGV->getContext().emitError(OS.str());
18831903
}
18841904

@@ -1892,16 +1912,20 @@ AArch64AsmPrinter::lowerPtrAuthGlobalConstant(const GlobalPtrAuthInfo &PAI) {
18921912
Sym, MCConstantExpr::create((-Offset).getSExtValue(), Ctx), Ctx);
18931913

18941914
uint64_t KeyID = PAI.getKey()->getZExtValue();
1895-
if (!isUInt<2>(KeyID))
1915+
if (KeyID > AArch64PACKey::LAST)
18961916
BaseGV->getContext().emitError(
1897-
"Invalid AArch64 PAC Key ID '" + utostr(KeyID) + "' in llvm.ptrauth global '" +
1917+
"AArch64 PAC key ID '" + Twine(KeyID) + "' out of range [0, " +
1918+
Twine(static_cast<int>(AArch64PACKey::LAST)) +
1919+
"] in llvm.ptrauth "
1920+
"global '" +
18981921
BaseGV->getName() + "'");
18991922

19001923
uint64_t Disc = PAI.getDiscriminator()->getZExtValue();
19011924
if (!isUInt<16>(Disc))
1902-
BaseGV->getContext().emitError("Invalid AArch64 Discriminator '" +
1903-
utostr(Disc) + "' in llvm.ptrauth global '" +
1904-
BaseGV->getName() + "'");
1925+
BaseGV->getContext().emitError(
1926+
"AArch64 PAC discriminator '" + Twine(Disc) +
1927+
"' out of range [0, 0xFFFF] in llvm.ptrauth global '" +
1928+
BaseGV->getName() + "'");
19051929

19061930
// Finally build the complete @AUTH expr.
19071931
return AArch64AuthMCExpr::create(Sym, Disc, AArch64PACKey::ID(KeyID),

llvm/lib/Target/AArch64/AArch64ExpandHardenedPseudos.cpp

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,22 @@ bool AArch64ExpandHardenedPseudos::expandPtrAuthPseudo(MachineInstr &MI) {
191191
// Where the $auth_ptr$ symbol is the stub slot containing the signed pointer
192192
// to _symbol.
193193
// We defined the stub ourselves, so we don't need a GOT access.
194-
assert(TM.getTargetTriple().isOSBinFormatMachO() &&
195-
"ptrauth chkstk_darwin only implemented on mach-o");
196-
auto *TLOF =
197-
static_cast<AArch64_MachoTargetObjectFile *>(TM.getObjFileLowering());
198-
MCSymbol *AuthPtrStubSym =
199-
TLOF->getAuthPtrSlotSymbol(TM, &MMI, GASym, Offset, Key, Disc);
194+
195+
MCSymbol *AuthPtrStubSym;
196+
if (TM.getTargetTriple().isOSBinFormatMachO()) {
197+
auto *TLOF =
198+
static_cast<AArch64_MachoTargetObjectFile *>(TM.getObjFileLowering());
199+
AuthPtrStubSym =
200+
TLOF->getAuthPtrSlotSymbol(TM, &MMI, GASym, Offset, Key, Disc);
201+
} else if (TM.getTargetTriple().isOSBinFormatELF()) {
202+
auto *TLOF =
203+
static_cast<AArch64_ELFTargetObjectFile *>(TM.getObjFileLowering());
204+
AuthPtrStubSym =
205+
TLOF->getAuthPtrSlotSymbol(TM, &MMI, GASym, Offset, Key, Disc);
206+
} else {
207+
llvm_unreachable(
208+
"ptrauth static materialization only implemented on mach-o and elf");
209+
}
200210

201211
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADRP), DstReg)
202212
.addSym(AuthPtrStubSym, AArch64II::MO_PAGE);
@@ -278,30 +288,33 @@ bool AArch64ExpandHardenedPseudos::expandPtrAuthPseudo(MachineInstr &MI) {
278288
}
279289
}
280290

291+
auto *SignMBB = &MBB;
292+
auto SignMBBI = MBBI;
293+
281294
unsigned DiscReg = AddrDisc;
282295
if (Disc) {
283296
assert(isUInt<16>(Disc) && "Constant discriminator is too wide");
284297

285298
if (AddrDisc != AArch64::XZR) {
286-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
287-
.addReg(AArch64::XZR)
288-
.addReg(AddrDisc)
289-
.addImm(0);
290-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X17)
291-
.addReg(AArch64::X17)
292-
.addImm(Disc)
293-
.addImm(/*shift=*/48);
299+
BuildMI(*SignMBB, SignMBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
300+
.addReg(AArch64::XZR)
301+
.addReg(AddrDisc)
302+
.addImm(0);
303+
BuildMI(*SignMBB, SignMBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X17)
304+
.addReg(AArch64::X17)
305+
.addImm(Disc)
306+
.addImm(/*shift=*/48);
294307
} else {
295-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X17)
296-
.addImm(Disc)
297-
.addImm(/*shift=*/0);
308+
BuildMI(*SignMBB, SignMBBI, DL, TII->get(AArch64::MOVZXi), AArch64::X17)
309+
.addImm(Disc)
310+
.addImm(/*shift=*/0);
298311
}
299312
DiscReg = AArch64::X17;
300313
}
301314

302315
unsigned PACOpc = getPACOpcodeForKey(Key, DiscReg == AArch64::XZR);
303-
auto MIB = BuildMI(MBB, MBBI, DL, TII->get(PACOpc), AArch64::X16)
304-
.addReg(AArch64::X16);
316+
auto MIB = BuildMI(*SignMBB, SignMBBI, DL, TII->get(PACOpc), AArch64::X16)
317+
.addReg(AArch64::X16);
305318
if (DiscReg != AArch64::XZR)
306319
MIB.addReg(DiscReg);
307320

@@ -448,8 +461,12 @@ bool AArch64ExpandHardenedPseudos::runOnMachineFunction(MachineFunction &MF) {
448461
bool Modified = false;
449462
for (auto &MBB : MF) {
450463
for (auto MBBI = MBB.instr_begin(), MBBE = MBB.instr_end(); MBBI != MBBE; ) {
451-
auto &MI = *MBBI++;
452-
if (expandMI(MI)) {
464+
auto &MI = *MBBI;
465+
bool IsExpanded = expandMI(MI);
466+
// Previous expandMI invocation might split the current basic block, so we
467+
// increment the instruction iterator after that.
468+
++MBBI;
469+
if (IsExpanded) {
453470
MI.eraseFromBundle();
454471
Modified |= true;
455472
}

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8601,6 +8601,8 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
86018601
SDValue AArch64TargetLowering::LowerPtrAuthGlobalAddressViaGOT(
86028602
SDValue TGA, SDLoc DL, EVT VT, AArch64PACKey::ID KeyC,
86038603
SDValue Discriminator, SDValue AddrDiscriminator, SelectionDAG &DAG) const {
8604+
assert((Subtarget->isTargetMachO() || Subtarget->isTargetELF()) &&
8605+
"LOADauthptrgot is only supported for MachO and ELF");
86048606

86058607
auto *TGN = cast<GlobalAddressSDNode>(TGA.getNode());
86068608
const GlobalValue *GV = TGN->getGlobal();
@@ -8672,7 +8674,7 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
86728674
SDLoc DL(Op);
86738675

86748676
// Both key allocation and the wrapper usage support are target-specific.
8675-
if (!Subtarget->isTargetMachO())
8677+
if (!Subtarget->isTargetMachO() && !Subtarget->isTargetELF())
86768678
llvm_unreachable("Unimplemented ptrauth global lowering");
86778679

86788680
uint64_t PtrOffsetC = 0;
@@ -8697,12 +8699,14 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
86978699
assert(PtrN->getTargetFlags() == 0 && "Unsupported tflags on ptrauth global");
86988700

86998701
// None of our lowerings support an offset larger than 32-bit.
8702+
// TODO: rela elf supports 64-bit?
87008703
if (!isUInt<32>(PtrOffsetC))
87018704
report_fatal_error("Unsupported >32-bit-wide offset in ptrauth global");
87028705

87038706
// The shared cache severely constrains the offset, to 5 bits, which prevents
8704-
// us from using LOADauthptrgot, our only option for extern_weak.
8705-
if (!isUInt<5>(PtrOffsetC) && PtrGV->hasExternalWeakLinkage())
8707+
// us from using LOADauthptrgot, our only option for extern_weak on MachO.
8708+
if (!isUInt<5>(PtrOffsetC) && PtrGV->hasExternalWeakLinkage() &&
8709+
(Subtarget->isTargetMachO() || Subtarget->isTargetELF()))
87068710
report_fatal_error("Offset in weak ptrauth global reference is too large");
87078711

87088712
// Blend only works if the integer discriminator is 16-bit wide.
@@ -8718,7 +8722,9 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
87188722

87198723
// No GOT load needed -> MOVaddrPAC
87208724
if (!NeedsGOTLoad) {
8721-
assert(!PtrGV->hasExternalWeakLinkage() && "extern_weak should use GOT");
8725+
assert(!(PtrGV->hasExternalWeakLinkage() &&
8726+
(Subtarget->isTargetMachO() || Subtarget->isTargetELF())) &&
8727+
"extern_weak on MachO should use GOT via LOADauthptrgot");
87228728
return SDValue(
87238729
DAG.getMachineNode(AArch64::MOVaddrPAC, DL, MVT::i64,
87248730
{TPtr, Key, TAddrDiscriminator, Discriminator}),

llvm/lib/Target/AArch64/AArch64MCInstLower.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,19 @@ AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
3939
: Ctx(ctx), Printer(printer) {}
4040

4141
static MCSymbol *getAuthGVStub(const GlobalVariable *GVB, AsmPrinter &Printer) {
42-
assert(Printer.TM.getTargetTriple().isOSBinFormatMachO() &&
43-
"auth_ptr stubs only implemented on macho");
44-
auto &TLOF = static_cast<const AArch64_MachoTargetObjectFile &>(
45-
Printer.getObjFileLowering());
46-
47-
return TLOF.getAuthPtrSlotSymbol(Printer.TM, Printer.MMI,
48-
*GlobalPtrAuthInfo::analyze(GVB));
42+
if (Printer.TM.getTargetTriple().isOSBinFormatMachO()) {
43+
auto &TLOF = static_cast<const AArch64_MachoTargetObjectFile &>(
44+
Printer.getObjFileLowering());
45+
return TLOF.getAuthPtrSlotSymbol(Printer.TM, Printer.MMI,
46+
*GlobalPtrAuthInfo::analyze(GVB));
47+
} else if (Printer.TM.getTargetTriple().isOSBinFormatELF()) {
48+
auto &TLOF = static_cast<const AArch64_ELFTargetObjectFile &>(
49+
Printer.getObjFileLowering());
50+
return TLOF.getAuthPtrSlotSymbol(Printer.TM, Printer.MMI,
51+
*GlobalPtrAuthInfo::analyze(GVB));
52+
} else {
53+
llvm_unreachable("auth_ptr stubs only implemented on macho and elf");
54+
}
4955
}
5056

5157
MCSymbol *

0 commit comments

Comments
 (0)