Skip to content

Commit 1488fb4

Browse files
[PAC][AArch64] Lower ptrauth constants in code (llvm#96879)
This re-applies llvm#94241 after fixing buildbot failure, see https://lab.llvm.org/buildbot/#/builders/51/builds/570 According to standard, `constexpr` variables and `const` variables initialized with constant expressions can be used in lambdas w/o capturing - see https://en.cppreference.com/w/cpp/language/lambda. However, MSVC used on buildkite seems to ignore that rule and does not allow using such uncaptured variables in lambdas: we have "error C3493: 'Mask16' cannot be implicitly captured because no default capture mode has been specified" - see https://buildkite.com/llvm-project/github-pull-requests/builds/73238 Explicitly capturing such a variable, however, makes buildbot fail with "error: lambda capture 'Mask16' is not required to be captured for this use [-Werror,-Wunused-lambda-capture]" - see https://lab.llvm.org/buildbot/#/builders/51/builds/570. Fix both cases by using `0xffff` value directly instead of giving a name to it. Original PR description below. Depends on llvm#94240. Define the following pseudos for lowering ptrauth constants in code: - non-`extern_weak`: - no GOT load needed: `MOVaddrPAC` - similar to `MOVaddr`, with added PAC; - GOT load needed: `LOADgotPAC` - similar to `LOADgot`, with added PAC; - `extern_weak`: `LOADauthptrstatic` - similar to `LOADgot`, but use a special stub slot named `sym$auth_ptr$key$disc` filled by dynamic linker during relocation resolving instead of a GOT slot. --------- Co-authored-by: Ahmed Bougacha <[email protected]>
1 parent 993d238 commit 1488fb4

27 files changed

+1222
-37
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

+11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ The address of a global value.
6060
6161
%0(p0) = G_GLOBAL_VALUE @var_local
6262
63+
G_PTRAUTH_GLOBAL_VALUE
64+
^^^^^^^^^^^^^^^^^^^^^^
65+
66+
The signed address of a global value. Operands: address to be signed (pointer),
67+
key (32-bit imm), address for address discrimination (zero if not needed) and
68+
an extra discriminator (64-bit imm).
69+
70+
.. code-block:: none
71+
72+
%0:_(p0) = G_PTRAUTH_GLOBAL_VALUE %1:_(p0), s32, %2:_(p0), s64
73+
6374
G_BLOCK_ADDR
6475
^^^^^^^^^^^^
6576

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

+7
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,13 @@ class MachineIRBuilder {
886886
MachineInstrBuilder buildFConstant(const DstOp &Res, double Val);
887887
MachineInstrBuilder buildFConstant(const DstOp &Res, const APFloat &Val);
888888

889+
/// Build and insert G_PTRAUTH_GLOBAL_VALUE
890+
///
891+
/// \return a MachineInstrBuilder for the newly created instruction.
892+
MachineInstrBuilder buildConstantPtrAuth(const DstOp &Res,
893+
const ConstantPtrAuth *CPA,
894+
Register Addr, Register AddrDisc);
895+
889896
/// Build and insert \p Res = COPY Op
890897
///
891898
/// Register-to-register COPY sets \p Res to \p Op.

llvm/include/llvm/CodeGen/ISDOpcodes.h

+6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ enum NodeType {
8383
ExternalSymbol,
8484
BlockAddress,
8585

86+
/// A ptrauth constant.
87+
/// ptr, key, addr-disc, disc
88+
/// Note that the addr-disc can be a non-constant value, to allow representing
89+
/// a constant global address signed using address-diversification, in code.
90+
PtrAuthGlobalAddress,
91+
8692
/// The address of the GOT
8793
GLOBAL_OFFSET_TABLE,
8894

llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h

+20
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,20 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
6161
/// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
6262
/// for ELF targets.
6363
class MachineModuleInfoELF : public MachineModuleInfoImpl {
64+
public:
65+
struct AuthStubInfo {
66+
const MCExpr *AuthPtrRef;
67+
};
68+
69+
private:
6470
/// GVStubs - These stubs are used to materialize global addresses in PIC
6571
/// mode.
6672
DenseMap<MCSymbol *, StubValueTy> GVStubs;
6773

74+
/// AuthPtrStubs - These stubs are used to materialize signed addresses for
75+
/// extern_weak symbols.
76+
DenseMap<MCSymbol *, AuthStubInfo> AuthPtrStubs;
77+
6878
virtual void anchor(); // Out of line virtual method.
6979

7080
public:
@@ -75,9 +85,19 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
7585
return GVStubs[Sym];
7686
}
7787

88+
AuthStubInfo &getAuthPtrStubEntry(MCSymbol *Sym) {
89+
assert(Sym && "Key cannot be null");
90+
return AuthPtrStubs[Sym];
91+
}
92+
7893
/// Accessor methods to return the set of stubs in sorted order.
7994

8095
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
96+
97+
using AuthStubPairTy = std::pair<MCSymbol *, AuthStubInfo>;
98+
typedef std::vector<AuthStubPairTy> AuthStubListTy;
99+
100+
AuthStubListTy getAuthGVStubList();
81101
};
82102

83103
/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation

llvm/include/llvm/Support/TargetOpcodes.def

+3
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
294294
/// Generic reference to global value.
295295
HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE)
296296

297+
/// Generic ptrauth-signed reference to global value.
298+
HANDLE_TARGET_OPCODE(G_PTRAUTH_GLOBAL_VALUE)
299+
297300
/// Generic instruction to materialize the address of an object in the constant
298301
/// pool.
299302
HANDLE_TARGET_OPCODE(G_CONSTANT_POOL)

llvm/include/llvm/Target/GenericOpcodes.td

+6
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ def G_GLOBAL_VALUE : GenericInstruction {
110110
let hasSideEffects = false;
111111
}
112112

113+
def G_PTRAUTH_GLOBAL_VALUE : GenericInstruction {
114+
let OutOperandList = (outs type0:$dst);
115+
let InOperandList = (ins unknown:$addr, i32imm:$key, type1:$addrdisc, i64imm:$disc);
116+
let hasSideEffects = 0;
117+
}
118+
113119
def G_CONSTANT_POOL : GenericInstruction {
114120
let OutOperandList = (outs type0:$dst);
115121
let InOperandList = (ins unknown:$src);

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -3494,7 +3494,11 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
34943494
EntryBuilder->buildConstant(Reg, 0);
34953495
else if (auto GV = dyn_cast<GlobalValue>(&C))
34963496
EntryBuilder->buildGlobalValue(Reg, GV);
3497-
else if (auto CAZ = dyn_cast<ConstantAggregateZero>(&C)) {
3497+
else if (auto CPA = dyn_cast<ConstantPtrAuth>(&C)) {
3498+
Register Addr = getOrCreateVReg(*CPA->getPointer());
3499+
Register AddrDisc = getOrCreateVReg(*CPA->getAddrDiscriminator());
3500+
EntryBuilder->buildConstantPtrAuth(Reg, CPA, Addr, AddrDisc);
3501+
} else if (auto CAZ = dyn_cast<ConstantAggregateZero>(&C)) {
34983502
if (!isa<FixedVectorType>(CAZ->getType()))
34993503
return false;
35003504
// Return the scalar if it is a <1 x Ty> vector.

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,19 @@ MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
397397
return buildFConstant(Res, *CFP);
398398
}
399399

400+
MachineInstrBuilder
401+
MachineIRBuilder::buildConstantPtrAuth(const DstOp &Res,
402+
const ConstantPtrAuth *CPA,
403+
Register Addr, Register AddrDisc) {
404+
auto MIB = buildInstr(TargetOpcode::G_PTRAUTH_GLOBAL_VALUE);
405+
Res.addDefToMIB(*getMRI(), MIB);
406+
MIB.addUse(Addr);
407+
MIB.addImm(CPA->getKey()->getZExtValue());
408+
MIB.addUse(AddrDisc);
409+
MIB.addImm(CPA->getDiscriminator()->getZExtValue());
410+
return MIB;
411+
}
412+
400413
MachineInstrBuilder MachineIRBuilder::buildBrCond(const SrcOp &Tst,
401414
MachineBasicBlock &Dest) {
402415
assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");

llvm/lib/CodeGen/MachineModuleInfoImpls.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
1515
#include "llvm/ADT/DenseMap.h"
16+
#include "llvm/ADT/STLExtras.h"
1617
#include "llvm/MC/MCSymbol.h"
1718

1819
using namespace llvm;
@@ -41,3 +42,25 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs(
4142
Map.clear();
4243
return List;
4344
}
45+
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());
52+
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+
});
59+
60+
AuthPtrStubs.clear();
61+
return List;
62+
}
63+
64+
MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() {
65+
return getAuthGVStubListHelper<MachineModuleInfoELF>(AuthPtrStubs);
66+
}

