Skip to content

Commit 7b79056

Browse files
committed
IRGen to copy non trivial structs with ptrauth qualified field function pointers
1 parent 9dceb37 commit 7b79056

File tree

2 files changed

+119
-9
lines changed

2 files changed

+119
-9
lines changed

lib/IRGen/GenStruct.cpp

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ static clang::CXXDestructorDecl *getCXXDestructor(SILType type) {
8383
return nullptr;
8484
return cxxRecordDecl->getDestructor();
8585
}
86-
8786
namespace {
8887
class StructFieldInfo : public RecordField<StructFieldInfo> {
8988
public:
@@ -415,6 +414,97 @@ namespace {
415414
}
416415
};
417416

417+
class AddressOnlyPointerAuthRecordTypeInfo final
418+
: public StructTypeInfoBase<AddressOnlyPointerAuthRecordTypeInfo,
419+
FixedTypeInfo, ClangFieldInfo> {
420+
const clang::RecordDecl *clangDecl;
421+
422+
void emitCopyWithCopyFunction(IRGenFunction &IGF, SILType T, Address src,
423+
Address dst) const {
424+
auto *copyFunction =
425+
clang::CodeGen::getNonTrivialCStructCopyAssignmentOperator(
426+
IGF.IGM.getClangCGM(), dst.getAlignment(), src.getAlignment(),
427+
/*isVolatile*/ false,
428+
clang::QualType(clangDecl->getTypeForDecl(), 0));
429+
auto *dstValue = dst.getAddress();
430+
auto *srcValue = src.getAddress();
431+
if (IGF.IGM.getLLVMContext().supportsTypedPointers()) {
432+
dstValue = IGF.coerceValue(
433+
dst.getAddress(), copyFunction->getFunctionType()->getParamType(0),
434+
IGF.IGM.DataLayout);
435+
srcValue = IGF.coerceValue(
436+
src.getAddress(), copyFunction->getFunctionType()->getParamType(1),
437+
IGF.IGM.DataLayout);
438+
}
439+
IGF.Builder.CreateCall(copyFunction->getFunctionType(), copyFunction,
440+
{dstValue, srcValue});
441+
}
442+
443+
public:
444+
AddressOnlyPointerAuthRecordTypeInfo(ArrayRef<ClangFieldInfo> fields,
445+
llvm::Type *storageType, Size size,
446+
Alignment align,
447+
const clang::RecordDecl *clangDecl)
448+
: StructTypeInfoBase(StructTypeInfoKind::AddressOnlyClangRecordTypeInfo,
449+
fields, storageType, size,
450+
// We can't assume any spare bits in a C++ type
451+
// with user-defined special member functions.
452+
SpareBitVector(llvm::Optional<APInt>{
453+
llvm::APInt(size.getValueInBits(), 0)}),
454+
align, IsNotPOD, IsNotBitwiseTakable, IsFixedSize),
455+
clangDecl(clangDecl) {
456+
(void)clangDecl;
457+
}
458+
459+
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
460+
SILType T) const override {
461+
if (!IGM.getOptions().ForceStructTypeLayouts) {
462+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
463+
}
464+
assert(false && "Implement proper type layout info in the future");
465+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
466+
}
467+
468+
void initializeFromParams(IRGenFunction &IGF, Explosion &params,
469+
Address addr, SILType T,
470+
bool isOutlined) const override {
471+
llvm_unreachable("Address-only C++ types must be created by C++ special "
472+
"member functions.");
473+
}
474+
475+
void initializeWithCopy(IRGenFunction &IGF, Address dst, Address src,
476+
SILType T, bool isOutlined) const override {
477+
emitCopyWithCopyFunction(IGF, T, src, dst);
478+
}
479+
480+
void assignWithCopy(IRGenFunction &IGF, Address dst, Address src, SILType T,
481+
bool isOutlined) const override {
482+
emitCopyWithCopyFunction(IGF, T, src, dst);
483+
}
484+
485+
void initializeWithTake(IRGenFunction &IGF, Address dst, Address src,
486+
SILType T, bool isOutlined) const override {
487+
emitCopyWithCopyFunction(IGF, T, src, dst);
488+
destroy(IGF, src, T, isOutlined);
489+
}
490+
491+
void assignWithTake(IRGenFunction &IGF, Address dst, Address src, SILType T,
492+
bool isOutlined) const override {
493+
emitCopyWithCopyFunction(IGF, T, src, dst);
494+
destroy(IGF, src, T, isOutlined);
495+
}
496+
497+
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF) const { return None; }
498+
llvm::NoneType getNonFixedOffsets(IRGenFunction &IGF, SILType T) const {
499+
return None;
500+
}
501+
MemberAccessStrategy
502+
getNonFixedFieldAccessStrategy(IRGenModule &IGM, SILType T,
503+
const ClangFieldInfo &field) const {
504+
llvm_unreachable("non-fixed field in Clang type?");
505+
}
506+
};
507+
418508
class AddressOnlyCXXClangRecordTypeInfo final
419509
: public StructTypeInfoBase<AddressOnlyCXXClangRecordTypeInfo,
420510
FixedTypeInfo, ClangFieldInfo> {
@@ -1045,8 +1135,10 @@ class ClangRecordLowering {
10451135
return AddressOnlyCXXClangRecordTypeInfo::create(
10461136
FieldInfos, llvmType, TotalStride, TotalAlignment, ClangDecl);
10471137
}
1048-
// TODO: New AddressOnlyPtrAuthTypeInfo to handle address diversified field
1049-
// function ptrs in C structs.
1138+
if (SwiftType.getStructOrBoundGenericStruct()->isNonTrivialPtrAuth()) {
1139+
return AddressOnlyPointerAuthRecordTypeInfo::create(
1140+
FieldInfos, llvmType, TotalStride, TotalAlignment, ClangDecl);
1141+
}
10501142
return LoadableClangRecordTypeInfo::create(
10511143
FieldInfos, NextExplosionIndex, llvmType, TotalStride,
10521144
std::move(SpareBits), TotalAlignment, ClangDecl);

test/IRGen/ptrauth_field_fptr_import.swift

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,13 @@ func test_addr_discriminated_field_fn_read() -> Int32 {
7272
}
7373

7474
// CHECK-LABEL: define hidden swiftcc void @"$s25ptrauth_field_fptr_import024test_addr_discriminated_B14_fn_ptr_modifyyyF"() #0 {
75+
// CHECK: entry:
76+
// CHECK: [[PTR:%.*]] = load i64, i64* bitcast (%struct.AddressDiscriminatedSecureStruct** @ptr_to_addr_discriminated_secure_struct to i64*), align 8
77+
// CHECK: 4: ; preds = %entry
78+
// CHECK: [[CAST0:%.*]] = inttoptr i64 [[PTR]] to i8*
79+
// CHECK: br label %11
7580
// CHECK: 11: ; preds = %4
76-
// CHECK: [[AddressDiscriminatedSecureStruct:%.*]] = phi i8* [ %5, %4 ]
81+
// CHECK: [[AddressDiscriminatedSecureStruct:%.*]] = phi i8* [ [[CAST0]], %4 ]
7782
// CHECK: [[CAST1:%.*]] = bitcast i8* [[AddressDiscriminatedSecureStruct]] to %TSo32AddressDiscriminatedSecureStructV*
7883
// CHECK: %.secure_func_ptr = getelementptr inbounds %TSo32AddressDiscriminatedSecureStructV, %TSo32AddressDiscriminatedSecureStructV* [[CAST1]], i32 0, i32 0
7984
// CHECK: [[CAST2:%.*]] = bitcast %Ts5Int32VIetCd_Sg* %ptrauth.temp to i64*
@@ -91,13 +96,26 @@ func test_addr_discriminated_field_fn_ptr_modify() {
9196
ptr_to_addr_discriminated_secure_struct!.pointee.secure_func_ptr = returnInt
9297
}
9398

94-
// TODO: Unimplemented non trivial pointer auth copy function
95-
// func test_addr_discriminated_copy() -> Int32 {
96-
// let struct_with_signed_val = ptr_to_addr_discriminated_secure_struct.pointee
97-
// return struct_with_signed_val.secure_func_ptr()
98-
// }
99+
// CHECK-LABEL: define hidden swiftcc i32 @"$s25ptrauth_field_fptr_import28test_addr_discriminated_copys5Int32VyF"() #0 {
100+
// CHECK: entry:
101+
// CHECK: [[STRUCT:%.*]] = alloca %TSo32AddressDiscriminatedSecureStructV, align 8
102+
// CHECK: [[LD:%.*]] = load i64, i64* bitcast (%struct.AddressDiscriminatedSecureStruct** @ptr_to_addr_discriminated_secure_struct to i64*), align 8
103+
// CHECK: 6: ; preds = %entry
104+
// CHECK: [[CAST0:%.*]] = inttoptr i64 [[LD]] to i8*
105+
// CHECK: br label %13
106+
// CHECK: 13: ; preds = %6
107+
// CHECK: [[PHI:%.*]] = phi i8* [ [[CAST0]], %6 ]
108+
// CHECK: [[CAST1:%.*]] = bitcast i8* [[PHI]] to %TSo32AddressDiscriminatedSecureStructV*
109+
// CHECK: [[CAST2:%.*]] = bitcast %TSo32AddressDiscriminatedSecureStructV* [[STRUCT]] to i8**
110+
// CHECK: [[CAST3:%.*]] = bitcast %TSo32AddressDiscriminatedSecureStructV* [[CAST1]] to i8**
111+
// CHECK: call void @__copy_assignment_8_8_pa1_88_0(i8** [[CAST2]], i8** [[CAST3]])
112+
func test_addr_discriminated_copy() -> Int32 {
113+
let struct_with_signed_val = ptr_to_addr_discriminated_secure_struct.pointee
114+
return struct_with_signed_val.secure_func_ptr()
115+
}
99116

100117
print(test_field_fn_read())
101118
test_field_fn_ptr_modify()
102119
print(test_addr_discriminated_field_fn_read())
103120
test_addr_discriminated_field_fn_ptr_modify()
121+
print(test_addr_discriminated_copy())

0 commit comments

Comments
 (0)