Skip to content

Commit 5872beb

Browse files
committed
Implement special address discrimination for ctors/dtors
1 parent e810621 commit 5872beb

File tree

6 files changed

+80
-5
lines changed

6 files changed

+80
-5
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2074,7 +2074,11 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
20742074
if (InitFiniAuthSchema) {
20752075
llvm::Constant *StorageAddress =
20762076
(InitFiniAuthSchema.isAddressDiscriminated()
2077-
? StorageAddress = Ctor.getAddrOfCurrentPosition(PtrTy)
2077+
? llvm::ConstantExpr::getIntToPtr(
2078+
llvm::ConstantInt::get(
2079+
IntPtrTy,
2080+
llvm::ConstantPtrAuth::AddrDiscriminator_CtorsDtors),
2081+
PtrTy)
20782082
: nullptr);
20792083
llvm::Constant *SignedCtorPtr = getConstantSignedPointer(
20802084
I.Initializer, InitFiniAuthSchema.getKey(), StorageAddress,

clang/test/CodeGen/ptrauth-init-fini.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
// SIGNED: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764), ptr null }]
1919
// SIGNED: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764), ptr null }]
2020

21-
// ADDRDISC: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr getelementptr inbounds ([1 x { i32, ptr, ptr }], ptr @llvm.global_ctors, i32 0, i32 0, i32 1)), ptr null }]
22-
// ADDRDISC: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764, ptr getelementptr inbounds ([1 x { i32, ptr, ptr }], ptr @llvm.global_dtors, i32 0, i32 0, i32 1)), ptr null }]
21+
// ADDRDISC: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), ptr null }]
22+
// ADDRDISC: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), ptr null }]
2323

2424
// UNSIGNED: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @foo, ptr null }]
2525
// UNSIGNED: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @bar, ptr null }]

llvm/include/llvm/IR/Constants.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,19 @@ class ConstantPtrAuth final : public Constant {
10561056
return !getAddrDiscriminator()->isNullValue();
10571057
}
10581058

1059+
/// A constant value for the address discriminator which has special
1060+
/// significance to ctors/dtors lowering. Regular address discrimination can't
1061+
/// be applied for them since uses of llvm.global_{c|d}tors are disallowed
1062+
/// (see Verifier::visitGlobalVariable) and we can't emit getelementptr
1063+
/// expressions referencing these special arrays.
1064+
enum { AddrDiscriminator_CtorsDtors = 1 };
1065+
1066+
/// Whether the address uses a special address discriminator.
1067+
/// These discriminators can't be used in real pointer-auth values; they
1068+
/// can only be used in "prototype" values that indicate how some real
1069+
/// schema is supposed to be produced.
1070+
bool hasSpecialAddressDiscriminator(uint64_t Value) const;
1071+
10591072
/// Check whether an authentication operation with key \p Key and (possibly
10601073
/// blended) discriminator \p Discriminator is known to be compatible with
10611074
/// this ptrauth signed pointer.

llvm/lib/IR/Constants.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,18 @@ Value *ConstantPtrAuth::handleOperandChangeImpl(Value *From, Value *ToV) {
20602060
Values, this, From, To, NumUpdated, OperandNo);
20612061
}
20622062

2063+
bool ConstantPtrAuth::hasSpecialAddressDiscriminator(uint64_t Value) const {
2064+
const auto *CastV = dyn_cast<ConstantExpr>(getAddrDiscriminator());
2065+
if (!CastV || CastV->getOpcode() != Instruction::IntToPtr)
2066+
return false;
2067+
2068+
const auto *IntVal = dyn_cast<ConstantInt>(CastV->getOperand(0));
2069+
if (!IntVal)
2070+
return false;
2071+
2072+
return IntVal->getValue() == Value;
2073+
}
2074+
20632075
bool ConstantPtrAuth::isKnownCompatibleWith(const Value *Key,
20642076
const Value *Discriminator,
20652077
const DataLayout &DL) const {

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ class AArch64AsmPrinter : public AsmPrinter {
101101

102102
void emitFunctionEntryLabel() override;
103103

104+
void emitXXStructor(const DataLayout &DL, const Constant *CV) override;
105+
104106
void LowerJumpTableDest(MCStreamer &OutStreamer, const MachineInstr &MI);
105107

106108
void LowerMOPS(MCStreamer &OutStreamer, const MachineInstr &MI);
@@ -1245,6 +1247,23 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() {
12451247
}
12461248
}
12471249

1250+
void AArch64AsmPrinter::emitXXStructor(const DataLayout &DL,
1251+
const Constant *CV) {
1252+
if (const auto *CPA = dyn_cast<ConstantPtrAuth>(CV))
1253+
if (CPA->hasAddressDiscriminator() &&
1254+
!CPA->hasSpecialAddressDiscriminator(
1255+
ConstantPtrAuth::AddrDiscriminator_CtorsDtors))
1256+
report_fatal_error(
1257+
"unexpected address discrimination value for ctors/dtors entry, only "
1258+
"'ptr inttoptr (i64 1 to ptr)' is allowed");
1259+
// If we have signed pointers in xxstructors list, they'll be lowered to @AUTH
1260+
// MCExpr's via AArch64AsmPrinter::lowerConstantPtrAuth. It does not look at
1261+
// actual address discrimination value and only checks
1262+
// hasAddressDiscriminator(), so it's OK to leave special address
1263+
// discrimination value here.
1264+
AsmPrinter::emitXXStructor(DL, CV);
1265+
}
1266+
12481267
/// Small jump tables contain an unsigned byte or half, representing the offset
12491268
/// from the lowest-addressed possible destination to the desired basic
12501269
/// block. Since all instructions are 4-byte aligned, this is further compressed

llvm/test/CodeGen/AArch64/ptrauth-init-fini.ll

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ define void @bar() {
6565
;; ^^^^ 0xD9D4: constant discriminator = 55764
6666
;; ^^ 0x80: bits 61..60 key = IA; bit 63 addr disc = true
6767

68-
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr getelementptr inbounds ([1 x { i32, ptr, ptr }], ptr @llvm.global_ctors, i32 0, i32 0, i32 1)), ptr null }]
69-
@llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764, ptr getelementptr inbounds ([1 x { i32, ptr, ptr }], ptr @llvm.global_dtors, i32 0, i32 0, i32 1)), ptr null }]
68+
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), ptr null }]
69+
@llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), ptr null }]
7070

