Skip to content

Commit 5f1bb62

Browse files
[AArch64][PAC] Lower ptrauth constants in code for MachO. (#97665)
This also adds support for auth stubs on MachO using __DATA,__auth_ptr. Some of the machinery for auth stubs is already implemented; this generalizes that a bit to support MachO, and moves some of the shared logic into MMIImpls. In particular, this originally had an AuthStubInfo struct, but we no longer need it beyond a single MCExpr. So this provides variants of the symbol stub helper type declarations and functions for "expr stubs", where a stub points at an arbitrary MCExpr, rather than a simple MCSymbol (and a bit).
1 parent 41de50b commit 5f1bb62

11 files changed

+621
-260
lines changed

llvm/include/llvm/CodeGen/MachineModuleInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,20 @@ class MachineModuleInfoImpl {
5858
using StubValueTy = PointerIntPair<MCSymbol *, 1, bool>;
5959
using SymbolListTy = std::vector<std::pair<MCSymbol *, StubValueTy>>;
6060

61+
/// A variant of SymbolListTy where the stub is a generalized MCExpr.
62+
using ExprStubListTy = std::vector<std::pair<MCSymbol *, const MCExpr *>>;
63+
6164
virtual ~MachineModuleInfoImpl();
6265

6366
protected:
6467
/// Return the entries from a DenseMap in a deterministic sorted orer.
6568
/// Clears the map.
6669
static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&);
70+
71+
/// Return the entries from a DenseMap in a deterministic sorted orer.
72+
/// Clears the map.
73+
static ExprStubListTy
74+
getSortedExprStubs(DenseMap<MCSymbol *, const MCExpr *> &);
6775
};
6876

6977
//===----------------------------------------------------------------------===//

llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
3636
/// bit is true if this GV is external.
3737
DenseMap<MCSymbol *, StubValueTy> ThreadLocalGVStubs;
3838

39+
/// Darwin '$auth_ptr' stubs. The key is the stub symbol, like
40+
/// "Lfoo$auth_ptr$ib$12". The value is the MCExpr representing that
41+
/// signed pointer, something like "_foo@AUTH(ib, 12)".
42+
DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;
43+
3944
virtual void anchor(); // Out of line virtual method.
4045

4146
public:
@@ -51,29 +56,32 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
5156
return ThreadLocalGVStubs[Sym];
5257
}
5358

59+
const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) {
60+
assert(Sym && "Key cannot be null");
61+
return AuthPtrStubs[Sym];
62+
}
63+
5464
/// Accessor methods to return the set of stubs in sorted order.
5565
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
5666
SymbolListTy GetThreadLocalGVStubList() {
5767
return getSortedStubs(ThreadLocalGVStubs);
5868
}
69+
70+
ExprStubListTy getAuthGVStubList() {
71+
return getSortedExprStubs(AuthPtrStubs);
72+
}
5973
};
6074

6175
/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
6276
/// for ELF targets.
6377
class MachineModuleInfoELF : public MachineModuleInfoImpl {
64-
public:
65-
struct AuthStubInfo {
66-
const MCExpr *AuthPtrRef;
67-
};
68-
69-
private:
7078
/// GVStubs - These stubs are used to materialize global addresses in PIC
7179
/// mode.
7280
DenseMap<MCSymbol *, StubValueTy> GVStubs;
7381

7482
/// AuthPtrStubs - These stubs are used to materialize signed addresses for
7583
/// extern_weak symbols.
76-
DenseMap<MCSymbol *, AuthStubInfo> AuthPtrStubs;
84+
DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;
7785

7886
virtual void anchor(); // Out of line virtual method.
7987

@@ -85,7 +93,7 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
8593
return GVStubs[Sym];
8694
}
8795

88-
AuthStubInfo &getAuthPtrStubEntry(MCSymbol *Sym) {
96+
const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) {
8997
assert(Sym && "Key cannot be null");
9098
return AuthPtrStubs[Sym];
9199
}
@@ -94,10 +102,9 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
94102

95103
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
96104

97-
using AuthStubPairTy = std::pair<MCSymbol *, AuthStubInfo>;
98-
typedef std::vector<AuthStubPairTy> AuthStubListTy;
99-
100-
AuthStubListTy getAuthGVStubList();
105+
ExprStubListTy getAuthGVStubList() {
106+
return getSortedExprStubs(AuthPtrStubs);
107+
}
101108
};
102109

103110
/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation

llvm/lib/CodeGen/MachineModuleInfoImpls.cpp

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,19 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs(
4343
return List;
4444
}
4545