llvm/lib/CodeGen/MachineVerifier.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,12 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
20662066
report("Dst operand 0 must be a pointer", MI);
20672067
break;
20682068
}
2069+
case TargetOpcode::G_PTRAUTH_GLOBAL_VALUE: {
2070+
const MachineOperand &AddrOp = MI->getOperand(1);
2071+
if (!AddrOp.isReg() || !MRI->getType(AddrOp.getReg()).isPointer())
2072+
report("addr operand must be a pointer", &AddrOp, 1);
2073+
break;
2074+
}
20692075
default:
20702076
break;
20712077
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,13 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
18021802
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
18031803
return DAG.getGlobalAddress(GV, getCurSDLoc(), VT);
18041804

1805+
if (const ConstantPtrAuth *CPA = dyn_cast<ConstantPtrAuth>(C)) {
1806+
return DAG.getNode(ISD::PtrAuthGlobalAddress, getCurSDLoc(), VT,
1807+
getValue(CPA->getPointer()), getValue(CPA->getKey()),
1808+
getValue(CPA->getAddrDiscriminator()),
1809+
getValue(CPA->getDiscriminator()));
1810+
}
1811+
18051812
if (isa<ConstantPointerNull>(C)) {
18061813
unsigned AS = V->getType()->getPointerAddressSpace();
18071814
return DAG.getConstant(0, getCurSDLoc(),

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
7575
}
7676
return "<<Unknown Node #" + utostr(getOpcode()) + ">>";
7777

78+
// clang-format off
7879
#ifndef NDEBUG
7980
case ISD::DELETED_NODE: return "<<Deleted Node!>>";
8081
#endif
@@ -126,6 +127,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
126127
case ISD::ConstantFP: return "ConstantFP";
127128
case ISD::GlobalAddress: return "GlobalAddress";
128129
case ISD::GlobalTLSAddress: return "GlobalTLSAddress";
130+
case ISD::PtrAuthGlobalAddress: return "PtrAuthGlobalAddress";
129131
case ISD::FrameIndex: return "FrameIndex";
130132
case ISD::JumpTable: return "JumpTable";
131133
case ISD::JUMP_TABLE_DEBUG_INFO:
@@ -168,8 +170,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
168170
return "OpaqueTargetConstant";
169171
return "TargetConstant";
170172

171-
// clang-format off
172-
173173
case ISD::TargetConstantFP: return "TargetConstantFP";
174174
case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
175175
case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress";

0 commit comments

Comments
 (0)