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"
@@ -75,24 +76,89 @@ static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
7576 return data;
7677}
7778
79+ struct LibPrespecializedState {
80+ struct AddressRange {
81+ uintptr_t start, end;
82+
83+ bool contains (const void *ptr) {
84+ return start <= (uintptr_t )ptr && (uintptr_t )ptr < end;
85+ }
86+ };
87+
88+ bool loggingEnabled;
89+ const LibPrespecializedData<InProcess> *data;
90+ AddressRange sharedCacheRange{0 , 0 };
91+ AddressRange metadataAllocatorInitialPoolRange{0 , 0 };
92+
93+ LibPrespecializedState () {
94+ loggingEnabled =
95+ runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ();
96+ data = findLibPrespecialized ();
97+
98+ #if DYLD_GET_SWIFT_PRESPECIALIZED_DATA_DEFINED
99+ size_t sharedCacheLength;
100+ sharedCacheRange.start =
101+ (uintptr_t )_dyld_get_shared_cache_range (&sharedCacheLength);
102+ sharedCacheRange.end = sharedCacheRange.start + sharedCacheLength;
103+
104+ auto [initialPoolStart, initialPoolLength] =
105+ MetadataAllocator::InitialPoolLocation ();
106+ metadataAllocatorInitialPoolRange.start = (uintptr_t )initialPoolStart;
107+ metadataAllocatorInitialPoolRange.end =
108+ metadataAllocatorInitialPoolRange.start + initialPoolLength;
109+ #endif
110+ }
111+ };
112+
113+ static Lazy<LibPrespecializedState> LibPrespecialized;
114+
115+ #define LOG (fmt, ...) \
116+ do { \
117+ if (SWIFT_UNLIKELY (prespecialized.loggingEnabled )) \
118+ fprintf (stderr, " Prespecializations library: " fmt " \n " , __VA_ARGS__); \
119+ } while (0 )
120+
78121const LibPrespecializedData<InProcess> *swift::getLibPrespecializedData () {
79122 return SWIFT_LAZY_CONSTANT (findLibPrespecialized ());
80123}
81124
82125// Returns true if the type has any arguments that aren't plain types (packs or
83126// unknown kinds).
84- static bool hasNonTypeGenericArguments (const TypeContextDescriptor *description) {
85- auto generics = description->getGenericContext ();
86- if (!generics)
87- return false ;
88-
127+ static bool
128+ hasNonTypeGenericArguments (const TargetGenericContext<InProcess> *generics) {
89129 for (auto param : generics->getGenericParams ())
90130 if (param.getKind () != GenericParamKind::Type)
91131 return true ;
92132
93133 return false ;
94134}
95135
136+ static bool
137+ isPotentialPrespecializedPointer (LibPrespecializedState &prespecialized,
138+ const void *pointer) {
139+ // Prespecialized metadata descriptors and arguments are always in the shared
140+ // cache. They're either statically emitted metadata, or they're
141+ // prespecialized metadata. Anything that's dynamically allocated, or
142+ // statically allocated outside the shared cache, is not a possible candidate.
143+
144+ // If we're loading a debug libprespecialized, we can't do these checks, so
145+ // just say everything is a potential argument. Performance is not so
146+ // important in that case.
147+ if (!prespecialized.sharedCacheRange .contains (prespecialized.data ))
148+ return true ;
149+
150+ // Anything outside the shared cache isn't a potential argument.
151+ if (!prespecialized.sharedCacheRange .contains (pointer))
152+ return false ;
153+
154+ // Dynamically allocated metadata could be within the shared cache, in the
155+ // initial metadata allocation pool. Reject anything in that region.
156+ if (prespecialized.metadataAllocatorInitialPoolRange .contains (pointer))
157+ return false ;
158+
159+ return true ;
160+ }
161+
96162static bool disableForValidation = false ;
97163
98164void
@@ -114,24 +180,40 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
114180 || disablePrespecializedMetadata.load (std::memory_order_acquire)))
115181 return nullptr ;
116182
117- auto *data = getLibPrespecializedData ();
183+ auto &prespecialized = LibPrespecialized.get ();
184+
185+ auto *data = prespecialized.data ;
118186 if (!data)
119187 return nullptr ;
120188
189+ auto *generics = description->getGenericContext ();
190+ if (!generics)
191+ return nullptr ;
192+
121193 // We don't support types with pack parameters yet (and especially not types
122194 // with unknown parameter kinds) so don't even try to look those up.
123- if (hasNonTypeGenericArguments (description ))
195+ if (hasNonTypeGenericArguments (generics ))
124196 return nullptr ;
125197
198+ if (!isPotentialPrespecializedPointer (prespecialized, description)) {
199+ LOG (" Rejecting descriptor %p, not in the shared cache" ,
200+ (const void *)description);
201+ return nullptr ;
202+ }
203+
204+ auto numKeyArguments = generics->getGenericContextHeader ().NumKeyArguments ;
205+ for (unsigned i = 0 ; i < numKeyArguments; i++) {
206+ if (!isPotentialPrespecializedPointer (prespecialized, arguments[i])) {
207+ LOG (" Rejecting argument %u %p to descriptor %p, not in the shared cache" ,
208+ i, arguments[i], (const void *)description);
209+ return nullptr ;
210+ }
211+ }
212+
126213 Demangler dem;
127214 auto mangleNode = _buildDemanglingForGenericType (description, arguments, dem);
128215 if (!mangleNode) {
129- if (SWIFT_UNLIKELY (runtime::environment::
130- SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ()))
131- fprintf (stderr,
132- " Prespecializations library: failed to build demangling with "
133- " descriptor %p.\n " ,
134- description);
216+ LOG (" failed to build demangling with descriptor %p." , description);
135217 return nullptr ;
136218 }
137219
@@ -159,10 +241,7 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
159241 auto *metadataMap = data->getMetadataMap ();
160242 auto *element = metadataMap->find (key.data (), key.size ());
161243 auto *result = element ? element->value : nullptr ;
162- if (SWIFT_UNLIKELY (runtime::environment::
163- SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ()))
164- fprintf (stderr, " Prespecializations library: found %p for key '%.*s'.\n " ,
165- result, (int )key.size (), key.data ());
244+ LOG (" found %p for key '%.*s'." , result, (int )key.size (), key.data ());
166245 return result;
167246}
168247
0 commit comments