46-
template <typename MachineModuleInfoTarget>
47-
static typename MachineModuleInfoTarget::AuthStubListTy getAuthGVStubListHelper(
48-
DenseMap<MCSymbol *, typename MachineModuleInfoTarget::AuthStubInfo>
49-
&AuthPtrStubs) {
50-
typename MachineModuleInfoTarget::AuthStubListTy List(AuthPtrStubs.begin(),
51-
AuthPtrStubs.end());
46+
using ExprStubPairTy = std::pair<MCSymbol *, const MCExpr *>;
47+
static int SortAuthStubPair(const ExprStubPairTy *LHS,
48+
const ExprStubPairTy *RHS) {
49+
return LHS->first->getName().compare(RHS->first->getName());
50+
}
5251

53-
if (!List.empty())
54-
llvm::sort(List.begin(), List.end(),
55-
[](const typename MachineModuleInfoTarget::AuthStubPairTy &LHS,
56-
const typename MachineModuleInfoTarget::AuthStubPairTy &RHS) {
57-
return LHS.first->getName() < RHS.first->getName();
58-
});
52+
MachineModuleInfoImpl::ExprStubListTy MachineModuleInfoImpl::getSortedExprStubs(
53+
DenseMap<MCSymbol *, const MCExpr *> &ExprStubs) {
54+
MachineModuleInfoImpl::ExprStubListTy List(ExprStubs.begin(),
55+
ExprStubs.end());
5956

60-
AuthPtrStubs.clear();
61-
return List;
62-
}
57+
array_pod_sort(List.begin(), List.end(), SortAuthStubPair);
6358

64-
MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() {
65-
return getAuthGVStubListHelper<MachineModuleInfoELF>(AuthPtrStubs);
59+
ExprStubs.clear();
60+
return List;
6661
}

llvm/lib/MC/MCMachOStreamer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
167167
return true;
168168
if (SegName == "__LLVM" && (SecName == "__cg_profile"))
169169
return true;
170+
171+
if (SegName == "__DATA" && SecName == "__auth_ptr")
172+
return true;
173+
170174
return false;
171175
}
172176

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -848,20 +848,38 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
848848
}
849849
}
850850

851-
template <typename MachineModuleInfoTarget>
852-
static void emitAuthenticatedPointer(
853-
MCStreamer &OutStreamer, MCSymbol *StubLabel,
854-
const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo) {
851+
static void emitAuthenticatedPointer(MCStreamer &OutStreamer,
852+
MCSymbol *StubLabel,
853+
const MCExpr *StubAuthPtrRef) {
855854
// sym$auth_ptr$key$disc:
856855
OutStreamer.emitLabel(StubLabel);
857-
OutStreamer.emitValue(StubInfo.AuthPtrRef, /*size=*/8);
856+
OutStreamer.emitValue(StubAuthPtrRef, /*size=*/8);
858857
}
859858

860859
void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
861860
emitHwasanMemaccessSymbols(M);
862861

863862
const Triple &TT = TM.getTargetTriple();
864863
if (TT.isOSBinFormatMachO()) {
864+
// Output authenticated pointers as indirect symbols, if we have any.
865+
MachineModuleInfoMachO &MMIMacho =
866+
MMI->getObjFileInfo<MachineModuleInfoMachO>();
867+
868+
auto Stubs = MMIMacho.getAuthGVStubList();
869+
870+
if (!Stubs.empty()) {
871+
// Switch to the "__auth_ptr" section.
872+
OutStreamer->switchSection(
873+
OutContext.getMachOSection("__DATA", "__auth_ptr", MachO::S_REGULAR,
874+
SectionKind::getMetadata()));
875+
emitAlignment(Align(8));
876+
877+
for (const auto &Stub : Stubs)
878+
emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);
879+
880+
OutStreamer->addBlankLine();
881+
}
882+
865883
// Funny Darwin hack: This flag tells the linker that no global symbols
866884
// contain code that falls through to other global symbols (e.g. the obvious
867885
// implementation of multiple entry points). If this doesn't occur, the
@@ -882,8 +900,7 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
882900
emitAlignment(Align(8));
883901

884902
for (const auto &Stub : Stubs)
885-
emitAuthenticatedPointer<MachineModuleInfoELF>(*OutStreamer, Stub.first,
886-
Stub.second);
903+
emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);
887904

