1010
1111#include " Discovery.h"
1212
13+ #include < cstdlib>
14+ #include < cstdint>
15+ #include < cstring>
16+ #include < type_traits>
17+ #include < vector>
18+
1319#if defined(SWT_NO_DYNAMIC_LINKING)
1420#pragma mark - Statically-linked section bounds
1521
@@ -31,103 +37,22 @@ static const char typeMetadataSectionBegin = 0;
3137static const char & typeMetadataSectionEnd = typeMetadataSectionBegin;
3238#endif
3339
34- // / The bounds of the test content section statically linked into the image
35- // / containing Swift Testing.
3640const void *_Nonnull const SWTTestContentSectionBounds[2 ] = {
37- &testContentSectionBegin,
38- &testContentSectionEnd
41+ &testContentSectionBegin, &testContentSectionEnd
3942};
4043
41- // / The bounds of the type metadata section statically linked into the image
42- // / containing Swift Testing.
4344const void *_Nonnull const SWTTypeMetadataSectionBounds[2 ] = {
44- &typeMetadataSectionBegin,
45- &typeMetadataSectionEnd
45+ &typeMetadataSectionBegin, &typeMetadataSectionEnd
4646};
4747#endif
4848
49- #pragma mark - Legacy test discovery
50-
51- #include < algorithm>
52- #include < array>
53- #include < atomic>
54- #include < cstring>
55- #include < iterator>
56- #include < memory>
57- #include < tuple>
58- #include < type_traits>
59- #include < vector>
60- #include < optional>
61-
62- // / Enumerate over all Swift type metadata sections in the current process.
63- // /
64- // / - Parameters:
65- // / - body: A function to call once for every section in the current process.
66- // / A pointer to the first type metadata record and the number of records
67- // / are passed to this function.
68- template <typename SectionEnumerator>
69- static void enumerateTypeMetadataSections (const SectionEnumerator& body);
70-
71- // / A type that acts as a C++ [Allocator](https://en.cppreference.com/w/cpp/named_req/Allocator)
72- // / without using global `operator new` or `operator delete`.
73- // /
74- // / This type is necessary because global `operator new` and `operator delete`
75- // / can be overridden in developer-supplied code and cause deadlocks or crashes
76- // / when subsequently used while holding a dyld- or libobjc-owned lock. Using
77- // / `std::malloc()` and `std::free()` allows the use of C++ container types
78- // / without this risk.
79- template <typename T>
80- struct SWTHeapAllocator {
81- using value_type = T;
82-
83- T *allocate (size_t count) {
84- return reinterpret_cast <T *>(std::calloc (count, sizeof (T)));
85- }
86-
87- void deallocate (T *ptr, size_t count) {
88- std::free (ptr);
89- }
90- };
91-
92- // / A structure describing the bounds of a Swift metadata section.
93- // /
94- // / The template argument `T` is the element type of the metadata section.
95- // / Instances of this type can be used with a range-based `for`-loop to iterate
96- // / the contents of the section.
97- template <typename T>
98- struct SWTSectionBounds {
99- // / The base address of the image containing the section, if known.
100- const void *imageAddress;
101-
102- // / The base address of the section.
103- const void *start;
104-
105- // / The size of the section in bytes.
106- size_t size;
107-
108- const struct SWTTypeMetadataRecord *begin (void ) const {
109- return reinterpret_cast <const T *>(start);
110- }
111-
112- const struct SWTTypeMetadataRecord *end (void ) const {
113- return reinterpret_cast <const T *>(reinterpret_cast <uintptr_t >(start) + size);
114- }
115- };
116-
117- // / A type that acts as a C++ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
118- // / and which contains a sequence of instances of `SWTSectionBounds<T>`.
119- template <typename T>
120- using SWTSectionBoundsList = std::vector<SWTSectionBounds<T>, SWTHeapAllocator<SWTSectionBounds<T>>>;
121-
12249#pragma mark - Swift ABI
12350
12451#if defined(__PTRAUTH_INTRINSICS__)
125- #include < ptrauth.h>
126- #define SWT_PTRAUTH __ptrauth
52+ #define SWT_PTRAUTH_SWIFT_TYPE_DESCRIPTOR __ptrauth (ptrauth_key_process_independent_data, 1 , 0xae86 )
12753#else
128- #define SWT_PTRAUTH (...)
54+ #define SWT_PTRAUTH_SWIFT_TYPE_DESCRIPTOR
12955#endif
130- #define SWT_PTRAUTH_SWIFT_TYPE_DESCRIPTOR SWT_PTRAUTH (ptrauth_key_process_independent_data, 1 , 0xae86 )
13156
13257// / A type representing a pointer relative to itself.
13358// /
@@ -164,10 +89,6 @@ struct SWTRelativePointer {
16489#endif
16590 return reinterpret_cast <const T *>(result);
16691 }
167-
168- const T *_Nullable operator ->(void ) const & {
169- return get ();
170- }
17192};
17293
17394// / A type representing a 32-bit absolute function pointer, usually used on platforms
@@ -184,10 +105,6 @@ struct SWTAbsoluteFunctionPointer {
184105 const T *_Nullable get (void ) const & {
185106 return _pointer;
186107 }
187-
188- const T *_Nullable operator ->(void ) const & {
189- return get ();
190- }
191108};
192109
193110// / A type representing a pointer relative to itself with low bits reserved for
@@ -270,14 +187,16 @@ struct SWTTypeMetadataRecord {
270187 }
271188};
272189
273- #pragma mark -
190+ #pragma mark - Legacy test discovery
274191
275192void **swt_copyTypesWithNamesContaining (const void *sectionBegin, size_t sectionSize, const char *nameSubstring, size_t *outCount) {
276- SWTSectionBounds<SWTTypeMetadataRecord> sb = { nullptr , sectionBegin, sectionSize } ;
277- std::vector< void *, SWTHeapAllocator< void *>> result ;
193+ void **result = nullptr ;
194+ size_t resultCount = 0 ;
278195
279- for (const auto & record : sb) {
280- auto contextDescriptor = record.getContextDescriptor ();
196+ auto records = reinterpret_cast <const SWTTypeMetadataRecord *>(sectionBegin);
197+ size_t recordCount = sectionSize / sizeof (SWTTypeMetadataRecord);
198+ for (size_t i = 0 ; i < recordCount; i++) {
199+ auto contextDescriptor = records[i].getContextDescriptor ();
281200 if (!contextDescriptor) {
282201 // This type metadata record is invalid (or we don't understand how to
283202 // get its context descriptor), so skip it.
@@ -297,14 +216,19 @@ void **swt_copyTypesWithNamesContaining(const void *sectionBegin, size_t section
297216 }
298217
299218 if (void *typeMetadata = contextDescriptor->getMetadata ()) {
300- result.push_back (typeMetadata);
219+ if (!result) {
220+ // This is the first matching type we've found. That presumably means
221+ // we'll find more, so allocate enough space for all remaining types in
222+ // the section. Is this necessarily space-efficient? No, but this
223+ // allocation is short-lived and is immediately copied and freed in the
224+ // Swift caller.
225+ result = reinterpret_cast <void **>(std::calloc (recordCount - i, sizeof (void *)));
226+ }
227+ result[resultCount] = typeMetadata;
228+ resultCount += 1 ;
301229 }
302230 }
303231
304- auto resultCopy = reinterpret_cast <void **>(std::calloc (sizeof (void *), result.size ()));
305- if (resultCopy) {
306- std::uninitialized_move (result.begin (), result.end (), resultCopy);
307- *outCount = result.size ();
308- }
309- return resultCopy;
232+ *outCount = resultCount;
233+ return result;
310234}
0 commit comments