Skip to content

Commit a55cb86

Browse files
committed
IRGen: Sign the class stub initialization callback pointer on arm64e
The Objective-C runtime expects a signed pointer here. The existing test would have caught this, except it was always disabled because the symbol name passed to the dlsym() check should not have had the leading '_'. Fixes <rdar://problem/57679510>.
1 parent 48dc2b2 commit a55cb86

File tree

10 files changed

+55
-40
lines changed

10 files changed

+55
-40
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,9 @@ namespace SpecialPointerAuthDiscriminators {
11641164
/// they're important enough to be worth writing in one place.
11651165
const uint16_t OpaqueReadResumeFunction = 56769;
11661166
const uint16_t OpaqueModifyResumeFunction = 3909;
1167+
1168+
/// Resilient class stub initializer callback
1169+
const uint16_t ResilientClassStubInitCallback = 0xC671;
11671170
}
11681171

11691172
/// 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
@@ -122,6 +122,9 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
122122

123123
/// Resumption functions from yield-many coroutines.
124124
PointerAuthSchema YieldManyResumeFunctions;
125+
126+
/// Resilient class stub initializer callbacks.
127+
PointerAuthSchema ResilientClassStubInitCallbacks;
125128
};
126129

127130
/// The set of options supported by IR generation.

lib/IRGen/GenClass.cpp

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,41 +2098,44 @@ static llvm::Function *emitObjCMetadataUpdateFunction(IRGenModule &IGM,
20982098
/// We emit Objective-C class stubs for non-generic classes with resilient
20992099
/// ancestry. This lets us attach categories to the class even though it
21002100
/// does not have statically-emitted metadata.
2101-
bool irgen::hasObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D) {
2102-
assert(IGM.getClassMetadataStrategy(D) == ClassMetadataStrategy::Resilient);
2103-
return IGM.ObjCInterop && !D->isGenericContext();
2101+
bool IRGenModule::hasObjCResilientClassStub(ClassDecl *D) {
2102+
assert(getClassMetadataStrategy(D) == ClassMetadataStrategy::Resilient);
2103+
return ObjCInterop && !D->isGenericContext();
21042104
}
21052105

2106-
void irgen::emitObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D) {
2107-
assert(hasObjCResilientClassStub(IGM, D));
2106+
void IRGenModule::emitObjCResilientClassStub(ClassDecl *D) {
2107+
assert(hasObjCResilientClassStub(D));
21082108

2109-
llvm::Constant *fields[] = {
2110-
llvm::ConstantInt::get(IGM.SizeTy, 0), // reserved
2111-
llvm::ConstantInt::get(IGM.SizeTy, 1), // isa
2112-
IGM.getAddrOfObjCMetadataUpdateFunction(D, NotForDefinition)
2113-
};
2114-
auto init = llvm::ConstantStruct::get(IGM.ObjCFullResilientClassStubTy,
2115-
makeArrayRef(fields));
2109+
ConstantInitBuilder builder(*this);
2110+
auto fields = builder.beginStruct(ObjCFullResilientClassStubTy);
2111+
fields.addInt(SizeTy, 0); // reserved
2112+
fields.addInt(SizeTy, 1); // isa
2113+
auto *impl = getAddrOfObjCMetadataUpdateFunction(D, NotForDefinition);
2114+
const auto &schema =
2115+
getOptions().PointerAuth.ResilientClassStubInitCallbacks;
2116+
fields.addSignedPointer(impl, schema, PointerAuthEntity()); // callback
2117+
2118+
auto init = fields.finishAndCreateFuture();
21162119

21172120
// Define the full stub. This is a private symbol.
2121+
LinkEntity entity = LinkEntity::forObjCResilientClassStub(
2122+
D, TypeMetadataAddress::FullMetadata);
21182123
auto fullObjCStub = cast<llvm::GlobalVariable>(
2119-
IGM.getAddrOfObjCResilientClassStub(D, ForDefinition,
2120-
TypeMetadataAddress::FullMetadata));
2121-
fullObjCStub->setInitializer(init);
2124+
getAddrOfLLVMVariable(entity, init, DebugTypeInfo()));
21222125

21232126
// Emit the metadata update function referenced above.
2124-
emitObjCMetadataUpdateFunction(IGM, D);
2127+
emitObjCMetadataUpdateFunction(*this, D);
21252128

21262129
// Apply the offset.
2127-
auto *objcStub = llvm::ConstantExpr::getBitCast(fullObjCStub, IGM.Int8PtrTy);
2130+
auto *objcStub = llvm::ConstantExpr::getBitCast(fullObjCStub, Int8PtrTy);
21282131
objcStub = llvm::ConstantExpr::getInBoundsGetElementPtr(
2129-
IGM.Int8Ty, objcStub, IGM.getSize(IGM.getPointerSize()));
2132+
Int8Ty, objcStub, getSize(getPointerSize()));
21302133
objcStub = llvm::ConstantExpr::getPointerCast(objcStub,
2131-
IGM.ObjCResilientClassStubTy->getPointerTo());
2134+
ObjCResilientClassStubTy->getPointerTo());
21322135

