Skip to content

Commit 6c59410

Browse files
committed
[ReflectionMirror] Change swift-reflection-test.c to use addReflectionInfo on non-Macho platforms.
1 parent 6d10ac9 commit 6c59410

File tree

3 files changed

+273
-2
lines changed

3 files changed

+273
-2
lines changed

stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import Darwin
2424
let RequestInstanceKind = "k"
2525
let RequestInstanceAddress = "i"
2626
let RequestReflectionInfos = "r"
27+
let RequestImages = "m"
2728
let RequestReadBytes = "b"
2829
let RequestSymbolAddress = "s"
2930
let RequestStringLength = "l"
@@ -45,12 +46,98 @@ public enum InstanceKind : UInt8 {
4546
case Closure
4647
}
4748

49+
/// Represents a section in a loaded image in this process.
50+
internal struct Section {
51+
/// The absolute start address of the section's data in this address space.
52+
let startAddress: UnsafeRawPointer
53+
54+
/// The size of the section in bytes.
55+
let size: UInt
56+
}
57+
58+
/// Holds the addresses and sizes of sections related to reflection
59+
internal struct ReflectionInfo : Sequence {
60+
/// The name of the loaded image
61+
internal let imageName: String
62+
63+
/// Reflection metadata sections
64+
internal let fieldmd: Section?
65+
internal let assocty: Section?
66+
internal let builtin: Section?
67+
internal let capture: Section?
68+
internal let typeref: Section?
69+
internal let reflstr: Section?
70+
71+
internal func makeIterator() -> AnyIterator<Section?> {
72+
return AnyIterator([
73+
fieldmd,
74+
assocty,
75+
builtin,
76+
capture,
77+
typeref,
78+
reflstr
79+
].makeIterator())
80+
}
81+
}
82+
4883
#if arch(x86_64) || arch(arm64)
4984
typealias MachHeader = mach_header_64
5085
#else
5186
typealias MachHeader = mach_header
5287
#endif
5388

