10
10
11
11
#include " Discovery.h"
12
12
13
+ #include < cstdlib>
14
+ #include < cstdint>
15
+ #include < cstring>
16
+ #include < type_traits>
17
+ #include < vector>
18
+
13
19
#if defined(SWT_NO_DYNAMIC_LINKING)
14
20
#pragma mark - Statically-linked section bounds
15
21
@@ -31,103 +37,22 @@ static const char typeMetadataSectionBegin = 0;
31
37
static const char & typeMetadataSectionEnd = typeMetadataSectionBegin;
32
38
#endif
33
39
34
- // / The bounds of the test content section statically linked into the image
35
- // / containing Swift Testing.
36
40
const void *_Nonnull const SWTTestContentSectionBounds[2 ] = {
37
- &testContentSectionBegin,
38
- &testContentSectionEnd
41
+ &testContentSectionBegin, &testContentSectionEnd
39
42
};
40
43
41
- // / The bounds of the type metadata section statically linked into the image
42
- // / containing Swift Testing.
43
44
const void *_Nonnull const SWTTypeMetadataSectionBounds[2 ] = {
44
- &typeMetadataSectionBegin,
45
- &typeMetadataSectionEnd
45
+ &typeMetadataSectionBegin, &typeMetadataSectionEnd
46
46
};
47
47
#endif
48
48
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
-
122
49
#pragma mark - Swift ABI
123
50
124
51
#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 )
127
53
#else
128
- #define SWT_PTRAUTH (...)
54
+ #define SWT_PTRAUTH_SWIFT_TYPE_DESCRIPTOR
129
55
#endif
130
- #define SWT_PTRAUTH_SWIFT_TYPE_DESCRIPTOR SWT_PTRAUTH (ptrauth_key_process_independent_data, 1 , 0xae86 )
131
56
132
57
// / A type representing a pointer relative to itself.
133
58
// /
@@ -164,10 +89,6 @@ struct SWTRelativePointer {
164
89
#endif
165
90
return reinterpret_cast <const T *>(result);
166
91
}
167
-
168
- const T *_Nullable operator ->(void ) const & {
169
- return get ();
170
- }
171
92
};
172
93
173
94
// / A type representing a 32-bit absolute function pointer, usually used on platforms
@@ -184,10 +105,6 @@ struct SWTAbsoluteFunctionPointer {
184
105
const T *_Nullable get (void ) const & {
185
106
return _pointer;
186
107
}
187
-
188
- const T *_Nullable operator ->(void ) const & {
189
- return get ();
190
- }
191
108
};
192
109
193
110
// / A type representing a pointer relative to itself with low bits reserved for
@@ -270,14 +187,16 @@ struct SWTTypeMetadataRecord {
270
187
}
271
188
};
272
189
273
- #pragma mark -
190
+ #pragma mark - Legacy test discovery
274
191
275
192
void **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 ;
278
195
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 ();
281
200
if (!contextDescriptor) {
282
201
// This type metadata record is invalid (or we don't understand how to
283
202
// get its context descriptor), so skip it.
@@ -297,14 +216,19 @@ void **swt_copyTypesWithNamesContaining(const void *sectionBegin, size_t section
297
216
}
298
217
299
218
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 ;
301
229
}
302
230
}
303
231
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;
310
234
}
0 commit comments