888905
OutStreamer->addBlankLine();
889906
}
@@ -1676,16 +1693,29 @@ void AArch64AsmPrinter::LowerLOADauthptrstatic(const MachineInstr &MI) {
16761693
//
16771694
// Where the $auth_ptr$ symbol is the stub slot containing the signed pointer
16781695
// to symbol.
1679-
assert(TM.getTargetTriple().isOSBinFormatELF() &&
1680-
"LOADauthptrstatic is implemented only for ELF");
1681-
const auto &TLOF =
1682-
static_cast<const AArch64_ELFTargetObjectFile &>(getObjFileLowering());
1683-
1684-
assert(GAOp.getOffset() == 0 &&
1685-
"non-zero offset for $auth_ptr$ stub slots is not supported");
1686-
const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
1687-
MCSymbol *AuthPtrStubSym =
1688-
TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
1696+
MCSymbol *AuthPtrStubSym;
1697+
if (TM.getTargetTriple().isOSBinFormatELF()) {
1698+
const auto &TLOF =
1699+
static_cast<const AArch64_ELFTargetObjectFile &>(getObjFileLowering());
1700+
1701+
assert(GAOp.getOffset() == 0 &&
1702+
"non-zero offset for $auth_ptr$ stub slots is not supported");
1703+
const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
1704+
AuthPtrStubSym =
1705+
TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
1706+
} else {
1707+
assert(TM.getTargetTriple().isOSBinFormatMachO() &&
1708+
"LOADauthptrstatic is implemented only for MachO/ELF");
1709+
1710+
const auto &TLOF = static_cast<const AArch64_MachoTargetObjectFile &>(
1711+
getObjFileLowering());
1712+
1713+
assert(GAOp.getOffset() == 0 &&
1714+
"non-zero offset for $auth_ptr$ stub slots is not supported");
1715+
const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
1716+
AuthPtrStubSym =
1717+
TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
1718+
}
16891719

16901720
MachineOperand StubMOHi =
16911721
MachineOperand::CreateMCSymbol(AuthPtrStubSym, AArch64II::MO_PAGE);

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9545,8 +9545,7 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
95459545
// Load a signed pointer for symbol 'sym' from a stub slot named
95469546
// 'sym$auth_ptr$key$disc' filled by dynamic linker during relocation
95479547
// resolving. This usually lowers to adrp+ldr, but also emits an entry into
9548-
// .data with an
9549-
// @AUTH relocation. See LowerLOADauthptrstatic.
9548+
// .data with an @AUTH relocation. See LowerLOADauthptrstatic.
95509549
//
95519550
// All 3 are pseudos that are expand late to longer sequences: this lets us
95529551
// provide integrity guarantees on the to-be-signed intermediate values.
@@ -9599,8 +9598,8 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
95999598
"constant discriminator in ptrauth global out of range [0, 0xffff]");
96009599

96019600
// Choosing between 3 lowering alternatives is target-specific.
9602-
if (!Subtarget->isTargetELF())
9603-
report_fatal_error("ptrauth global lowering is only implemented for ELF");
9601+
if (!Subtarget->isTargetELF() && !Subtarget->isTargetMachO())
9602+
report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
96049603

96059604
int64_t PtrOffsetC = 0;
96069605
if (Ptr.getOpcode() == ISD::ADD) {

llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,14 @@ static MCSymbol *getAuthPtrSlotSymbolHelper(
105105
Twine("$auth_ptr$") + AArch64PACKeyIDToString(Key) + Twine('$') +
106106
Twine(Discriminator));
107107

108-
typename MachineModuleInfoTarget::AuthStubInfo &StubInfo =
109-
TargetMMI.getAuthPtrStubEntry(StubSym);
108+
const MCExpr *&StubAuthPtrRef = TargetMMI.getAuthPtrStubEntry(StubSym);
110109

111-
if (StubInfo.AuthPtrRef)
110+
if (StubAuthPtrRef)
112111
return StubSym;
113112

114113
const MCExpr *Sym = MCSymbolRefExpr::create(RawSym, Ctx);
115114

116-
StubInfo.AuthPtrRef =
115+
StubAuthPtrRef =
117116
AArch64AuthMCExpr::create(Sym, Discriminator, Key,
118117
/*HasAddressDiversity=*/false, Ctx);
119118
return StubSym;
@@ -126,3 +125,11 @@ MCSymbol *AArch64_ELFTargetObjectFile::getAuthPtrSlotSymbol(
126125
return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, ELFMMI, RawSym, Key,
127126
Discriminator);
128127
}
128+
129+
MCSymbol *AArch64_MachoTargetObjectFile::getAuthPtrSlotSymbol(
130+
const TargetMachine &TM, MachineModuleInfo *MMI, const MCSymbol *RawSym,
131+
AArch64PACKey::ID Key, uint16_t Discriminator) const {
132+
auto &MachOMMI = MMI->getObjFileInfo<MachineModuleInfoMachO>();
133+
return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, MachOMMI, RawSym,
134+
Key, Discriminator);
135+
}

llvm/lib/Target/AArch64/AArch64TargetObjectFile.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ class AArch64_MachoTargetObjectFile : public TargetLoweringObjectFileMachO {
6060

6161
void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV,
6262
const TargetMachine &TM) const override;
63+
64+
MCSymbol *getAuthPtrSlotSymbol(const TargetMachine &TM,
65+
MachineModuleInfo *MMI, const MCSymbol *RawSym,
66+
AArch64PACKey::ID Key,
67+
uint16_t Discriminator) const;
6368
};
6469

6570
/// This implementation is used for AArch64 COFF targets.

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6636,8 +6636,8 @@ bool AArch64InstructionSelector::selectPtrAuthGlobalValue(
66366636
"constant discriminator in ptrauth global out of range [0, 0xffff]");
66376637

66386638
// Choosing between 3 lowering alternatives is target-specific.
6639-
if (!STI.isTargetELF())
6640-
report_fatal_error("ptrauth global lowering is only implemented for ELF");
6639+
if (!STI.isTargetELF() && !STI.isTargetMachO())
6640+
report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
66416641

66426642
if (!MRI.hasOneDef(Addr))
66436643
return false;

0 commit comments

Comments
 (0)