2133-
auto entity = LinkEntity::forObjCResilientClassStub(
2136+
entity = LinkEntity::forObjCResilientClassStub(
21342137
D, TypeMetadataAddress::AddressPoint);
2135-
IGM.defineAlias(entity, objcStub);
2138+
defineAlias(entity, objcStub);
21362139
}
21372140

21382141
/// Emit the private data (RO-data) associated with a class.

lib/IRGen/GenClass.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,6 @@ namespace irgen {
168168
llvm::Value *selfValue,
169169
llvm::Value *metadataValue);
170170

171-
/// We emit Objective-C class stubs for non-generic classes with resilient
172-
/// ancestry. This lets us attach categories to the class even though it
173-
/// does not have statically-emitted metadata.
174-
bool hasObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D);
175-
176-
/// Emit a resilient class stub.
177-
void emitObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D);
178-
179171
/// Emit the constant fragile offset of the given property inside an instance
180172
/// of the class.
181173
llvm::Constant *tryEmitConstantClassFragilePhysicalMemberOffset(

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,7 +1672,7 @@ namespace {
16721672
/ IGM.getPointerSize());
16731673
} else {
16741674
ExtraClassDescriptorFlags flags;
1675-
if (hasObjCResilientClassStub(IGM, getType()))
1675+
if (IGM.hasObjCResilientClassStub(getType()))
16761676
flags.setObjCResilientClassStub(true);
16771677
B.addInt32(flags.getOpaqueValue());
16781678
}
@@ -1694,7 +1694,7 @@ namespace {
16941694
ClassMetadataStrategy::Resilient)
16951695
return;
16961696

1697-
if (!hasObjCResilientClassStub(IGM, getType()))
1697+
if (!IGM.hasObjCResilientClassStub(getType()))
16981698
return;
16991699

