1111// ===----------------------------------------------------------------------===//
1212
1313#include " swift/Runtime/LibPrespecialized.h"
14+ #include " MetadataCache.h"
1415#include " Private.h"
1516#include " swift/Basic/Lazy.h"
1617#include " swift/Runtime/EnvironmentVariables.h"
@@ -71,24 +72,89 @@ static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
7172 return data;
7273}
7374
75+ struct LibPrespecializedState {
76+ struct AddressRange {
77+ uintptr_t start, end;
78+
79+ bool contains (const void *ptr) {
80+ return start <= (uintptr_t )ptr && (uintptr_t )ptr < end;
81+ }
82+ };
83+
84+ bool loggingEnabled;
85+ const LibPrespecializedData<InProcess> *data;
86+ AddressRange sharedCacheRange{0 , 0 };
87+ AddressRange metadataAllocatorInitialPoolRange{0 , 0 };
88+
89+ LibPrespecializedState () {
90+ loggingEnabled =
91+ runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ();
92+ data = findLibPrespecialized ();
93+
94+ #if DYLD_GET_SWIFT_PRESPECIALIZED_DATA_DEFINED
95+ size_t sharedCacheLength;
96+ sharedCacheRange.start =
97+ (uintptr_t )_dyld_get_shared_cache_range (&sharedCacheLength);
98+ sharedCacheRange.end = sharedCacheRange.start + sharedCacheLength;
99+
100+ auto [initialPoolStart, initialPoolLength] =
101+ MetadataAllocator::InitialPoolLocation ();
102+ metadataAllocatorInitialPoolRange.start = (uintptr_t )initialPoolStart;
103+ metadataAllocatorInitialPoolRange.end =
104+ metadataAllocatorInitialPoolRange.start + initialPoolLength;
105+ #endif
106+ }
107+ };
108+
109+ static Lazy<LibPrespecializedState> LibPrespecialized;
110+
111+ #define LOG (fmt, ...) \
112+ do { \
113+ if (SWIFT_UNLIKELY (prespecialized.loggingEnabled )) \
114+ fprintf (stderr, " Prespecializations library: " fmt " \n " , __VA_ARGS__); \
115+ } while (0 )
116+
74117const LibPrespecializedData<InProcess> *swift::getLibPrespecializedData () {
75118 return SWIFT_LAZY_CONSTANT (findLibPrespecialized ());
76119}
77120
78121// Returns true if the type has any arguments that aren't plain types (packs or
79122// unknown kinds).
80- static bool hasNonTypeGenericArguments (const TypeContextDescriptor *description) {
81- auto generics = description->getGenericContext ();
82- if (!generics)
83- return false ;
84-
123+ static bool
124+ hasNonTypeGenericArguments (const TargetGenericContext<InProcess> *generics) {
85125 for (auto param : generics->getGenericParams ())
86126 if (param.getKind () != GenericParamKind::Type)
87127 return true ;
88128
89129 return false ;
90130}
91131
132+ static bool
133+ isPotentialPrespecializedPointer (LibPrespecializedState &prespecialized,
134+ const void *pointer) {
135+ // Prespecialized metadata descriptors and arguments are always in the shared
136+ // cache. They're either statically emitted metadata, or they're
137+ // prespecialized metadata. Anything that's dynamically allocated, or
138+ // statically allocated outside the shared cache, is not a possible candidate.
139+
140+ // If we're loading a debug libprespecialized, we can't do these checks, so
141+ // just say everything is a potential argument. Performance is not so
142+ // important in that case.
143+ if (!prespecialized.sharedCacheRange .contains (prespecialized.data ))
144+ return true ;
145+
146+ // Anything outside the shared cache isn't a potential argument.
147+ if (!prespecialized.sharedCacheRange .contains (pointer))
148+ return false ;
149+
150+ // Dynamically allocated metadata could be within the shared cache, in the
151+ // initial metadata allocation pool. Reject anything in that region.
152+ if (prespecialized.metadataAllocatorInitialPoolRange .contains (pointer))
153+ return false ;
154+
155+ return true ;
156+ }
157+
92158static bool disableForValidation = false ;
93159
94160Metadata *
@@ -97,24 +163,40 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
97163 if (disableForValidation)
98164 return nullptr ;
99165
100- auto *data = getLibPrespecializedData ();
166+ auto &prespecialized = LibPrespecialized.get ();
167+
168+ auto *data = prespecialized.data ;
101169 if (!data)
102170 return nullptr ;
103171
172+ auto *generics = description->getGenericContext ();
173+ if (!generics)
174+ return nullptr ;
175+
104176 // We don't support types with pack parameters yet (and especially not types
105177 // with unknown parameter kinds) so don't even try to look those up.
106- if (hasNonTypeGenericArguments (description ))
178+ if (hasNonTypeGenericArguments (generics ))
107179 return nullptr ;
108180
181+ if (!isPotentialPrespecializedPointer (prespecialized, description)) {
182+ LOG (" Rejecting descriptor %p, not in the shared cache" ,
183+ (const void *)description);
184+ return nullptr ;
185+ }
186+
187+ auto numKeyArguments = generics->getGenericContextHeader ().NumKeyArguments ;
188+ for (unsigned i = 0 ; i < numKeyArguments; i++) {
189+ if (!isPotentialPrespecializedPointer (prespecialized, arguments[i])) {
190+ LOG (" Rejecting argument %u %p to descriptor %p, not in the shared cache" ,
191+ i, arguments[i], (const void *)description);
192+ return nullptr ;
193+ }
194+ }
195+
109196 Demangler dem;
110197 auto mangleNode = _buildDemanglingForGenericType (description, arguments, dem);
111198 if (!mangleNode) {
112- if (SWIFT_UNLIKELY (runtime::environment::
113- SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ()))
114- fprintf (stderr,
115- " Prespecializations library: failed to build demangling with "
116- " descriptor %p.\n " ,
117- description);
199+ LOG (" failed to build demangling with descriptor %p." , description);
118200 return nullptr ;
119201 }
120202
@@ -142,10 +224,7 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
142224 auto *metadataMap = data->getMetadataMap ();
143225 auto *element = metadataMap->find (key.data (), key.size ());
144226 auto *result = element ? element->value : nullptr ;
145- if (SWIFT_UNLIKELY (runtime::environment::
146- SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ()))
147- fprintf (stderr, " Prespecializations library: found %p for key '%.*s'.\n " ,
148- result, (int )key.size (), key.data ());
227+ LOG (" found %p for key '%.*s'." , result, (int )key.size (), key.data ());
149228 return result;
150229}
151230
0 commit comments