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