17001700
B.addRelativeAddress(
@@ -3390,8 +3390,8 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
33903390
// Even non-@objc classes can have Objective-C categories attached, so
33913391
// we always emit a resilient class stub as long as -enable-objc-interop
33923392
// is set.
3393-
if (hasObjCResilientClassStub(IGM, classDecl)) {
3394-
emitObjCResilientClassStub(IGM, classDecl);
3393+
if (IGM.hasObjCResilientClassStub(classDecl)) {
3394+
IGM.emitObjCResilientClassStub(classDecl);
33953395

33963396
if (classDecl->isObjC()) {
33973397
auto *stub = IGM.getAddrOfObjCResilientClassStub(

lib/IRGen/IRGen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,10 @@ static void setPointerAuthOptions(PointerAuthOptions &opts,
729729
PointerAuthSchema(codeKey, /*address*/ true, Discrimination::Type);
730730
opts.YieldOnceResumeFunctions =
731731
PointerAuthSchema(codeKey, /*address*/ true, Discrimination::Type);
732+
733+
opts.ResilientClassStubInitCallbacks =
734+
PointerAuthSchema(codeKey, /*address*/ true, Discrimination::Constant,
735+
SpecialPointerAuthDiscriminators::ResilientClassStubInitCallback);
732736
}
733737

734738
std::unique_ptr<llvm::TargetMachine>

lib/IRGen/IRGenModule.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,14 @@ private: \
15631563

15641564
void emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *);
15651565

1566+
/// We emit Objective-C class stubs for non-generic classes with resilient
1567+
/// ancestry. This lets us attach categories to the class even though it
1568+
/// does not have statically-emitted metadata.
1569+
bool hasObjCResilientClassStub(ClassDecl *D);
1570+
1571+
/// Emit a resilient class stub.
1572+
void emitObjCResilientClassStub(ClassDecl *D);
1573+
15661574
private:
15671575
llvm::Constant *
15681576
getAddrOfSharedContextDescriptor(LinkEntity entity,

test/IRGen/class_update_callback_with_stub.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,21 @@ import resilient_objc_class
6363
// CHECK-SAME: internal global %objc_full_class_stub {
6464
// CHECK-SAME: [[INT]] 0,
6565
// CHECK-SAME: [[INT]] 1,
66-
// CHECK-SAME: %objc_class* (%objc_class*, i8*)* @"$s31class_update_callback_with_stub17ResilientSubclassCMU"
66+
// CHECK-SAME: %objc_class* (%objc_class*, i8*)* {{.*}}@"$s31class_update_callback_with_stub17ResilientSubclassCMU{{(\.ptrauth)?}}"
6767
// CHECK-SAME: }
6868

6969
// CHECK-LABEL: @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMt" =
7070
// CHECK-SAME: internal global %objc_full_class_stub {
7171
// CHECK-SAME: [[INT]] 0,
7272
// CHECK-SAME: [[INT]] 1,
73-
// CHECK-SAME: %objc_class* (%objc_class*, i8*)* @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMU"
73+
// CHECK-SAME: %objc_class* (%objc_class*, i8*)* {{.*}}@"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMU{{(\.ptrauth)?}}"
7474
// CHECK-SAME: }
7575

7676
// CHECK-LABEL: @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMt" =
7777
// CHECK-SAME: internal global %objc_full_class_stub {
7878
// CHECK-SAME: [[INT]] 0,
7979
// CHECK-SAME: [[INT]] 1,
80-
// CHECK-SAME: %objc_class* (%objc_class*, i8*)* @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMU"
80+
// CHECK-SAME: %objc_class* (%objc_class*, i8*)* {{.*}}@"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMU{{(\.ptrauth)?}}"
8181
// CHECK-SAME: }
8282

8383

validation-test/Runtime/class_stubs.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// RUN: %target-build-swift -emit-library -emit-module -o %t/libfirst.dylib -emit-objc-header-path %t/first.h %S/Inputs/class-stubs-from-objc/first.swift -Xlinker -install_name -Xlinker @executable_path/libfirst.dylib -enable-library-evolution
66
// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -emit-objc-header-path %t/second.h -I %t %S/Inputs/class-stubs-from-objc/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -target %target-next-stable-abi-triple
77
// RUN: cp %S/Inputs/class-stubs-from-objc/module.map %t/
8-
// RUN: xcrun -sdk %sdk %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -Wl,-U,_objc_loadClassref -target %target-next-stable-abi-triple
8+
// RUN: xcrun -sdk %sdk %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -target %target-next-stable-abi-triple
99
// RUN: %target-codesign %t/main %t/libfirst.dylib %t/libsecond.dylib
1010
// RUN: %target-run %t/main %t/libfirst.dylib %t/libsecond.dylib
1111

@@ -31,7 +31,7 @@ + (int)classMethod {
3131

3232
int main(int argc, const char * const argv[]) {
3333
// Only test the new behavior on a new enough libobjc.
34-
if (!dlsym(RTLD_NEXT, "_objc_loadClassref")) {
34+
if (!dlsym(RTLD_NEXT, "objc_loadClassref")) {
3535
fprintf(stderr, "skipping evolution tests; OS too old\n");
3636
return EXIT_SUCCESS;
3737
}

validation-test/Runtime/class_stubs_weak.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// RUN: cp %S/Inputs/class-stubs-weak/module.map %t/
88

99
// Note: This is the just-built Clang, not the system Clang.
10-
// RUN: xcrun -sdk %sdk %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -Wl,-U,_objc_loadClassref -target %target-triple
10+
// RUN: xcrun -sdk %sdk %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -target %target-triple
1111

1212
// Now rebuild the library, omitting the weak-exported class
1313
// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -I %t %S/Inputs/class-stubs-weak/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -target %target-next-stable-abi-triple
@@ -19,6 +19,8 @@
1919
// REQUIRES: objc_interop
2020
// REQUIRES: swift_stable_abi
2121

22+
// REQUIRES: rdar62692550
23+
2224
#import <dlfcn.h>
2325
#import <stdio.h>
2426
#import "second.h"
@@ -37,7 +39,7 @@ + (int)classMethod {
3739

3840
int main(int argc, const char * const argv[]) {
3941
// Only test the new behavior on a new enough libobjc.
40-
if (!dlsym(RTLD_NEXT, "_objc_loadClassref")) {
42+
if (!dlsym(RTLD_NEXT, "objc_loadClassref")) {
4143
fprintf(stderr, "skipping evolution tests; OS too old\n");
4244
return EXIT_SUCCESS;
4345
}

0 commit comments

Comments
 (0)