89+
/// Get the location and size of a section in a binary.
90+
///
91+
/// - Parameter name: The name of the section
92+
/// - Parameter imageHeader: A pointer to the Mach header describing the
93+
/// image.
94+
/// - Returns: A `Section` containing the address and size, or `nil` if there
95+
/// is no section by the given name.
96+
internal func getSectionInfo(_ name: String,
97+
_ imageHeader: UnsafePointer<MachHeader>) -> Section? {
98+
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
99+
var size: UInt = 0
100+
let address = getsectiondata(imageHeader, "__TEXT", name, &size)
101+
guard let nonNullAddress = address else { return nil }
102+
guard size != 0 else { return nil }
103+
return Section(startAddress: nonNullAddress, size: size)
104+
}
105+
106+
/// Get the Swift Reflection section locations for a loaded image.
107+
///
108+
/// An image of interest must have the following sections in the __DATA
109+
/// segment:
110+
/// - __swift5_fieldmd
111+
/// - __swift5_assocty
112+
/// - __swift5_builtin
113+
/// - __swift5_capture
114+
/// - __swift5_typeref
115+
/// - __swift5_reflstr (optional, may have been stripped out)
116+
///
117+
/// - Parameter i: The index of the loaded image as reported by Dyld.
118+
/// - Returns: A `ReflectionInfo` containing the locations of all of the
119+
/// needed sections, or `nil` if the image doesn't contain all of them.
120+
internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? {
121+
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
122+
let header = unsafeBitCast(_dyld_get_image_header(i),
123+
to: UnsafePointer<MachHeader>.self)
124+
125+
let imageName = _dyld_get_image_name(i)!
126+
let fieldmd = getSectionInfo("__swift5_fieldmd", header)
127+
let assocty = getSectionInfo("__swift5_assocty", header)
128+
let builtin = getSectionInfo("__swift5_builtin", header)
129+
let capture = getSectionInfo("__swift5_capture", header)
130+
let typeref = getSectionInfo("__swift5_typeref", header)
131+
let reflstr = getSectionInfo("__swift5_reflstr", header)
132+
return ReflectionInfo(imageName: String(validatingUTF8: imageName)!,
133+
fieldmd: fieldmd,
134+
assocty: assocty,
135+
builtin: builtin,
136+
capture: capture,
137+
typeref: typeref,
138+
reflstr: reflstr)
139+
}
140+
54141
/// Get the TEXT segment location and size for a loaded image.
55142
///
56143
/// - Parameter i: The index of the loaded image as reported by Dyld.
@@ -107,6 +194,24 @@ internal func readUInt() -> UInt {
107194
/// Send all known `ReflectionInfo`s for all images loaded in the current
108195
/// process.
109196
internal func sendReflectionInfos() {
197+
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
198+
let infos = (0..<_dyld_image_count()).compactMap(getReflectionInfoForImage)
199+
200+
var numInfos = infos.count
201+
debugLog("\(numInfos) reflection info bundles.")
202+
precondition(numInfos >= 1)
203+
sendBytes(from: &numInfos, count: MemoryLayout<UInt>.size)
204+
for info in infos {
205+
debugLog("Sending info for \(info.imageName)")
206+
for section in info {
207+
sendValue(section?.startAddress)
208+
sendValue(section?.size ?? 0)
209+
}
210+
}
211+
}
212+
213+
/// Send all loadedimages loaded in the current process.
214+
internal func sendImages() {
110215
debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
111216
let infos = (0..<_dyld_image_count()).map(getAddressInfoForImage)
112217

@@ -200,6 +305,8 @@ internal func reflect(instanceAddress: UInt, kind: InstanceKind) {
200305
sendValue(instanceAddress)
201306
case String(validatingUTF8: RequestReflectionInfos)!:
202307
sendReflectionInfos()
308+
case String(validatingUTF8: RequestImages)!:
309+
sendImages()
203310
case String(validatingUTF8: RequestReadBytes)!:
204311
sendBytes()
205312
case String(validatingUTF8: RequestSymbolAddress)!:

tools/swift-reflection-test/messages.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
static const char *REQUEST_INSTANCE_KIND = "k\n";
1414
static const char *REQUEST_INSTANCE_ADDRESS = "i\n";
1515
static const char *REQUEST_REFLECTION_INFO = "r\n";
16+
static const char *REQUEST_IMAGES = "m\n";
1617
static const char *REQUEST_READ_BYTES = "b\n";
1718
static const char *REQUEST_SYMBOL_ADDRESS = "s\n";
1819
static const char *REQUEST_STRING_LENGTH = "l\n";

tools/swift-reflection-test/swift-reflection-test.c

Lines changed: 165 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ typedef struct PipeMemoryReader {
3434
int from_child[2];
3535
} PipeMemoryReader;
3636

37+
typedef struct RemoteSection {
38+
uintptr_t StartAddress;
39+
uintptr_t Size;
40+
uintptr_t EndAddress;
41+
} RemoteSection;
42+
43+
typedef struct RemoteReflectionInfo {
44+
RemoteSection fieldmd;
45+
RemoteSection assocty;
46+
RemoteSection builtin;
47+
RemoteSection capture;
48+
RemoteSection typeref;
49+
RemoteSection reflstr;
50+
uintptr_t StartAddress;
51+
size_t TotalSize;
52+
} RemoteReflectionInfo;
53+
3754
static void errorAndExit(const char *message) {
3855
fprintf(stderr, "%s\n", message);
3956
abort();
@@ -44,6 +61,77 @@ static void errnoAndExit(const char *message) {
4461
abort();
4562
}
4663

64+
static swift_reflection_section_t
65+
makeLocalSection(void *Buffer, RemoteSection Section,
66+
RemoteReflectionInfo Info) {
67+
if (Section.Size == 0) {
68+
swift_reflection_section_t LS = {NULL, NULL};
69+
return LS;
70+
}
71+
72+
uintptr_t Base
73+
= (uintptr_t)Buffer + Section.StartAddress - Info.StartAddress;
74+
swift_reflection_section_t LS = {
75+
(void *)Base,
76+
(void *)(Base + Section.Size)
77+
};
78+
return LS;
79+
}
80+
81+
static
82+
uintptr_t getStartAddress(const RemoteSection Sections[], size_t Count) {
83+
uintptr_t Start = 0;
84+
for (size_t i = 0; i < Count; ++i) {
85+
if (Sections[i].StartAddress != 0) {
86+
if (Start != 0)
87+
Start = MIN(Start, Sections[i].StartAddress);
88+
else
89+
Start = Sections[i].StartAddress;
90+
}
91+
}
92+
return Start;
93+
}
94+
95+
static
96+
uintptr_t getEndAddress(const RemoteSection Sections[], size_t Count) {
97+
uintptr_t End = 0;
98+
for (size_t i = 0; i < Count; ++i) {
99+
if (Sections[i].StartAddress != 0)
100+
End = MAX(End, Sections[i].EndAddress);
101+
}
102+
return End;
103+
}
104+
105+
static
106+
RemoteReflectionInfo makeRemoteReflectionInfo(RemoteSection fieldmd,
107+
RemoteSection assocty,
108+
RemoteSection builtin,
109+
RemoteSection capture,
110+
RemoteSection typeref,
111+
RemoteSection reflstr) {
112+
RemoteReflectionInfo Info = {
113+
fieldmd,
114+
assocty,
115+
builtin,
116+
capture,
117+
typeref,
118+
reflstr,
119+
0,
120+
0
121+
};
122+
123+
const RemoteSection Sections[6] = {
124+
fieldmd, assocty, builtin, capture, typeref, reflstr
125+
};
126+
127+
Info.StartAddress = getStartAddress(Sections, 6);
128+
129+
uintptr_t EndAddress = getEndAddress(Sections, 6);
130+
Info.TotalSize = EndAddress - Info.StartAddress;
131+
132+
return Info;
133+
}
134+
47135
static const size_t ReadEnd = 0;
48136
static const size_t WriteEnd = 1;
49137

@@ -165,11 +253,24 @@ PipeMemoryReader createPipeMemoryReader() {
165253
return Reader;
166254
}
167255

256+
static
257+
RemoteSection makeRemoteSection(const PipeMemoryReader *Reader) {
258+
uintptr_t Start;
259+
size_t Size;
260+
261+
PipeMemoryReader_collectBytesFromPipe(Reader, &Start, sizeof(Start));
262+
PipeMemoryReader_collectBytesFromPipe(Reader, &Size, sizeof(Size));
263+
264+
RemoteSection RS = {Start, Size, Start + Size};
265+
return RS;
266+
}
267+
268+
#if defined(__APPLE__) && defined(__MACH__)
168269
static void
169-
PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC,
270+
PipeMemoryReader_receiveImages(SwiftReflectionContextRef RC,
170271
const PipeMemoryReader *Reader) {
171272
int WriteFD = PipeMemoryReader_getParentWriteFD(Reader);
172-
write(WriteFD, REQUEST_REFLECTION_INFO, 2);
273+
write(WriteFD, REQUEST_IMAGES, 2);
173274
size_t NumReflectionInfos;
174275
PipeMemoryReader_collectBytesFromPipe(Reader, &NumReflectionInfos,
175276
sizeof(NumReflectionInfos));
@@ -188,6 +289,64 @@ PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC,
188289

189290
free(Images);
190291
}
292+
#endif
293+
294+
static void
295+
PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC,
296+
const PipeMemoryReader *Reader) {
297+
int WriteFD = PipeMemoryReader_getParentWriteFD(Reader);
298+
write(WriteFD, REQUEST_REFLECTION_INFO, 2);
299+
size_t NumReflectionInfos;
300+
PipeMemoryReader_collectBytesFromPipe(Reader, &NumReflectionInfos,
301+
sizeof(NumReflectionInfos));
302+
303+
if (NumReflectionInfos == 0)
304+
return;
305+
306+
RemoteReflectionInfo *RemoteInfos = calloc(NumReflectionInfos,
307+
sizeof(RemoteReflectionInfo));
308+
if (RemoteInfos == NULL)
309+
errnoAndExit("malloc failed");
310+
311+
for (size_t i = 0; i < NumReflectionInfos; ++i) {
312+
RemoteInfos[i] = makeRemoteReflectionInfo(
313+
makeRemoteSection(Reader),
314+
makeRemoteSection(Reader),
315+
makeRemoteSection(Reader),
316+
makeRemoteSection(Reader),
317+
makeRemoteSection(Reader),
318+
makeRemoteSection(Reader));
319+
}
320+
321+
// Now pull in the remote sections into our address space.
322+
323+
for (size_t i = 0; i < NumReflectionInfos; ++i) {
324+
RemoteReflectionInfo RemoteInfo = RemoteInfos[i];
325+
326+
void *Buffer = malloc(RemoteInfo.TotalSize);
327+
328+
int Success = PipeMemoryReader_readBytes((void *)Reader,
329+
RemoteInfo.StartAddress,
330+
Buffer,
331+
RemoteInfo.TotalSize);
332+
if (!Success)
333+
errorAndExit("Couldn't read reflection information");
334+
335+
swift_reflection_info_t Info = {
336+
{makeLocalSection(Buffer, RemoteInfo.fieldmd, RemoteInfo), 0},
337+
{makeLocalSection(Buffer, RemoteInfo.assocty, RemoteInfo), 0},
338+
{makeLocalSection(Buffer, RemoteInfo.builtin, RemoteInfo), 0},
339+
{makeLocalSection(Buffer, RemoteInfo.capture, RemoteInfo), 0},
340+
{makeLocalSection(Buffer, RemoteInfo.typeref, RemoteInfo), 0},
341+
{makeLocalSection(Buffer, RemoteInfo.reflstr, RemoteInfo), 0},
342+
/*LocalStartAddress*/ (uintptr_t) Buffer,
343+
/*RemoteStartAddress*/ RemoteInfo.StartAddress,
344+
};
345+
swift_reflection_addReflectionInfo(RC, Info);
346+
}
347+
348+
free(RemoteInfos);
349+
}
191350

192351
uint64_t PipeMemoryReader_getStringLength(void *Context, swift_addr_t Address) {
193352
const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context;
@@ -291,7 +450,11 @@ int doDumpHeapInstance(const char *BinaryFilename) {
291450
if (PointerSize != sizeof(uintptr_t))
292451
errorAndExit("Child process had unexpected architecture");
293452

453+
#if defined(__APPLE__) && defined(__MACH__)
454+
PipeMemoryReader_receiveImages(RC, &Pipe);
455+
#else
294456
PipeMemoryReader_receiveReflectionInfo(RC, &Pipe);
457+
#endif
295458

296459
while (1) {
297460
InstanceKind Kind = PipeMemoryReader_receiveInstanceKind(&Pipe);

0 commit comments

Comments
 (0)