Skip to content

Commit 8819581

Browse files
Merge pull request #63788 from aschwaighofer/sign_relative_pwt
Sign relative protocol witness tables
2 parents 598ac05 + 1fa68ff commit 8819581

File tree

7 files changed

+111
-12
lines changed

7 files changed

+111
-12
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,9 @@ namespace SpecialPointerAuthDiscriminators {
14421442

14431443
/// C type StoreExtraInhabitantTag function descriminator
14441444
const uint16_t StoreExtraInhabitantTagFunction = 0x9bf6; // = 39926
1445+
1446+
// Relative protocol witness table descriminator
1447+
const uint16_t RelativeProtocolWitnessTable = 0xb830; // = 47152
14451448
}
14461449

14471450
/// The number of arguments that will be passed directly to a generic

include/swift/AST/IRGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
204204

205205
/// C type StoreExtraInhabitantTag function descriminator.
206206
PointerAuthSchema StoreExtraInhabitantTagFunction;
207+
208+
/// Relative protocol witness table descriminator.
209+
PointerAuthSchema RelativeProtocolWitnessTable;
207210
};
208211

209212
enum class JITDebugArtifact : unsigned {

lib/IRGen/GenProto.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,17 @@ WitnessIndex ProtocolInfo::getAssociatedTypeIndex(
11921192
llvm_unreachable("didn't find entry for associated type");
11931193
}
11941194

1195+
static llvm::Constant *
1196+
getConstantSignedRelativeProtocolWitnessTable(IRGenModule &IGM,
1197+
llvm::Value *table) {
1198+
auto constantTable = cast<llvm::Constant>(table);
1199+
auto &schema = IGM.getOptions().PointerAuth.RelativeProtocolWitnessTable;
1200+
constantTable =
1201+
IGM.getConstantSignedPointer(constantTable, schema, PointerAuthEntity(),
1202+
/*storageAddress*/ nullptr);
1203+
return constantTable;
1204+
}
1205+
11951206
namespace {
11961207

11971208
/// Conformance info for a witness table that can be directly generated.
@@ -1694,6 +1705,8 @@ void WitnessTableBuilderBase::defineAssociatedTypeWitnessTableAccessFunction(
16941705
// If we can emit a constant table, do so.
16951706
if (auto constantTable =
16961707
conformanceI->tryGetConstantTable(IGM, associatedType)) {
1708+
constantTable =
1709+
getConstantSignedRelativeProtocolWitnessTable(IGM, constantTable);
16971710
IGF.Builder.CreateRet(constantTable);
16981711
return;
16991712
}
@@ -1890,6 +1903,7 @@ llvm::Function *FragileWitnessTableBuilder::buildInstantiationFunction() {
18901903
// Ask the ConformanceInfo to emit the wtable.
18911904
llvm::Value *baseWTable =
18921905
base.second->getTable(IGF, &metadata);
1906+
18931907
baseWTable = IGF.Builder.CreateBitCast(baseWTable, IGM.Int8PtrTy);
18941908

18951909
// Store that to the appropriate slot in the new witness table.
@@ -2626,6 +2640,11 @@ llvm::Value *IRGenFunction::optionallyLoadFromConditionalProtocolWitnessTable(
26262640
auto *phi = Builder.CreatePHI(wtable->getType(), 2);
26272641
phi->addIncoming(wtable, origBB);
26282642
phi->addIncoming(wtableDeref, isCondBB);
2643+
if (auto &schema = getOptions().PointerAuth.RelativeProtocolWitnessTable) {
2644+
auto info = PointerAuthInfo::emit(*this, schema, nullptr,
2645+
PointerAuthEntity());
2646+
return emitPointerAuthAuth(*this, phi, info);
2647+
}
26292648
return phi;
26302649
}
26312650

@@ -2660,11 +2679,25 @@ llvm::Value *irgen::loadParentProtocolWitnessTable(IRGenFunction &IGF,
26602679
Builder.CreateBr(endBB);
26612680

26622681
Builder.emitBlock(isNotCondBB);
2682+
if (auto &schema = IGF.getOptions().PointerAuth.RelativeProtocolWitnessTable) {
2683+
auto info = PointerAuthInfo::emit(IGF, schema, nullptr,
2684+
PointerAuthEntity());
2685+
wtable = emitPointerAuthAuth(IGF, wtable, info);
2686+
}
26632687
auto baseWTable2 =
26642688
emitInvariantLoadOfOpaqueWitness(IGF,/*isProtocolWitness*/true, wtable,
26652689
index);
26662690
baseWTable2 = IGF.Builder.CreateBitCast(baseWTable2,
26672691
IGF.IGM.WitnessTablePtrTy);
2692+
if (auto &schema = IGF.getOptions().PointerAuth.RelativeProtocolWitnessTable) {
2693+
auto info = PointerAuthInfo::emit(IGF, schema, nullptr,
2694+
PointerAuthEntity());
2695+
baseWTable2 = emitPointerAuthSign(IGF, baseWTable2, info);
2696+
2697+
baseWTable2 = IGF.Builder.CreateBitCast(baseWTable2,
2698+
IGF.IGM.WitnessTablePtrTy);
2699+
}
2700+
26682701
Builder.CreateBr(endBB);
26692702

26702703
Builder.emitBlock(endBB);
@@ -3268,6 +3301,8 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
32683301

32693302
auto &conformanceI = IGF.IGM.getConformanceInfo(proto, concreteConformance);
32703303
wtable = conformanceI.getTable(IGF, srcMetadataCache);
3304+
if (isa<llvm::Constant>(wtable))
3305+
wtable = getConstantSignedRelativeProtocolWitnessTable(IGF.IGM, wtable);
32713306

32723307
IGF.setScopedLocalTypeData(srcType, cacheKind, wtable);
32733308
return wtable;

lib/IRGen/IRGen.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,8 @@ bool swift::compileAndWriteLLVM(llvm::Module *module,
869869
}
870870

871871
static void setPointerAuthOptions(PointerAuthOptions &opts,
872-
const clang::PointerAuthOptions &clangOpts){
872+
const clang::PointerAuthOptions &clangOpts,
873+
const IRGenOptions &irgenOpts) {
873874
// Intentionally do a slice-assignment to copy over the clang options.
874875
static_cast<clang::PointerAuthOptions&>(opts) = clangOpts;
875876

@@ -1011,6 +1012,11 @@ static void setPointerAuthOptions(PointerAuthOptions &opts,
10111012
opts.StoreExtraInhabitantTagFunction = PointerAuthSchema(
10121013
codeKey, /*address*/ false, Discrimination::Constant,
10131014
SpecialPointerAuthDiscriminators::StoreExtraInhabitantTagFunction);
1015+
1016+
if (irgenOpts.UseRelativeProtocolWitnessTables)
1017+
opts.RelativeProtocolWitnessTable = PointerAuthSchema(
1018+
dataKey, /*address*/ false, Discrimination::Constant,
1019+
SpecialPointerAuthDiscriminators::RelativeProtocolWitnessTable);
10141020
}
10151021

10161022
std::unique_ptr<llvm::TargetMachine>
@@ -1045,7 +1051,7 @@ swift::createTargetMachine(const IRGenOptions &Opts, ASTContext &Ctx) {
10451051
// after the module loaders are set up, and where these options are
10461052
// formally not const.
10471053
setPointerAuthOptions(const_cast<IRGenOptions &>(Opts).PointerAuth,
1048-
clangInstance.getCodeGenOpts().PointerAuth);
1054+
clangInstance.getCodeGenOpts().PointerAuth, Opts);
10491055
}
10501056
}
10511057

stdlib/public/runtime/Metadata.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5527,14 +5527,30 @@ instantiateRelativeWitnessTable(const Metadata *Type,
55275527
// Advance the address point; the private storage area is accessed via
55285528
// negative offsets.
55295529
auto table = fullTable + privateSizeInWords;
5530-
5530+
#if SWIFT_PTRAUTH
5531+
table[0] = ptrauth_sign_unauthenticated(
5532+
(void*)pattern,
5533+
ptrauth_key_process_independent_data,
5534+
SpecialPointerAuthDiscriminators::RelativeProtocolWitnessTable);
5535+
#else
55315536
table[0] = (void*)pattern;
5537+
#endif
5538+
55325539
assert(1 == WitnessTableFirstRequirementOffset);
55335540

55345541
// Fill in the base protocols of the requirements from the pattern.
55355542
for (size_t i = 0, e = numBaseProtocols; i < e; ++i) {
55365543
size_t index = i + WitnessTableFirstRequirementOffset;
5544+
#if SWIFT_PTRAUTH
5545+
auto rawValue = ((RelativeBaseWitness const *)pattern)[index].get();
5546+
table[index] = (rawValue == nullptr) ? rawValue :
5547+
ptrauth_sign_unauthenticated(
5548+
rawValue,
5549+
ptrauth_key_process_independent_data,
5550+
SpecialPointerAuthDiscriminators::RelativeProtocolWitnessTable);
5551+
#else
55375552
table[index] = ((RelativeBaseWitness const *)pattern)[index].get();
5553+
#endif
55385554
}
55395555

55405556
// Copy any instantiation arguments that correspond to conditional
@@ -5627,6 +5643,13 @@ swift::swift_getWitnessTableRelative(const ProtocolConformanceDescriptor *confor
56275643
assert(!conformance->isSynthesizedNonUnique());
56285644
auto pattern = conformance->getWitnessTablePattern();
56295645
auto table = uniqueForeignWitnessTableRef(pattern);
5646+
5647+
#if SWIFT_STDLIB_USE_RELATIVE_PROTOCOL_WITNESS_TABLES && SWIFT_PTRAUTH
5648+
table = ptrauth_sign_unauthenticated(table,
5649+
ptrauth_key_process_independent_data,
5650+
SpecialPointerAuthDiscriminators::RelativeProtocolWitnessTable);
5651+
#endif
5652+
56305653
return reinterpret_cast<const RelativeWitnessTable*>(table);
56315654
}
56325655

@@ -5855,8 +5878,14 @@ RelativeWitnessTable *swift::lookThroughOptionalConditionalWitnessTable(
58555878
if (conditional_wtable & 0x1) {
58565879
conditional_wtable = conditional_wtable & ~(uintptr_t)(0x1);
58575880
conditional_wtable = (uintptr_t)*(void**)conditional_wtable;
5881+
58585882
}
58595883
auto table = (RelativeWitnessTable*)conditional_wtable;
5884+
#if SWIFT_PTRAUTH
5885+
table = swift_auth_data_non_address(
5886+
table,
5887+
SpecialPointerAuthDiscriminators::RelativeProtocolWitnessTable);
5888+
#endif
58605889
return table;
58615890
}
58625891

@@ -6169,7 +6198,7 @@ static const RelativeWitnessTable *swift_getAssociatedConformanceWitnessRelative
61696198

61706199
auto assocWitnessTable = witnessFn(assocType, conformingType, origWTable);
61716200

6172-
// The access function returns an unsigned pointer for now.
6201+
// The access function returns an signed pointer.
61736202
return assocWitnessTable;
61746203
}
61756204

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,7 @@ swift_conformsToProtocolImpl(const Metadata *const type,
11631163
std::tie(table, hasUninstantiatedSuperclass) =
11641164
swift_conformsToProtocolMaybeInstantiateSuperclasses(
11651165
type, protocol, true /*instantiateSuperclassMetadata*/);
1166+
11661167
return table;
11671168
}
11681169

test/IRGen/relative_protocol_witness_table.swift

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
// RUN: %target-swift-frontend -enable-relative-protocol-witness-tables -module-name A -primary-file %s -emit-ir | %FileCheck %s
1+
// RUN: %target-swift-frontend -enable-relative-protocol-witness-tables -module-name A -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK-%target-cpu --check-prefix=CHECK
22

3-
// REQUIRES: CPU=x86_64 || CPU=arm64
4-
// UNSUPPORTED: CPU=arm64e
3+
// REQUIRES: CPU=x86_64 || CPU=arm64 || CPU=arm64e
54

65
func testVWT<T>(_ t: T) {
76
var local = t
@@ -216,8 +215,15 @@ func instantiate_conditional_conformance_2nd<T>(_ t : T) where T: Sub, T.S == T
216215
// CHECK: br label %[[LBL2]]
217216
// CHECK:[[LBL2]]:
218217
// CHECK: [[T5:%.*]] = phi i8** [ [[PWT]], %[[ENTRY]] ], [ [[T4]], %[[LBL1]] ]
219-
// CHECK: [[CAST:%.*]] = bitcast i8** [[T5]] to i32*
220-
// CHECK: [[SLOT:%.*]] = getelementptr inbounds i32, i32* [[CAST]], i32 1
218+
// CHECK-arm64e: [[T6:%.*]] = ptrtoint i8** [[T5]] to i64
219+
// CHECK-arm64e: [[T7:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T6]], i32 2, i64 47152)
220+
// CHECK-arm64e: [[T8:%.*]] = inttoptr i64 [[T7]] to i8**
221+
// CHECK-arm64e: [[CAST:%.*]] = bitcast i8** [[T8]] to i32*
222+
// CHECK-arm64e: [[SLOT:%.*]] = getelementptr inbounds i32, i32* [[CAST]], i32 1
223+
// CHECK-arm64: [[CAST:%.*]] = bitcast i8** [[T5]] to i32*
224+
// CHECK-arm64: [[SLOT:%.*]] = getelementptr inbounds i32, i32* [[CAST]], i32 1
225+
// CHECK-x86_64: [[CAST:%.*]] = bitcast i8** [[T5]] to i32*
226+
// CHECK-x86_64: [[SLOT:%.*]] = getelementptr inbounds i32, i32* [[CAST]], i32 1
221227
// CHECK: [[T0:%.*]] = load i32, i32* [[SLOT]]
222228
// CHECK: [[T1:%.*]] = sext i32 [[T0]] to i64
223229
// CHECK: [[T2:%.*]] = ptrtoint i32* [[SLOT]] to i64
@@ -243,14 +249,22 @@ func instantiate_conditional_conformance_2nd<T>(_ t : T) where T: Sub, T.S == T
243249
// CHECK: br label %[[L3:.*]]
244250

245251
// CHECK:[[L2]]:
246-
// CHECK: [[T8:%.*]] = bitcast i8** [[T_INHERITED]] to i32*
252+
// CHECK-arm64e: [[P0:%.*]] = ptrtoint i8** [[T_INHERITED]] to i64
253+
// CHECK-arm64e: [[P1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P0]], i32 2, i64 47152)
254+
// CHECK-arm64e: [[P2:%.*]] = inttoptr i64 [[P1]] to i8**
255+
// CHECK-arm64e: [[T8:%.*]] = bitcast i8** [[P2]] to i32*
256+
// CHECK-arm64: [[T8:%.*]] = bitcast i8** [[T_INHERITED]] to i32*
257+
// CHECK-x86_64: [[T8:%.*]] = bitcast i8** [[T_INHERITED]] to i32*
247258
// CHECK: [[T9:%.*]] = getelementptr inbounds i32, i32* [[T8]], i32 1
248259
// CHECK: [[T10:%.*]] = load i32, i32* [[T9]]
249260
// CHECK: [[T11:%.*]] = sext i32 [[T10]] to i64
250261
// CHECK: [[T12:%.*]] = ptrtoint i32* [[T9]] to i64
251262
// CHECK: [[T13:%.*]] = add i64 [[T12]], [[T11]]
252263
// CHECK: [[T14:%.*]] = inttoptr i64 [[T13]] to i8*
253264
// CHECK: [[T15:%.*]] = bitcast i8* [[T14]] to i8**
265+
// CHECK-arm64e: [[T16:%.*]] = ptrtoint i8** [[T15]] to i64
266+
// CHECK-arm64e: [[T17:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T16]], i32 2, i64 47152)
267+
// CHECK-arm64e: [[T15:%.*]] = inttoptr i64 [[T17]] to i8**
254268
// CHECK: br label %[[L3:.*]]
255269

256270
// CHECK:[[L3]]:
@@ -259,7 +273,7 @@ func instantiate_conditional_conformance_2nd<T>(_ t : T) where T: Sub, T.S == T
259273
// Passing the witness table.
260274

261275
// CHECK: define{{.*}} swiftcc void @"$s1A6useIt2yyF"()
262-
// CHECK: call swiftcc void @"$s1A15requireWitness2yyxAA9InheritedRzlF"(%swift.opaque* {{.*}}, %swift.type* {{.*}} @"$s1A7BStructVMf"{{.*}}, i8** {{.*}} @"$s1A7BStructVAA9InheritedAAWP"
276+
// CHECK: call swiftcc void @"$s1A15requireWitness2yyxAA9InheritedRzlF"(%swift.opaque* {{.*}}, %swift.type* {{.*}} @"$s1A7BStructVMf"{{.*}}, i8** {{.*}} @"$s1A7BStructVAA9InheritedAAWP{{(.ptrauth)?}}"
263277
// CHECK: ret void
264278

265279
// Accessing an associated witness
@@ -323,14 +337,22 @@ func instantiate_conditional_conformance_2nd<T>(_ t : T) where T: Sub, T.S == T
323337
// CHECK: br label %[[T23:.*]]
324338

325339
// CHECK: [[T14]]:
326-
// CHECK: [[T15:%.*]] = bitcast i8** [[T4]] to i32*
340+
// CHECK-arm64e: [[P0:%.*]] = ptrtoint i8** [[T4]] to i64
341+
// CHECK-arm64e: [[P1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P0]], i32 2, i64 47152)
342+
// CHECK-arm64e: [[P2:%.*]] = inttoptr i64 [[P1]] to i8**
343+
// CHECK-arm64e: [[T15:%.*]] = bitcast i8** [[P2]] to i32*
344+
// CHECK-x86_64: [[T15:%.*]] = bitcast i8** [[T4]] to i32*
345+
// CHECK-arm64: [[T15:%.*]] = bitcast i8** [[T4]] to i32*
327346
// CHECK: [[T16:%.*]] = getelementptr inbounds i32, i32* [[T15]], i32 1
328347
// CHECK: [[T17:%.*]] = load i32, i32* [[T16]]
329348
// CHECK: [[T18:%.*]] = sext i32 [[T17]] to i64
330349
// CHECK: [[T19:%.*]] = ptrtoint i32* [[T16]] to i64
331350
// CHECK: [[T20:%.*]] = add i64 [[T19]], [[T18]]
332351
// CHECK: [[T21:%.*]] = inttoptr i64 [[T20]] to i8*
333352
// CHECK: [[T22:%.*]] = bitcast i8* [[T21]] to i8**
353+
// CHECK-arm64e: [[P0:%.*]] = ptrtoint i8** [[T22]] to i64
354+
// CHECK-arm64e: [[P1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[P0]], i32 2, i64 47152)
355+
// CHECK-arm64e: [[T22:%.*]] = inttoptr i64 [[P1]] to i8**
334356
// CHECK: br label %[[T23]]
335357

336358
// CHECK: [[T23]]:

0 commit comments

Comments
 (0)