Skip to content

Commit 817a4fc

Browse files
committed
Refine patch a bit.
- IR: rewrite isCompatibleWith, rename to isKnownCompatibleWith - IR: comments, authenticated -> signed/ptrauth - IR: hasAddressDiversity -> hasAddressDiscriminator - LangRef.rst: typo - PointerAuth.md: whitespace - Bitcode: format
1 parent c6638c7 commit 817a4fc

File tree

6 files changed

+85
-76
lines changed

6 files changed

+85
-76
lines changed

llvm/docs/LangRef.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4769,7 +4769,7 @@ Its type is the same as the first argument. An integer constant discriminator
47694769
and an address discriminator may be optionally specified. Otherwise, they have
47704770
values ``i64 0`` and ``ptr null``.
47714771

4772-
If the address disciminator is ``null`` then the expression is equivalent to
4772+
If the address discriminator is ``null`` then the expression is equivalent to
47734773

47744774
.. code-block:: llvm
47754775

llvm/docs/PointerAuth.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ The latter are represented using a
237237
which describes an authenticated relocation producing a signed pointer.
238238

239239
```llvm
240-
ptrauth (ptr CST, i32 KEY, i64 DISC, ptr ADDRDISC)
240+
ptrauth (ptr CST, i32 KEY, i64 DISC, ptr ADDRDISC)
241241
```
242242

243243
is equivalent to:

