Skip to content

Commit c92f2a2

Browse files
authored
When ptrauth-copying vtable/wtables, allow NULL entries (due to VFE) (swiftlang#40578)
* When ptrauth-copying vtable/wtables, allow NULL entries (due to VFE) * Mark virtual-function-elimination-generics-exec.swift UNSUPPORTED: arm64e until the rebranch * Fix test expectations
1 parent 2fc0e35 commit c92f2a2

File tree

4 files changed

+74
-15
lines changed

4 files changed

+74
-15
lines changed

include/swift/Runtime/Config.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,14 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
330330

331331
/// Copy an address-discriminated signed pointer from the source to the dest.
332332
template <class T>
333-
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE
334-
static inline void swift_ptrauth_copy(T *dest, const T *src, unsigned extra) {
333+
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE static inline void
334+
swift_ptrauth_copy(T *dest, const T *src, unsigned extra, bool allowNull) {
335335
#if SWIFT_PTRAUTH
336+
if (allowNull && *src == nullptr) {
337+
*dest = nullptr;
338+
return;
339+
}
340+
336341
*dest = ptrauth_auth_and_resign(*src,
337342
ptrauth_key_function_pointer,
338343
ptrauth_blend_discriminator(src, extra),
@@ -348,8 +353,13 @@ static inline void swift_ptrauth_copy(T *dest, const T *src, unsigned extra) {
348353
template <class T>
349354
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE
350355
static inline void swift_ptrauth_copy_data(T *dest, const T *src,
351-
unsigned extra) {
356+
unsigned extra, bool allowNull) {
352357
#if SWIFT_PTRAUTH
358+
if (allowNull && *src == nullptr) {
359+
*dest = nullptr;
360+
return;
361+
}
362+
353363
*dest = ptrauth_auth_and_resign(*src,
354364
ptrauth_key_process_independent_data,
355365
ptrauth_blend_discriminator(src, extra),
@@ -365,11 +375,11 @@ static inline void swift_ptrauth_copy_data(T *dest, const T *src,
365375
template <class T>
366376
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE static inline void
367377
swift_ptrauth_copy_code_or_data(T *dest, const T *src, unsigned extra,
368-
bool isCode) {
378+
bool isCode, bool allowNull) {
369379
if (isCode) {
370-
return swift_ptrauth_copy(dest, src, extra);
380+
return swift_ptrauth_copy(dest, src, extra, allowNull);
371381
} else {
372-
return swift_ptrauth_copy_data(dest, src, extra);
382+
return swift_ptrauth_copy_data(dest, src, extra, allowNull);
373383
}
374384
}
375385

stdlib/public/runtime/Metadata.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,8 @@ static void swift_objc_classCopyFixupHandler(Class oldClass, Class newClass) {
440440
reinterpret_cast<void **>(&dest[i]),
441441
reinterpret_cast<void *const *>(&src[i]),
442442
descriptors[i].Flags.getExtraDiscriminator(),
443-
!descriptors[i].Flags.isAsync());
443+
!descriptors[i].Flags.isAsync(),
444+
/*allowNull*/ false); // Don't allow NULL for Obj-C classes
444445
}
445446
}
446447

@@ -2686,7 +2687,9 @@ static void copySuperclassMetadataToSubclass(ClassMetadata *theClass,
26862687
reinterpret_cast<void **>(&dest[i]),
26872688
reinterpret_cast<void *const *>(&src[i]),
26882689
descriptors[i].Flags.getExtraDiscriminator(),
2689-
!descriptors[i].Flags.isAsync());
2690+
!descriptors[i].Flags.isAsync(),
2691+
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable
2692+
// might be proven unused and null'ed)
26902693
}
26912694
#else
26922695
memcpy(dest, src, vtable->VTableSize * sizeof(uintptr_t));
@@ -4746,15 +4749,19 @@ static void copyProtocolWitness(void **dest, void * const *src,
47464749
case ProtocolRequirementFlags::Kind::Setter:
47474750
case ProtocolRequirementFlags::Kind::ReadCoroutine:
47484751
case ProtocolRequirementFlags::Kind::ModifyCoroutine:
4749-
swift_ptrauth_copy_code_or_data(dest, src,
4750-
reqt.Flags.getExtraDiscriminator(),
4751-
!reqt.Flags.isAsync());
4752+
swift_ptrauth_copy_code_or_data(
4753+
dest, src, reqt.Flags.getExtraDiscriminator(), !reqt.Flags.isAsync(),
4754+
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable
4755+
// might be proven unused and null'ed)
47524756
return;
47534757

47544758
// FIXME: these should both use ptrauth_key_process_independent_data now.
47554759
case ProtocolRequirementFlags::Kind::AssociatedConformanceAccessFunction:
47564760
case ProtocolRequirementFlags::Kind::AssociatedTypeAccessFunction:
4757-
swift_ptrauth_copy(dest, src, reqt.Flags.getExtraDiscriminator());
4761+
swift_ptrauth_copy(
4762+
dest, src, reqt.Flags.getExtraDiscriminator(),
4763+
/*allowNull*/ true); // NULL allowed for VFE (methods in the vtable
4764+
// might be proven unused and null'ed)
47584765
return;
47594766
}
47604767
swift_unreachable("bad witness kind");

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,7 +2341,7 @@ void DynamicReplacementDescriptor::enableReplacement() const {
23412341
reinterpret_cast<void **>(&chainRoot->implementationFunction),
23422342
reinterpret_cast<void *const *>(&previous->implementationFunction),
23432343
replacedFunctionKey->getExtraDiscriminator(),
2344-
!replacedFunctionKey->isAsync());
2344+
!replacedFunctionKey->isAsync(), /*allowNull*/ false);
23452345
}
23462346

23472347
// First populate the current replacement's chain entry.
@@ -2352,7 +2352,7 @@ void DynamicReplacementDescriptor::enableReplacement() const {
23522352
reinterpret_cast<void **>(&currentEntry->implementationFunction),
23532353
reinterpret_cast<void *const *>(&chainRoot->implementationFunction),
23542354
replacedFunctionKey->getExtraDiscriminator(),
2355-
!replacedFunctionKey->isAsync());
2355+
!replacedFunctionKey->isAsync(), /*allowNull*/ false);
23562356

23572357
currentEntry->next = chainRoot->next;
23582358

@@ -2388,7 +2388,7 @@ void DynamicReplacementDescriptor::disableReplacement() const {
23882388
reinterpret_cast<void **>(&previous->implementationFunction),
23892389
reinterpret_cast<void *const *>(&thisEntry->implementationFunction),
23902390
replacedFunctionKey->getExtraDiscriminator(),
2391-
!replacedFunctionKey->isAsync());
2391+
!replacedFunctionKey->isAsync(), /*allowNull*/ false);
23922392
}
23932393

