Skip to content

Commit c488632

Browse files
authored
Remove some remnants of the C++ section discovery code that we no longer need. (#905)
This PR removes additional C++ section discovery code that is no longer needed. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent 52aa355 commit c488632

File tree

5 files changed

+50
-149
lines changed

5 files changed

+50
-149
lines changed

Sources/Testing/Discovery+Platform.swift

+8-24
Original file line numberDiff line numberDiff line change
@@ -72,36 +72,20 @@ private let _startCollectingSectionBounds: Void = {
7272
return
7373
}
7474

75-
// If this image contains the Swift section we need, acquire the lock and
75+
// If this image contains the Swift section(s) we need, acquire the lock and
7676
// store the section's bounds.
77-
let testContentSectionBounds: SectionBounds? = {
77+
func findSectionBounds(forSectionNamed segmentName: String, _ sectionName: String, ofKind kind: SectionBounds.Kind) {
7878
var size = CUnsignedLong(0)
79-
if let start = getsectiondata(mh, "__DATA_CONST", "__swift5_tests", &size), size > 0 {
79+
if let start = getsectiondata(mh, segmentName, sectionName, &size), size > 0 {
8080
let buffer = UnsafeRawBufferPointer(start: start, count: Int(clamping: size))
81-
return SectionBounds(imageAddress: mh, buffer: buffer)
82-
}
83-
return nil
84-
}()
85-
86-
let typeMetadataSectionBounds: SectionBounds? = {
87-
var size = CUnsignedLong(0)
88-
if let start = getsectiondata(mh, "__TEXT", "__swift5_types", &size), size > 0 {
89-
let buffer = UnsafeRawBufferPointer(start: start, count: Int(clamping: size))
90-
return SectionBounds(imageAddress: mh, buffer: buffer)
91-
}
92-
return nil
93-
}()
94-
95-
if testContentSectionBounds != nil || typeMetadataSectionBounds != nil {
96-
_sectionBounds.withLock { sectionBounds in
97-
if let testContentSectionBounds {
98-
sectionBounds[.testContent]!.append(testContentSectionBounds)
99-
}
100-
if let typeMetadataSectionBounds {
101-
sectionBounds[.typeMetadata]!.append(typeMetadataSectionBounds)
81+
let sb = SectionBounds(imageAddress: mh, buffer: buffer)
82+
_sectionBounds.withLock { sectionBounds in
83+
sectionBounds[kind]!.append(sb)
10284
}
10385
}
10486
}
87+
findSectionBounds(forSectionNamed: "__DATA_CONST", "__swift5_tests", ofKind: .testContent)
88+
findSectionBounds(forSectionNamed: "__TEXT", "__swift5_types", ofKind: .typeMetadata)
10589
}
10690

10791
#if _runtime(_ObjC)

Sources/Testing/Test+Discovery+Legacy.swift

+9-11
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,13 @@ let exitTestContainerTypeNameMagic = "__🟠$exit_test_body__"
5757
///
5858
/// - Returns: A sequence of Swift types whose names contain `nameSubstring`.
5959
func types(withNamesContaining nameSubstring: String) -> some Sequence<Any.Type> {
60-
SectionBounds.all(.typeMetadata).lazy
61-
.map { sb in
62-
var count = 0
63-
let start = swt_copyTypes(in: sb.buffer.baseAddress!, sb.buffer.count, withNamesContaining: nameSubstring, count: &count)
64-
defer {
65-
free(start)
66-
}
67-
return start.withMemoryRebound(to: Any.Type.self, capacity: count) { start in
68-
Array(UnsafeBufferPointer(start: start, count: count))
69-
}
70-
}.joined()
60+
SectionBounds.all(.typeMetadata).lazy.flatMap { sb in
61+
var count = 0
62+
let start = swt_copyTypes(in: sb.buffer.baseAddress!, sb.buffer.count, withNamesContaining: nameSubstring, count: &count)
63+
defer {
64+
free(start)
65+
}
66+
return UnsafeBufferPointer(start: start, count: count)
67+
.withMemoryRebound(to: Any.Type.self) { Array($0) }
68+
}
7169
}

Sources/_TestingInternals/Discovery.cpp

+29-105
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
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;
3137
static const char& typeMetadataSectionEnd = typeMetadataSectionBegin;
3238
#endif
3339

34-
/// The bounds of the test content section statically linked into the image
35-
/// containing Swift Testing.
3640
const 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.
4344
const 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

275192
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;
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
}

Sources/_TestingInternals/Versions.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@
1010

1111
#include "Versions.h"
1212

13-
#if defined(_SWT_TESTING_LIBRARY_VERSION) && !defined(SWT_TESTING_LIBRARY_VERSION)
14-
#warning _SWT_TESTING_LIBRARY_VERSION is deprecated
15-
#warning Define SWT_TESTING_LIBRARY_VERSION and optionally SWT_TARGET_TRIPLE instead
16-
#define SWT_TESTING_LIBRARY_VERSION _SWT_TESTING_LIBRARY_VERSION
17-
#endif
18-
1913
const char *swt_getTestingLibraryVersion(void) {
2014
#if defined(SWT_TESTING_LIBRARY_VERSION)
2115
return SWT_TESTING_LIBRARY_VERSION;

Sources/_TestingInternals/include/Discovery.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,10 @@ SWT_EXTERN const void *_Nonnull const SWTTypeMetadataSectionBounds[2];
9494
/// - nameSubstring: A string which the names of matching classes all contain.
9595
/// - outCount: On return, the number of type metadata pointers returned.
9696
///
97-
/// - Returns: A pointer to an array of type metadata pointers. The caller is
98-
/// responsible for freeing this memory with `free()` when done.
99-
SWT_EXTERN void *_Nonnull *_Nonnull swt_copyTypesWithNamesContaining(
97+
/// - Returns: A pointer to an array of type metadata pointers, or `nil` if no
98+
/// matching types were found. The caller is responsible for freeing this
99+
/// memory with `free()` when done.
100+
SWT_EXTERN void *_Nonnull *_Nullable swt_copyTypesWithNamesContaining(
100101
const void *sectionBegin,
101102
size_t sectionSize,
102103
const char *nameSubstring,

0 commit comments

Comments
 (0)