llvm/include/llvm/IR/Constants.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ struct OperandTraits<NoCFIValue> : public FixedNumOperandTraits<NoCFIValue, 1> {
10071007

10081008
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(NoCFIValue, Value)
10091009

1010-
/// A signed pointer
1010+
/// A signed pointer, in the ptrauth sense.
10111011
///
10121012
class ConstantPtrAuth final : public Constant {
10131013
friend struct ConstantPtrAuthKeyType;
@@ -1022,7 +1022,7 @@ class ConstantPtrAuth final : public Constant {
10221022
Value *handleOperandChangeImpl(Value *From, Value *To);
10231023

10241024
public:
1025-
/// Return a pointer authenticated with the specified parameters.
1025+
/// Return a pointer signed with the specified parameters.
10261026
static ConstantPtrAuth *get(Constant *Ptr, ConstantInt *Key,
10271027
ConstantInt *Disc, Constant *AddrDisc);
10281028

@@ -1033,34 +1033,34 @@ class ConstantPtrAuth final : public Constant {
10331033
/// Transparently provide more efficient getOperand methods.
10341034
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
10351035

1036-
/// The pointer that is authenticated in this authenticated global reference.
1036+
/// The pointer that is signed in this ptrauth signed pointer.
10371037
Constant *getPointer() const { return cast<Constant>(Op<0>().get()); }
10381038

10391039
/// The Key ID, an i32 constant.
10401040
ConstantInt *getKey() const { return cast<ConstantInt>(Op<1>().get()); }
10411041

1042-
/// The discriminator.
1042+
/// The integer discriminator, an i64 constant, or 0.
10431043
ConstantInt *getDiscriminator() const {
10441044
return cast<ConstantInt>(Op<2>().get());
10451045
}
10461046

10471047
/// The address discriminator if any, or the null constant.
10481048
/// If present, this must be a value equivalent to the storage location of
1049-
/// the only user of the authenticated ptrauth global.
1049+
/// the only global-initializer user of the ptrauth signed pointer.
10501050
Constant *getAddrDiscriminator() const {
10511051
return cast<Constant>(Op<3>().get());
10521052
}
10531053

10541054
/// Whether there is any non-null address discriminator.
1055-
bool hasAddressDiversity() const {
1055+
bool hasAddressDiscriminator() const {
10561056
return !getAddrDiscriminator()->isNullValue();
10571057
}
10581058

1059-
/// Check whether an authentication operation with key \p KeyV and (possibly
1060-
/// blended) discriminator \p DiscriminatorV is compatible with this
1061-
/// authenticated global reference.
1062-
bool isCompatibleWith(const Value *Key, const Value *Discriminator,
1063-
const DataLayout &DL) const;
1059+
/// Check whether an authentication operation with key \p Key and (possibly
1060+
/// blended) discriminator \p Discriminator is known to be compatible with
1061+
/// this ptrauth signed pointer.
1062+
bool isKnownCompatibleWith(const Value *Key, const Value *Discriminator,
1063+
const DataLayout &DL) const;
10641064

10651065
/// Methods for support type inquiry through isa, cast, and dyn_cast:
10661066
static bool classof(const Value *V) {

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3646,10 +3646,10 @@ Error BitcodeReader::parseConstants() {
36463646
if (Record.size() < 4)
36473647
return error("Invalid ptrauth record");
36483648
// Ptr, Key, Disc, AddrDisc
3649-
V = BitcodeConstant::create(
3650-
Alloc, CurTy, BitcodeConstant::ConstantPtrAuthOpcode,
3651-
{(unsigned)Record[0], (unsigned)Record[1], (unsigned)Record[2],
3652-
(unsigned)Record[3]});
3649+
V = BitcodeConstant::create(Alloc, CurTy,
3650+
BitcodeConstant::ConstantPtrAuthOpcode,
3651+
{(unsigned)Record[0], (unsigned)Record[1],
3652+
(unsigned)Record[2], (unsigned)Record[3]});
36533653
break;
36543654
}
36553655
}

llvm/lib/IR/Constants.cpp

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,59 +2021,6 @@ Value *NoCFIValue::handleOperandChangeImpl(Value *From, Value *To) {
20212021
//---- ConstantPtrAuth::get() implementations.
20222022
//
20232023

2024-
static bool areEquivalentAddrDiscriminators(const Value *V1, const Value *V2,
2025-
const DataLayout &DL) {
2026-
APInt Off1(DL.getTypeSizeInBits(V1->getType()), 0);
2027-
APInt Off2(DL.getTypeSizeInBits(V2->getType()), 0);
2028-
2029-
if (auto *V1Cast = dyn_cast<PtrToIntOperator>(V1))
2030-
V1 = V1Cast->getPointerOperand();
2031-
if (auto *V2Cast = dyn_cast<PtrToIntOperator>(V2))
2032-
V2 = V2Cast->getPointerOperand();
2033-
auto *V1Base = V1->stripAndAccumulateConstantOffsets(
2034-
DL, Off1, /*AllowNonInbounds=*/true);
2035-
auto *V2Base = V2->stripAndAccumulateConstantOffsets(
2036-
DL, Off2, /*AllowNonInbounds=*/true);
2037-
return V1Base == V2Base && Off1 == Off2;
2038-
}
2039-
2040-
bool ConstantPtrAuth::isCompatibleWith(const Value *Key,
2041-
const Value *Discriminator,
2042-
const DataLayout &DL) const {
2043-
// If the keys are different, there's no chance for this to be compatible.
2044-
if (Key != getKey())
2045-
return false;
2046-
2047-
// If the discriminators are the same, this is compatible iff there is no
2048-
// address discriminator.
2049-
if (Discriminator == getDiscriminator())
2050-
return getAddrDiscriminator()->isNullValue();
2051-
2052-
// If we dynamically blend the discriminator with the address discriminator,
2053-
// this is compatible.
2054-
if (auto *DiscBlend = dyn_cast<IntrinsicInst>(Discriminator)) {
2055-
if (DiscBlend->getIntrinsicID() == Intrinsic::ptrauth_blend &&
2056-
DiscBlend->getOperand(1) == getDiscriminator() &&
2057-
areEquivalentAddrDiscriminators(DiscBlend->getOperand(0),
2058-
getAddrDiscriminator(), DL))
2059-
return true;
2060-
}
2061-
2062-
// If we don't have a non-address discriminator, we don't need a blend in
2063-
// the first place: accept the address discriminator as the discriminator.
2064-
if (getDiscriminator()->isNullValue() &&
2065-
areEquivalentAddrDiscriminators(getAddrDiscriminator(), Discriminator,
2066-
DL))
2067-
return true;
2068-
2069-
// Otherwise, we don't know.
2070-
return false;
2071-
}
2072-
2073-
ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const {
2074-
return get(Pointer, getKey(), getDiscriminator(), getAddrDiscriminator());
2075-
}
2076-
20772024
ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key,
20782025
ConstantInt *Disc, Constant *AddrDisc) {
20792026
Constant *ArgVec[] = {Ptr, Key, Disc, AddrDisc};
@@ -2082,6 +2029,10 @@ ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key,
20822029
return pImpl->ConstantPtrAuths.getOrCreate(Ptr->getType(), MapKey);
20832030
}
20842031

2032+
ConstantPtrAuth *ConstantPtrAuth::getWithSameSchema(Constant *Pointer) const {
2033+
return get(Pointer, getKey(), getDiscriminator(), getAddrDiscriminator());
2034+
}
2035+
20852036
ConstantPtrAuth::ConstantPtrAuth(Constant *Ptr, ConstantInt *Key,
20862037
ConstantInt *Disc, Constant *AddrDisc)
20872038
: Constant(Ptr->getType(), Value::ConstantPtrAuthVal, &Op<0>(), 4) {
@@ -2125,6 +2076,66 @@ Value *ConstantPtrAuth::handleOperandChangeImpl(Value *From, Value *ToV) {
21252076
Values, this, From, To, NumUpdated, OperandNo);
21262077
}
21272078

2079+
bool ConstantPtrAuth::isKnownCompatibleWith(const Value *Key,
2080+
const Value *Discriminator,
2081+
const DataLayout &DL) const {
2082+
// If the keys are different, there's no chance for this to be compatible.
2083+
if (getKey() != Key)
2084+
return false;
2085+
2086+
// We can have 3 kinds of discriminators:
2087+
// - simple, integer-only: `i64 x, ptr null` vs. `i64 x`
2088+
// - address-only: `i64 0, ptr p` vs. `ptr p`
2089+
// - blended address/integer: `i64 x, ptr p` vs. `@llvm.ptrauth.blend(p, x)`
2090+
2091+
// If this constant has a simple discriminator (integer, no address), easy:
2092+
// it's compatible iff the provided full discriminator is also a simple
2093+
// discriminator, identical to our integer discriminator.
2094+
if (!hasAddressDiscriminator())
2095+
return getDiscriminator() == Discriminator;
2096+
2097+
// Otherwise, we can isolate address and integer discriminator components.
2098+
const Value *AddrDiscriminator = nullptr;
2099+
2100+
// This constant may or may not have an integer discriminator (instead of 0).
2101+
if (!getDiscriminator()->isNullValue()) {
2102+
// If it does, there's an implicit blend. We need to have a matching blend
2103+
// intrinsic in the provided full discriminator.
2104+
if (!match(Discriminator,
2105+
m_Intrinsic<Intrinsic::ptrauth_blend>(
2106+
m_Value(AddrDiscriminator), m_Specific(getDiscriminator()))))
2107+
return false;
2108+
} else {
2109+
// Otherwise, interpret the provided full discriminator as address-only.
2110+
AddrDiscriminator = Discriminator;
2111+
}
2112+
2113+
// Either way, we can now focus on comparing the address discriminators.
2114+
2115+
// Discriminators are i64, so the provided addr disc may be a ptrtoint.
2116+
if (auto *Cast = dyn_cast<PtrToIntOperator>(AddrDiscriminator))
2117+
AddrDiscriminator = Cast->getPointerOperand();
2118+
2119+
// Beyond that, we're only interested in compatible pointers.
2120+
if (getAddrDiscriminator()->getType() != AddrDiscriminator->getType())
2121+
return false;
2122+
2123+
// These are often the same constant GEP, making them trivially equivalent.
2124+
if (getAddrDiscriminator() == AddrDiscriminator)
2125+
return true;
2126+
2127+
// Finally, they may be equivalent base+offset expressions.
2128+
APInt Off1(DL.getIndexTypeSizeInBits(getAddrDiscriminator()->getType()), 0);
2129+
auto *Base1 = getAddrDiscriminator()->stripAndAccumulateConstantOffsets(
2130+
DL, Off1, /*AllowNonInbounds=*/true);
2131+
2132+
APInt Off2(DL.getIndexTypeSizeInBits(AddrDiscriminator->getType()), 0);
2133+
auto *Base2 = AddrDiscriminator->stripAndAccumulateConstantOffsets(
2134+
DL, Off2, /*AllowNonInbounds=*/true);
2135+
2136+
return Base1 == Base2 && Off1 == Off2;
2137+
}
2138+
21282139
//---- ConstantExpr::get() implementations.
21292140
//
21302141

llvm/test/Assembler/ptrauth-const.ll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,14 @@
1111
; CHECK: @intdisc = global ptr ptrauth (ptr @var, i32 0, i64 -1)
1212
@intdisc = global ptr ptrauth (ptr @var, i32 0, i64 -1)
1313

14-
@addrdisc_storage = global ptr null
15-
; CHECK: @addrdisc = global ptr ptrauth (ptr @var, i32 2, i64 1234, ptr @addrdisc_storage)
16-
@addrdisc = global ptr ptrauth (ptr @var, i32 2, i64 1234, ptr @addrdisc_storage)
14+
; CHECK: @addrdisc = global ptr ptrauth (ptr @var, i32 2, i64 1234, ptr @addrdisc)
15+
@addrdisc = global ptr ptrauth (ptr @var, i32 2, i64 1234, ptr @addrdisc)
1716

1817

1918
@var1 = addrspace(1) global i32 0
2019

2120
; CHECK: @addrspace = global ptr addrspace(1) ptrauth (ptr addrspace(1) @var1, i32 0)
2221
@addrspace = global ptr addrspace(1) ptrauth (ptr addrspace(1) @var1, i32 0)
2322

24-
@addrspace_addrdisc_storage = addrspace(2) global ptr addrspace(1) null
25-
; CHECK: @addrspace_addrdisc = global ptr addrspace(1) ptrauth (ptr addrspace(1) @var1, i32 2, i64 1234, ptr addrspace(2) @addrspace_addrdisc_storage)
26-
@addrspace_addrdisc = global ptr addrspace(1) ptrauth (ptr addrspace(1) @var1, i32 2, i64 1234, ptr addrspace(2) @addrspace_addrdisc_storage)
23+
; CHECK: @addrspace_addrdisc = addrspace(2) global ptr addrspace(1) ptrauth (ptr addrspace(1) @var1, i32 2, i64 1234, ptr addrspace(2) @addrspace_addrdisc)
24+
@addrspace_addrdisc = addrspace(2) global ptr addrspace(1) ptrauth (ptr addrspace(1) @var1, i32 2, i64 1234, ptr addrspace(2) @addrspace_addrdisc)

0 commit comments

Comments
 (0)