7171
define void @foo() {
7272
ret void
@@ -75,3 +75,30 @@ define void @foo() {
7575
define void @bar() {
7676
ret void
7777
}
78+
79+
;--- err1.ll
80+
81+
; RUN: not --crash llc -mtriple aarch64-elf -mattr=+pauth -filetype=asm -o - err1.ll 2>&1 | \
82+
; RUN: FileCheck %s --check-prefix=ERR1
83+
84+
; ERR1: LLVM ERROR: unexpected address discrimination value for ctors/dtors entry, only 'ptr inttoptr (i64 1 to ptr)' is allowed
85+
86+
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr inttoptr (i64 2 to ptr)), ptr null }]
87+
88+
define void @foo() {
89+
ret void
90+
}
91+
92+
;--- err2.ll
93+
94+
; RUN: not --crash llc -mtriple aarch64-elf -mattr=+pauth -filetype=asm -o - err2.ll 2>&1 | \
95+
; RUN: FileCheck %s --check-prefix=ERR2
96+
97+
; ERR2: LLVM ERROR: unexpected address discrimination value for ctors/dtors entry, only 'ptr inttoptr (i64 1 to ptr)' is allowed
98+
99+
@g = external global ptr
100+
@llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764, ptr @g), ptr null }]
101+
102+
define void @bar() {
103+
ret void
104+
}

0 commit comments

Comments
 (0)