Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/MachineModuleInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,20 @@ class MachineModuleInfoImpl {
using StubValueTy = PointerIntPair<MCSymbol *, 1, bool>;
using SymbolListTy = std::vector<std::pair<MCSymbol *, StubValueTy>>;

/// A variant of SymbolListTy where the stub is a generalized MCExpr.
using ExprStubListTy = std::vector<std::pair<MCSymbol *, const MCExpr *>>;

virtual ~MachineModuleInfoImpl();

protected:
/// Return the entries from a DenseMap in a deterministic sorted orer.
/// Clears the map.
static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&);

/// Return the entries from a DenseMap in a deterministic sorted orer.
/// Clears the map.
static ExprStubListTy
getSortedExprStubs(DenseMap<MCSymbol *, const MCExpr *> &);
};

//===----------------------------------------------------------------------===//
Expand Down
31 changes: 19 additions & 12 deletions llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
/// bit is true if this GV is external.
DenseMap<MCSymbol *, StubValueTy> ThreadLocalGVStubs;

/// Darwin '$auth_ptr' stubs. The key is the stub symbol, like
/// "Lfoo$addend$auth_ptr$ib$12". The value is the MCExpr representing that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just in case you've missed that - currently, there is no addend support for $auth_ptr$ symbols - see getAuthPtrSlotSymbolHelper. It's probably worth mentioning that addend is optional in this comment. Feel free to ignore though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I don't think we'll ever need the addend support here, I'm keeping it downstream for some other use-cases.

I should mention we're also missing the address-diversity support here, and that one we'll likely want to add here in the future, at least for MachO; we'll see then whether it's needed for ELF, given the broader support for auth GOT relocations that MachO doesn't expose.

/// pointer, something like "_foo+addend@AUTH(ib, 12)".
DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;

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

public:
Expand All @@ -51,29 +56,32 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
return ThreadLocalGVStubs[Sym];
}

const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
return AuthPtrStubs[Sym];
}

/// Accessor methods to return the set of stubs in sorted order.
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
SymbolListTy GetThreadLocalGVStubList() {
return getSortedStubs(ThreadLocalGVStubs);
}

ExprStubListTy getAuthGVStubList() {
return getSortedExprStubs(AuthPtrStubs);
}
};

/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
/// for ELF targets.
class MachineModuleInfoELF : public MachineModuleInfoImpl {
public:
struct AuthStubInfo {
const MCExpr *AuthPtrRef;
};

private:
/// GVStubs - These stubs are used to materialize global addresses in PIC
/// mode.
DenseMap<MCSymbol *, StubValueTy> GVStubs;

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

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

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

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

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

using AuthStubPairTy = std::pair<MCSymbol *, AuthStubInfo>;
typedef std::vector<AuthStubPairTy> AuthStubListTy;

AuthStubListTy getAuthGVStubList();
ExprStubListTy getAuthGVStubList() {
return getSortedExprStubs(AuthPtrStubs);
}
};

/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation
Expand Down
29 changes: 12 additions & 17 deletions llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,19 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs(
return List;
}

template <typename MachineModuleInfoTarget>
static typename MachineModuleInfoTarget::AuthStubListTy getAuthGVStubListHelper(
DenseMap<MCSymbol *, typename MachineModuleInfoTarget::AuthStubInfo>
&AuthPtrStubs) {
typename MachineModuleInfoTarget::AuthStubListTy List(AuthPtrStubs.begin(),
AuthPtrStubs.end());
using ExprStubPairTy = std::pair<MCSymbol *, const MCExpr *>;
static int SortAuthStubPair(const ExprStubPairTy *LHS,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably worth adding a test which checks that stubs are sorted. I'm OK with merging this "as is" and implementing new tests as a separate patch later.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the ordering doesn't matter as long as it's stable; I added another extern_weak as the barest of sanity checks.

const ExprStubPairTy *RHS) {
return LHS->first->getName().compare(RHS->first->getName());
}

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

AuthPtrStubs.clear();
return List;
}
array_pod_sort(List.begin(), List.end(), SortAuthStubPair);

MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() {
return getAuthGVStubListHelper<MachineModuleInfoELF>(AuthPtrStubs);
ExprStubs.clear();
return List;
}
4 changes: 4 additions & 0 deletions llvm/lib/MC/MCMachOStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
return true;
if (SegName == "__LLVM" && (SecName == "__cg_profile"))
return true;

if (SegName == "__DATA" && SecName == "__auth_ptr")
return true;

return false;
}

Expand Down
65 changes: 48 additions & 17 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,20 +848,39 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
}
}

template <typename MachineModuleInfoTarget>
static void emitAuthenticatedPointer(
MCStreamer &OutStreamer, MCSymbol *StubLabel,
const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo) {
static void emitAuthenticatedPointer(MCStreamer &OutStreamer,
MCSymbol *StubLabel,
const MCExpr *StubAuthPtrRef) {
// sym$auth_ptr$key$disc:
OutStreamer.emitLabel(StubLabel);
OutStreamer.emitValue(StubInfo.AuthPtrRef, /*size=*/8);
OutStreamer.emitValue(StubAuthPtrRef, /*size=*/8);
}

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

const Triple &TT = TM.getTargetTriple();
if (TT.isOSBinFormatMachO()) {

// Output authenticated pointers as indirect symbols, if we have any.
MachineModuleInfoMachO &MMIMacho =
MMI->getObjFileInfo<MachineModuleInfoMachO>();

auto Stubs = MMIMacho.getAuthGVStubList();

if (!Stubs.empty()) {
// Switch to the "__auth_ptr" section.
OutStreamer->switchSection(
OutContext.getMachOSection("__DATA", "__auth_ptr", MachO::S_REGULAR,
SectionKind::getMetadata()));
emitAlignment(Align(8));

for (auto &Stub : Stubs)
emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);

OutStreamer->addBlankLine();
}

// Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious
// implementation of multiple entry points). If this doesn't occur, the
Expand All @@ -882,8 +901,7 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
emitAlignment(Align(8));

for (const auto &Stub : Stubs)
emitAuthenticatedPointer<MachineModuleInfoELF>(*OutStreamer, Stub.first,
Stub.second);
emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);