23942394
/// An automatic dymamic replacement entry.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Tests that under -enable-llvm-vfe, LLVM GlobalDCE is able to remove unused
2+
// virtual methods, and that used virtual methods are not removed (by running
3+
// the program).
4+
5+
// RUN: %empty-directory(%t)
6+
// RUN: %target-build-swift -Xfrontend -enable-llvm-vfe %s -Onone -emit-ir -o %t/main.ll
7+
// RUN: %target-clang %t/main.ll -isysroot %sdk -L%swift_obj_root/lib/swift/%target-sdk-name -flto -o %t/main
8+
// RUN: %target-run %t/main | %FileCheck %s
9+
10+
// RUN: %llvm-nm --defined-only %t/main | %FileCheck %s --check-prefix=NM
11+
12+
// REQUIRES: executable_test
13+
14+
// FIXME(mracek): More work needed to get this to work on non-Apple platforms.
15+
// REQUIRES: VENDOR=apple
16+
17+
// For LTO, the linker dlopen()'s the libLTO library, which is a scenario that
18+
// ASan cannot work in ("Interceptors are not working, AddressSanitizer is
19+
// loaded too late").
20+
// REQUIRES: no_asan
21+
22+
// Requires rdar://85970023 which is only fixed in the 20211026 branch of LLVM.
23+
// UNSUPPORTED: CPU=arm64e
24+
25+
class MyClass {
26+
func foo() { print("MyClass.foo") }
27+
func bar() { print("MyClass.bar") }
28+
}
29+
30+
class MyDerivedClass<T>: MyClass {
31+
override func foo() { print("MyDerivedClass<T>.foo, T=\(type(of: T.self))") }
32+
override func bar() { print("MyDerivedClass<T>.bar, T=\(type(of: T.self))") }
33+
}
34+
35+
let o: MyClass = MyDerivedClass<Int>()
36+
o.foo()
37+
// CHECK: MyDerivedClass<T>.foo, T=Int.Type
38+
39+
// NM-NOT: $s4main14MyDerivedClassC3baryyF
40+
// NM: $s4main14MyDerivedClassC3fooyyF
41+
// NM-NOT: $s4main7MyClassC3baryyF
42+
// NM: $s4main7MyClassC3fooyyF

0 commit comments

Comments
 (0)