Skip to content

Commit c0b1c62

Browse files
author
vporpo
authored
[SandboxIR] Implement ConstantPtrAuth (#109315)
This patch implements sandboxir::ConstantPtrAuth mirroring llvm::ConstantPtrAuth
1 parent b014265 commit c0b1c62

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ class GlobalIFunc;
134134
class GlobalVariable;
135135
class GlobalAlias;
136136
class NoCFIValue;
137+
class ConstantPtrAuth;
137138
class Context;
138139
class Function;
139140
class Instruction;
@@ -342,6 +343,7 @@ class Value {
342343
friend class GlobalVariable; // For `Val`.
343344
friend class GlobalAlias; // For `Val`.
344345
friend class NoCFIValue; // For `Val`.
346+
friend class ConstantPtrAuth; // For `Val`.
345347

346348
/// All values point to the context.
347349
Context &Ctx;
@@ -1603,6 +1605,62 @@ class NoCFIValue final : public Constant {
16031605
#endif
16041606
};
16051607

1608+
class ConstantPtrAuth final : public Constant {
1609+
ConstantPtrAuth(llvm::ConstantPtrAuth *C, Context &Ctx)
1610+
: Constant(ClassID::ConstantPtrAuth, C, Ctx) {}
1611+
friend class Context; // For constructor.
1612+
1613+
public:
1614+
/// Return a pointer signed with the specified parameters.
1615+
static ConstantPtrAuth *get(Constant *Ptr, ConstantInt *Key,
1616+
ConstantInt *Disc, Constant *AddrDisc);
1617+
/// The pointer that is signed in this ptrauth signed pointer.
1618+
Constant *getPointer() const;
1619+
1620+
/// The Key ID, an i32 constant.
1621+
ConstantInt *getKey() const;
1622+
1623+
/// The integer discriminator, an i64 constant, or 0.
1624+
ConstantInt *getDiscriminator() const;
1625+
1626+
/// The address discriminator if any, or the null constant.
1627+
/// If present, this must be a value equivalent to the storage location of
1628+
/// the only global-initializer user of the ptrauth signed pointer.
1629+
Constant *getAddrDiscriminator() const;
1630+
1631+
/// Whether there is any non-null address discriminator.
1632+
bool hasAddressDiscriminator() const {
1633+
return cast<llvm::ConstantPtrAuth>(Val)->hasAddressDiscriminator();
1634+
}
1635+
1636+
/// Whether the address uses a special address discriminator.
1637+
/// These discriminators can't be used in real pointer-auth values; they
1638+
/// can only be used in "prototype" values that indicate how some real
1639+
/// schema is supposed to be produced.
1640+
bool hasSpecialAddressDiscriminator(uint64_t Value) const {
1641+
return cast<llvm::ConstantPtrAuth>(Val)->hasSpecialAddressDiscriminator(
1642+
Value);
1643+
}
1644+
1645+
/// Check whether an authentication operation with key \p Key and (possibly
1646+
/// blended) discriminator \p Discriminator is known to be compatible with
1647+
/// this ptrauth signed pointer.
1648+
bool isKnownCompatibleWith(const Value *Key, const Value *Discriminator,
1649+
const DataLayout &DL) const {
1650+
return cast<llvm::ConstantPtrAuth>(Val)->isKnownCompatibleWith(
1651+
Key->Val, Discriminator->Val, DL);
1652+
}
1653+
1654+
/// Produce a new ptrauth expression signing the given value using
1655+
/// the same schema as is stored in one.
1656+
ConstantPtrAuth *getWithSameSchema(Constant *Pointer) const;
1657+
1658+
/// For isa/dyn_cast.
1659+
static bool classof(const sandboxir::Value *From) {
1660+
return From->getSubclassID() == ClassID::ConstantPtrAuth;
1661+
}
1662+
};
1663+
16061664
class BlockAddress final : public Constant {
16071665
BlockAddress(llvm::BlockAddress *C, Context &Ctx)
16081666
: Constant(ClassID::BlockAddress, C, Ctx) {}

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ DEF_CONST(GlobalIFunc, GlobalIFunc)
3939
DEF_CONST(GlobalAlias, GlobalAlias)
4040
DEF_CONST(BlockAddress, BlockAddress)
4141
DEF_CONST(NoCFIValue, NoCFIValue)
42+
DEF_CONST(ConstantPtrAuth, ConstantPtrAuth)
4243
DEF_CONST(DSOLocalEquivalent, DSOLocalEquivalent)
4344
DEF_CONST(ConstantTokenNone, ConstantTokenNone)
4445

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,6 +2640,40 @@ PointerType *NoCFIValue::getType() const {
26402640
return cast<PointerType>(Ctx.getType(cast<llvm::NoCFIValue>(Val)->getType()));
26412641
}
26422642

2643+
ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key,
2644+
ConstantInt *Disc, Constant *AddrDisc) {
2645+
auto *LLVMC = llvm::ConstantPtrAuth::get(
2646+
cast<llvm::Constant>(Ptr->Val), cast<llvm::ConstantInt>(Key->Val),
2647+
cast<llvm::ConstantInt>(Disc->Val), cast<llvm::Constant>(AddrDisc->Val));
2648+
return cast<ConstantPtrAuth>(Ptr->getContext().getOrCreateConstant(LLVMC));
2649+
}
2650+
2651+
Constant *ConstantPtrAuth::getPointer() const {
2652+
return Ctx.getOrCreateConstant(
2653+
cast<llvm::ConstantPtrAuth>(Val)->getPointer());
2654+
}
2655+
2656+
ConstantInt *ConstantPtrAuth::getKey() const {
2657+
return cast<ConstantInt>(
2658+
Ctx.getOrCreateConstant(cast<llvm::ConstantPtrAuth>(Val)->getKey()));
2659+
}
2660+
2661+
ConstantInt *ConstantPtrAuth::getDiscriminator() const {
2662+
return cast<ConstantInt>(Ctx.getOrCreateConstant(
2663+
cast<llvm::ConstantPtrAuth>(Val)->getDiscriminator()));
2664+
}
2665+
2666+
Constant *ConstantPtrAuth::getAddrDiscriminator() const {
2667+
return Ctx.getOrCreateConstant(
2668+
cast<llvm::ConstantPtrAuth>(Val)->getAddrDiscriminator());
2669+
}
2670+
2671+
ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const {
2672+
auto *LLVMC = cast<llvm::ConstantPtrAuth>(Val)->getWithSameSchema(
2673+
cast<llvm::Constant>(Pointer->Val));
2674+
return cast<ConstantPtrAuth>(Ctx.getOrCreateConstant(LLVMC));
2675+
}
2676+
26432677
BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
26442678
auto *LLVMC = llvm::BlockAddress::get(cast<llvm::Function>(F->Val),
26452679
cast<llvm::BasicBlock>(BB->Val));
@@ -2850,6 +2884,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
28502884
It->second = std::unique_ptr<NoCFIValue>(
28512885
new NoCFIValue(cast<llvm::NoCFIValue>(C), *this));
28522886
break;
2887+
case llvm::Value::ConstantPtrAuthVal:
2888+
It->second = std::unique_ptr<ConstantPtrAuth>(
2889+
new ConstantPtrAuth(cast<llvm::ConstantPtrAuth>(C), *this));
2890+
break;
28532891
default:
28542892
It->second = std::unique_ptr<Constant>(new Constant(C, *this));
28552893
break;

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,43 @@ define void @foo() {
11421142
EXPECT_EQ(NoCFI->getType(), F.getType());
11431143
}
11441144

1145+
TEST_F(SandboxIRTest, ConstantPtrAuth) {
1146+
parseIR(C, R"IR(
1147+
define ptr @foo() {
1148+
ret ptr ptrauth (ptr @foo, i32 2, i64 1234)
1149+
}
1150+
)IR");
1151+
Function &LLVMF = *M->getFunction("foo");
1152+
auto *LLVMBB = &*LLVMF.begin();
1153+
auto *LLVMRet = cast<llvm::ReturnInst>(&*LLVMBB->begin());
1154+
auto *LLVMPtrAuth = cast<llvm::ConstantPtrAuth>(LLVMRet->getReturnValue());
1155+
sandboxir::Context Ctx(C);
1156+
1157+
auto &F = *Ctx.createFunction(&LLVMF);
1158+
auto *BB = &*F.begin();
1159+
auto It = BB->begin();
1160+
auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
1161+
// Check classof(), creation.
1162+
auto *PtrAuth = cast<sandboxir::ConstantPtrAuth>(Ret->getReturnValue());
1163+
// Check get(), getKey(), getDiscriminator(), getAddrDiscriminator().
1164+
auto *NewPtrAuth = sandboxir::ConstantPtrAuth::get(
1165+
&F, PtrAuth->getKey(), PtrAuth->getDiscriminator(),
1166+
PtrAuth->getAddrDiscriminator());
1167+
EXPECT_EQ(NewPtrAuth, PtrAuth);
1168+
// Check hasAddressDiscriminator().
1169+
EXPECT_EQ(PtrAuth->hasAddressDiscriminator(),
1170+
LLVMPtrAuth->hasAddressDiscriminator());
1171+
// Check hasSpecialAddressDiscriminator().
1172+
EXPECT_EQ(PtrAuth->hasSpecialAddressDiscriminator(0u),
1173+
LLVMPtrAuth->hasSpecialAddressDiscriminator(0u));
1174+
// Check isKnownCompatibleWith().
1175+
const DataLayout &DL = M->getDataLayout();
1176+
EXPECT_TRUE(PtrAuth->isKnownCompatibleWith(PtrAuth->getKey(),
1177+
PtrAuth->getDiscriminator(), DL));
1178+
// Check getWithSameSchema().
1179+
EXPECT_EQ(PtrAuth->getWithSameSchema(&F), PtrAuth);
1180+
}
1181+
11451182
TEST_F(SandboxIRTest, BlockAddress) {
11461183
parseIR(C, R"IR(
11471184
define void @foo(ptr %ptr) {

0 commit comments

Comments
 (0)