Skip to content

Commit be3eef8

Browse files
committed
[Runtime] Disable prespecialized metadata if we have overridden images.
We need to check for overridden images on every image load, otherwise XCTest (among others) may `dlopen()` an image that pulls in something that is overridden, at which point the prespecialized metadata won't match the image we loaded. rdar://125727356
1 parent bb339b8 commit be3eef8

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

include/swift/Runtime/LibPrespecialized.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct LibPrespecializedData {
4848
const LibPrespecializedData<InProcess> *getLibPrespecializedData();
4949
Metadata *getLibPrespecializedMetadata(const TypeContextDescriptor *description,
5050
const void *const *arguments);
51+
void libPrespecializedImageLoaded();
5152

5253
} // namespace swift
5354

stdlib/public/runtime/LibPrespecialized.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "swift/Runtime/EnvironmentVariables.h"
1717
#include "swift/Runtime/Metadata.h"
1818

19+
#include <atomic>
20+
1921
#if SWIFT_STDLIB_HAS_DLADDR && __has_include(<dlfcn.h>)
2022
#include <dlfcn.h>
2123
#define USE_DLOPEN 1
@@ -27,6 +29,8 @@
2729

2830
using namespace swift;
2931

32+
static std::atomic<bool> disablePrespecializedMetadata = false;
33+
3034
static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
3135
if (!runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED())
3236
return nullptr;
@@ -91,10 +95,23 @@ static bool hasNonTypeGenericArguments(const TypeContextDescriptor *description)
9195

9296
static bool disableForValidation = false;
9397

98+
void
99+
swift::libPrespecializedImageLoaded() {
100+
#if DYLD_GET_SWIFT_PRESPECIALIZED_DATA_DEFINED
101+
// A newly loaded image might have caused us to load images that are
102+
// overriding images in the shared cache. If we do that, turn off
103+
// prespecialized metadata.
104+
if (dyld_shared_cache_some_image_overridden())
105+
disablePrespecializedMetadata.store(true, std::memory_order_release);
106+
#endif
107+
}
108+
94109
Metadata *
95110
swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
96111
const void *const *arguments) {
97-
if (disableForValidation)
112+
if (SWIFT_UNLIKELY(
113+
disableForValidation
114+
|| disablePrespecializedMetadata.load(std::memory_order_acquire)))
98115
return nullptr;
99116

100117
auto *data = getLibPrespecializedData();

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "swift/Runtime/Debug.h"
3030
#include "swift/Runtime/EnvironmentVariables.h"
3131
#include "swift/Runtime/HeapObject.h"
32+
#include "swift/Runtime/LibPrespecialized.h"
3233
#include "swift/Runtime/Metadata.h"
3334
#include "swift/Strings.h"
3435
#include "swift/Threading/Mutex.h"
@@ -347,6 +348,8 @@ void swift::addImageTypeMetadataRecordBlockCallbackUnsafe(
347348
assert(recordsSize % sizeof(TypeMetadataRecord) == 0
348349
&& "weird-sized type metadata section?!");
349350

351+
libPrespecializedImageLoaded();
352+
350353
// If we have a section, enqueue the type metadata for lookup.
351354
auto recordBytes = reinterpret_cast<const char *>(records);
352355
auto recordsBegin

0 commit comments

Comments
 (0)