Skip to content

Commit

Permalink
[PAC][AArch64] Lower ptrauth constants in code (#96879)
Browse files Browse the repository at this point in the history
This re-applies #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 #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 <ahmed@bougacha.org>
  • Loading branch information
kovdan01 and ahmedbougacha committed Jun 28, 2024
1 parent 993d238 commit 1488fb4
Show file tree
Hide file tree
Showing 27 changed files with 1,222 additions and 37 deletions.
11 changes: 11 additions & 0 deletions llvm/docs/GlobalISel/GenericOpcode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ The address of a global value.
%0(p0) = G_GLOBAL_VALUE @var_local
G_PTRAUTH_GLOBAL_VALUE
^^^^^^^^^^^^^^^^^^^^^^

The signed address of a global value. Operands: address to be signed (pointer),
key (32-bit imm), address for address discrimination (zero if not needed) and
an extra discriminator (64-bit imm).

.. code-block:: none
%0:_(p0) = G_PTRAUTH_GLOBAL_VALUE %1:_(p0), s32, %2:_(p0), s64
G_BLOCK_ADDR
^^^^^^^^^^^^

Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,13 @@ class MachineIRBuilder {
MachineInstrBuilder buildFConstant(const DstOp &Res, double Val);
MachineInstrBuilder buildFConstant(const DstOp &Res, const APFloat &Val);

/// Build and insert G_PTRAUTH_GLOBAL_VALUE
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildConstantPtrAuth(const DstOp &Res,
const ConstantPtrAuth *CPA,
Register Addr, Register AddrDisc);

/// Build and insert \p Res = COPY Op
///
/// Register-to-register COPY sets \p Res to \p Op.
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/CodeGen/ISDOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ enum NodeType {
ExternalSymbol,
BlockAddress,

/// A ptrauth constant.
/// ptr, key, addr-disc, disc
/// Note that the addr-disc can be a non-constant value, to allow representing
/// a constant global address signed using address-diversification, in code.
PtrAuthGlobalAddress,

/// The address of the GOT
GLOBAL_OFFSET_TABLE,

Expand Down
20 changes: 20 additions & 0 deletions llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,20 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
/// 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;

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

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

AuthStubInfo &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); }

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

AuthStubListTy getAuthGVStubList();
};

/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
/// Generic reference to global value.
HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE)

/// Generic ptrauth-signed reference to global value.
HANDLE_TARGET_OPCODE(G_PTRAUTH_GLOBAL_VALUE)

/// Generic instruction to materialize the address of an object in the constant
/// pool.
HANDLE_TARGET_OPCODE(G_CONSTANT_POOL)
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ def G_GLOBAL_VALUE : GenericInstruction {
let hasSideEffects = false;
}

def G_PTRAUTH_GLOBAL_VALUE : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins unknown:$addr, i32imm:$key, type1:$addrdisc, i64imm:$disc);
let hasSideEffects = 0;
}

def G_CONSTANT_POOL : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins unknown:$src);
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3494,7 +3494,11 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
EntryBuilder->buildConstant(Reg, 0);
else if (auto GV = dyn_cast<GlobalValue>(&C))
EntryBuilder->buildGlobalValue(Reg, GV);
else if (auto CAZ = dyn_cast<ConstantAggregateZero>(&C)) {
else if (auto CPA = dyn_cast<ConstantPtrAuth>(&C)) {
Register Addr = getOrCreateVReg(*CPA->getPointer());
Register AddrDisc = getOrCreateVReg(*CPA->getAddrDiscriminator());
EntryBuilder->buildConstantPtrAuth(Reg, CPA, Addr, AddrDisc);
} else if (auto CAZ = dyn_cast<ConstantAggregateZero>(&C)) {
if (!isa<FixedVectorType>(CAZ->getType()))
return false;
// Return the scalar if it is a <1 x Ty> vector.
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,19 @@ MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
return buildFConstant(Res, *CFP);
}

MachineInstrBuilder
MachineIRBuilder::buildConstantPtrAuth(const DstOp &Res,
const ConstantPtrAuth *CPA,
Register Addr, Register AddrDisc) {
auto MIB = buildInstr(TargetOpcode::G_PTRAUTH_GLOBAL_VALUE);
Res.addDefToMIB(*getMRI(), MIB);
MIB.addUse(Addr);
MIB.addImm(CPA->getKey()->getZExtValue());
MIB.addUse(AddrDisc);
MIB.addImm(CPA->getDiscriminator()->getZExtValue());
return MIB;
}

MachineInstrBuilder MachineIRBuilder::buildBrCond(const SrcOp &Tst,
MachineBasicBlock &Dest) {
assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");
Expand Down
23 changes: 23 additions & 0 deletions llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCSymbol.h"

using namespace llvm;
Expand Down Expand Up @@ -41,3 +42,25 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs(
Map.clear();
return List;
}

template <typename MachineModuleInfoTarget>
static typename MachineModuleInfoTarget::AuthStubListTy getAuthGVStubListHelper(
DenseMap<MCSymbol *, typename MachineModuleInfoTarget::AuthStubInfo>
&AuthPtrStubs) {
typename MachineModuleInfoTarget::AuthStubListTy List(AuthPtrStubs.begin(),
AuthPtrStubs.end());

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();
});

AuthPtrStubs.clear();
return List;
}

MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() {
return getAuthGVStubListHelper<MachineModuleInfoELF>(AuthPtrStubs);
}
6 changes: 6 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2066,6 +2066,12 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
report("Dst operand 0 must be a pointer", MI);
break;
}
case TargetOpcode::G_PTRAUTH_GLOBAL_VALUE: {
const MachineOperand &AddrOp = MI->getOperand(1);
if (!AddrOp.isReg() || !MRI->getType(AddrOp.getReg()).isPointer())
report("addr operand must be a pointer", &AddrOp, 1);
break;
}
default:
break;
}
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,13 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
return DAG.getGlobalAddress(GV, getCurSDLoc(), VT);

if (const ConstantPtrAuth *CPA = dyn_cast<ConstantPtrAuth>(C)) {
return DAG.getNode(ISD::PtrAuthGlobalAddress, getCurSDLoc(), VT,
getValue(CPA->getPointer()), getValue(CPA->getKey()),
getValue(CPA->getAddrDiscriminator()),
getValue(CPA->getDiscriminator()));
}

if (isa<ConstantPointerNull>(C)) {
unsigned AS = V->getType()->getPointerAddressSpace();
return DAG.getConstant(0, getCurSDLoc(),
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
}
return "<<Unknown Node #" + utostr(getOpcode()) + ">>";

// clang-format off
#ifndef NDEBUG
case ISD::DELETED_NODE: return "<<Deleted Node!>>";
#endif
Expand Down Expand Up @@ -126,6 +127,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::ConstantFP: return "ConstantFP";
case ISD::GlobalAddress: return "GlobalAddress";
case ISD::GlobalTLSAddress: return "GlobalTLSAddress";
case ISD::PtrAuthGlobalAddress: return "PtrAuthGlobalAddress";
case ISD::FrameIndex: return "FrameIndex";
case ISD::JumpTable: return "JumpTable";
case ISD::JUMP_TABLE_DEBUG_INFO:
Expand Down Expand Up @@ -168,8 +170,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
return "OpaqueTargetConstant";
return "TargetConstant";

// clang-format off

case ISD::TargetConstantFP: return "TargetConstantFP";
case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress";
Expand Down
Loading

0 comments on commit 1488fb4

Please sign in to comment.