OutStreamer->addBlankLine();
}
Expand Down Expand Up @@ -1676,16 +1694,29 @@ void AArch64AsmPrinter::LowerLOADauthptrstatic(const MachineInstr &MI) {
//
// Where the $auth_ptr$ symbol is the stub slot containing the signed pointer
// to symbol.
assert(TM.getTargetTriple().isOSBinFormatELF() &&
"LOADauthptrstatic is implemented only for ELF");
const auto &TLOF =
static_cast<const AArch64_ELFTargetObjectFile &>(getObjFileLowering());

assert(GAOp.getOffset() == 0 &&
"non-zero offset for $auth_ptr$ stub slots is not supported");
const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
MCSymbol *AuthPtrStubSym =
TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
MCSymbol *AuthPtrStubSym;
if (TM.getTargetTriple().isOSBinFormatELF()) {
const auto &TLOF =
static_cast<const AArch64_ELFTargetObjectFile &>(getObjFileLowering());

assert(GAOp.getOffset() == 0 &&
"non-zero offset for $auth_ptr$ stub slots is not supported");
const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
AuthPtrStubSym =
TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
} else {
assert(TM.getTargetTriple().isOSBinFormatMachO() &&
"LOADauthptrstatic is implemented only for MachO/ELF");

const auto &TLOF = static_cast<const AArch64_MachoTargetObjectFile &>(
getObjFileLowering());

assert(GAOp.getOffset() == 0 &&
"non-zero offset for $auth_ptr$ stub slots is not supported");
const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
AuthPtrStubSym =
TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
}

MachineOperand StubMOHi =
MachineOperand::CreateMCSymbol(AuthPtrStubSym, AArch64II::MO_PAGE);
Expand Down
7 changes: 3 additions & 4 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9545,8 +9545,7 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
// Load a signed pointer for symbol 'sym' from a stub slot named
// 'sym$auth_ptr$key$disc' filled by dynamic linker during relocation
// resolving. This usually lowers to adrp+ldr, but also emits an entry into
// .data with an
// @AUTH relocation. See LowerLOADauthptrstatic.
// .data with an @AUTH relocation. See LowerLOADauthptrstatic.
//
// All 3 are pseudos that are expand late to longer sequences: this lets us
// provide integrity guarantees on the to-be-signed intermediate values.
Expand Down Expand Up @@ -9599,8 +9598,8 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
"constant discriminator in ptrauth global out of range [0, 0xffff]");

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

int64_t PtrOffsetC = 0;
if (Ptr.getOpcode() == ISD::ADD) {
Expand Down
15 changes: 11 additions & 4 deletions llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,14 @@ static MCSymbol *getAuthPtrSlotSymbolHelper(
Twine("$auth_ptr$") + AArch64PACKeyIDToString(Key) + Twine('$') +
Twine(Discriminator));

typename MachineModuleInfoTarget::AuthStubInfo &StubInfo =
TargetMMI.getAuthPtrStubEntry(StubSym);
const MCExpr *&StubAuthPtrRef = TargetMMI.getAuthPtrStubEntry(StubSym);

if (StubInfo.AuthPtrRef)
if (StubAuthPtrRef)
return StubSym;

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

StubInfo.AuthPtrRef =
StubAuthPtrRef =
AArch64AuthMCExpr::create(Sym, Discriminator, Key,
/*HasAddressDiversity=*/false, Ctx);
return StubSym;
Expand All @@ -126,3 +125,11 @@ MCSymbol *AArch64_ELFTargetObjectFile::getAuthPtrSlotSymbol(
return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, ELFMMI, RawSym, Key,
Discriminator);
}

MCSymbol *AArch64_MachoTargetObjectFile::getAuthPtrSlotSymbol(
const TargetMachine &TM, MachineModuleInfo *MMI, const MCSymbol *RawSym,
AArch64PACKey::ID Key, uint16_t Discriminator) const {
auto &MachOMMI = MMI->getObjFileInfo<MachineModuleInfoMachO>();
return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, MachOMMI, RawSym,
Key, Discriminator);
}
5 changes: 5 additions & 0 deletions llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ class AArch64_MachoTargetObjectFile : public TargetLoweringObjectFileMachO {

void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV,
const TargetMachine &TM) const override;

MCSymbol *getAuthPtrSlotSymbol(const TargetMachine &TM,
MachineModuleInfo *MMI, const MCSymbol *RawSym,
AArch64PACKey::ID Key,
uint16_t Discriminator) const;
};

/// This implementation is used for AArch64 COFF targets.
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6636,8 +6636,8 @@ bool AArch64InstructionSelector::selectPtrAuthGlobalValue(
"constant discriminator in ptrauth global out of range [0, 0xffff]");

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

if (!MRI.hasOneDef(Addr))
return false;
Expand Down
Loading