diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 7ebbf49dc3589..fd19354a4ce7a 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -509,6 +509,7 @@ class MetadataReader { if (!meta || meta->getKind() != MetadataKind::Class) return None; +#if SWIFT_OBJC_INTEROP // The following algorithm only works on the non-fragile Apple runtime. // Grab the RO-data pointer. This part is not ABI. @@ -524,6 +525,23 @@ class MetadataReader { return None; return start; +#else + // All swift class instances start with an isa pointer, + // followed by the retain counts (which are the size of a long long). + size_t isaAndRetainCountSize = sizeof(StoredSize) + sizeof(long long); + size_t start = isaAndRetainCountSize; + + auto classMeta = cast>(meta); + while (classMeta->Superclass) { + classMeta = cast>( + readMetadata(classMeta->Superclass)); + + // Subtract the size contribution of the isa and retain counts from + // the super class. + start += classMeta->InstanceSize - isaAndRetainCountSize; + } + return start; +#endif } /// Given a pointer to the metadata, attempt to read the value diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h index e8232a46df278..08f8c3cca83ca 100644 --- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h +++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h @@ -80,6 +80,11 @@ void swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef, swift_reflection_info_t Info); +/// Add reflection sections from a loaded Swift image. +SWIFT_REMOTE_MIRROR_LINKAGE +void swift_reflection_addReflectionMappingInfo( + SwiftReflectionContextRef ContextRef, swift_reflection_mapping_info_t Info); + /// Add reflection information from a loaded Swift image. /// Returns true on success, false if the image's memory couldn't be read. SWIFT_REMOTE_MIRROR_LINKAGE diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h index 0c85cc4486f31..13331659e805c 100644 --- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h +++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h @@ -48,11 +48,23 @@ typedef struct swift_reflection_section { void *End; } swift_reflection_section_t; +/// Represents the remote address and size of an image's section +typedef struct swift_remote_reflection_section { + uintptr_t StartAddress; + uintptr_t Size; +} swift_remote_reflection_section_t; + typedef struct swift_reflection_section_pair { swift_reflection_section_t section; swift_reflection_ptr_t offset; ///< DEPRECATED. Must be zero } swift_reflection_section_pair_t; +/// Represents the mapping between an image sections's local and remote addresses +typedef struct swift_reflection_section_mapping { + swift_reflection_section_t local_section; + swift_remote_reflection_section_t remote_section; +} swift_reflection_section_mapping_t; + /// Represents the set of Swift reflection sections of an image. /// Not all sections may be present. /// @@ -71,6 +83,16 @@ typedef struct swift_reflection_info { swift_reflection_ptr_t RemoteStartAddress; } swift_reflection_info_t; +/// Represents the set of Swift reflection sections of an image, +typedef struct swift_reflection_mapping_info { + swift_reflection_section_mapping_t field; + swift_reflection_section_mapping_t associated_types; + swift_reflection_section_mapping_t builtin_types; + swift_reflection_section_mapping_t capture; + swift_reflection_section_mapping_t type_references; + swift_reflection_section_mapping_t reflection_strings; +} swift_reflection_mapping_info_t; + /// The layout kind of a Swift type. typedef enum swift_layout_kind { // Nothing is known about the size or contents of this value. diff --git a/stdlib/private/CMakeLists.txt b/stdlib/private/CMakeLists.txt index 46fff31994d92..b1cf2ed6b1b2f 100644 --- a/stdlib/private/CMakeLists.txt +++ b/stdlib/private/CMakeLists.txt @@ -23,8 +23,10 @@ if(SWIFT_BUILD_SDK_OVERLAY) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") add_subdirectory(StdlibUnittestFoundationExtras) - if (SWIFT_INCLUDE_TESTS) - add_subdirectory(SwiftReflectionTest) - endif() + endif() + # Currently SwiftReflectionTest cannot be built on Windows, due to + # dependencies on POSIX symbols + if (SWIFT_INCLUDE_TESTS AND (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")) + add_subdirectory(SwiftReflectionTest) endif() endif() diff --git a/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift b/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift index 7026959536d9c..b077bd4923a2e 100644 --- a/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift +++ b/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift @@ -16,11 +16,6 @@ // //===----------------------------------------------------------------------===// -// FIXME: Make this work with Linux - -import MachO -import Darwin - let RequestInstanceKind = "k" let RequestInstanceAddress = "i" let RequestReflectionInfos = "r" @@ -31,56 +26,10 @@ let RequestStringLength = "l" let RequestDone = "d" let RequestPointerSize = "p" -internal func debugLog(_ message: @autoclosure () -> String) { -#if DEBUG_LOG - fputs("Child: \(message())\n", stderr) - fflush(stderr) -#endif -} - -public enum InstanceKind : UInt8 { - case None - case Object - case Existential - case ErrorExistential - case Closure - case Enum - case EnumValue -} - -/// Represents a section in a loaded image in this process. -internal struct Section { - /// The absolute start address of the section's data in this address space. - let startAddress: UnsafeRawPointer - - /// The size of the section in bytes. - let size: UInt -} -/// Holds the addresses and sizes of sections related to reflection -internal struct ReflectionInfo : Sequence { - /// The name of the loaded image - internal let imageName: String - - /// Reflection metadata sections - internal let fieldmd: Section? - internal let assocty: Section? - internal let builtin: Section? - internal let capture: Section? - internal let typeref: Section? - internal let reflstr: Section? - - internal func makeIterator() -> AnyIterator { - return AnyIterator([ - fieldmd, - assocty, - builtin, - capture, - typeref, - reflstr - ].makeIterator()) - } -} +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) +import MachO +import Darwin #if arch(x86_64) || arch(arm64) typealias MachHeader = mach_header_64 @@ -105,6 +54,36 @@ internal func getSectionInfo(_ name: String, return Section(startAddress: nonNullAddress, size: size) } +/// Get the TEXT segment location and size for a loaded image. +/// +/// - Parameter i: The index of the loaded image as reported by Dyld. +/// - Returns: The image name, address, and size. +internal func getAddressInfoForImage(atIndex i: UInt32) -> + (name: String, address: UnsafeMutablePointer?, size: UInt) { + debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") } + let header = unsafeBitCast(_dyld_get_image_header(i), + to: UnsafePointer.self) + let name = String(validatingUTF8: _dyld_get_image_name(i)!)! + var size: UInt = 0 + let address = getsegmentdata(header, "__TEXT", &size) + return (name, address, size) +} + +/// Send all loadedimages loaded in the current process. +internal func sendImages() { + debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") } + let infos = (0..= 1) + sendValue(infos.count) + for (name, address, size) in infos { + debugLog("Sending info for \(name)") + sendValue(address) + sendValue(size) + } +} + /// Get the Swift Reflection section locations for a loaded image. /// /// An image of interest must have the following sections in the __TEXT @@ -140,19 +119,100 @@ internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? { reflstr: reflstr) } -/// Get the TEXT segment location and size for a loaded image. -/// -/// - Parameter i: The index of the loaded image as reported by Dyld. -/// - Returns: The image name, address, and size. -internal func getAddressInfoForImage(atIndex i: UInt32) -> - (name: String, address: UnsafeMutablePointer?, size: UInt) { - debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") } - let header = unsafeBitCast(_dyld_get_image_header(i), - to: UnsafePointer.self) - let name = String(validatingUTF8: _dyld_get_image_name(i)!)! - var size: UInt = 0 - let address = getsegmentdata(header, "__TEXT", &size) - return (name, address, size) +internal func getImageCount() -> UInt32 { + return _dyld_image_count() +} + +let rtldDefault = UnsafeMutableRawPointer(bitPattern: Int(-2)) +#elseif !os(Windows) +import SwiftShims +import Glibc + +let rtldDefault: UnsafeMutableRawPointer? = nil + +extension Section { + init(range: MetadataSectionRange) { + self.startAddress = UnsafeRawPointer(bitPattern: range.start)! + self.size = UInt(range.length) + } +} + +internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? { + return _getMetadataSection(UInt(i)).map { rawPointer in + let name = _getMetadataSectionName(rawPointer) + let metadataSection = rawPointer.bindMemory(to: MetadataSections.self, capacity: 1).pointee + return ReflectionInfo(imageName: String(validatingUTF8: name)!, + fieldmd: Section(range: metadataSection.swift5_fieldmd), + assocty: Section(range: metadataSection.swift5_assocty), + builtin: Section(range: metadataSection.swift5_builtin), + capture: Section(range: metadataSection.swift5_capture), + typeref: Section(range: metadataSection.swift5_typeref), + reflstr: Section(range: metadataSection.swift5_reflstr)) + } +} + +internal func getImageCount() -> UInt32 { + return UInt32(_getMetadataSectionCount()) +} + +internal func sendImages() { + preconditionFailure("Should only be called in macOS!") +} + + +#else // os(Linux) +#error("SwiftReflectionTest does not currently support this OS.") +#endif + +internal func debugLog(_ message: @autoclosure () -> String) { +#if DEBUG_LOG + fputs("Child: \(message())\n", stderr) + fflush(stderr) +#endif +} + +public enum InstanceKind: UInt8 { + case None + case Object + case Existential + case ErrorExistential + case Closure + case Enum + case EnumValue +} + +/// Represents a section in a loaded image in this process. +internal struct Section { + /// The absolute start address of the section's data in this address space. + let startAddress: UnsafeRawPointer + + /// The size of the section in bytes. + let size: UInt +} + +/// Holds the addresses and sizes of sections related to reflection. +internal struct ReflectionInfo : Sequence { + /// The name of the loaded image. + internal let imageName: String + + /// Reflection metadata sections. + internal let fieldmd: Section? + internal let assocty: Section? + internal let builtin: Section? + internal let capture: Section? + internal let typeref: Section? + internal let reflstr: Section? + + internal func makeIterator() -> AnyIterator { + return AnyIterator([ + fieldmd, + assocty, + builtin, + capture, + typeref, + reflstr + ].makeIterator()) + } } internal func sendBytes(from address: UnsafePointer, count: Int) { @@ -197,7 +257,7 @@ internal func readUInt() -> UInt { /// process. internal func sendReflectionInfos() { debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") } - let infos = (0..<_dyld_image_count()).compactMap(getReflectionInfoForImage) + let infos = (0..= 1) - sendValue(infos.count) - for (name, address, size) in infos { - debugLog("Sending info for \(name)") - sendValue(address) - sendValue(size) - } -} - internal func printErrnoAndExit() { debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") } let errorCString = strerror(errno)! @@ -261,8 +306,7 @@ internal func sendSymbolAddress() { debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") } let name = readLine()! name.withCString { - let handle = UnsafeMutableRawPointer(bitPattern: Int(-2))! - let symbol = dlsym(handle, $0) + let symbol = dlsym(rtldDefault, $0) let symbolAddress = unsafeBitCast(symbol, to: UInt.self) sendValue(symbolAddress) } diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp index d888ffa8b0ae7..114cf058512d0 100644 --- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp +++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp @@ -174,6 +174,17 @@ ReflectionSection sectionFromInfo(const swift_reflection_info_t &Info, (uintptr_t)Section.section.End - (uintptr_t)Section.section.Begin); } +template +ReflectionSection reflectionSectionFromLocalAndRemote( + const swift_reflection_section_mapping_t &Section) { + auto RemoteSectionStart = (uint64_t)Section.remote_section.StartAddress; + + auto Start = RemoteRef(RemoteSectionStart, Section.local_section.Begin); + + return ReflectionSection(Start, + (uintptr_t)Section.remote_section.Size); +} + void swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef, swift_reflection_info_t Info) { @@ -201,6 +212,26 @@ swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef, Context->addReflectionInfo(ContextInfo); } +void swift_reflection_addReflectionMappingInfo( + SwiftReflectionContextRef ContextRef, + swift_reflection_mapping_info_t Info) { + auto Context = ContextRef->nativeContext; + + ReflectionInfo ContextInfo{ + reflectionSectionFromLocalAndRemote(Info.field), + reflectionSectionFromLocalAndRemote( + Info.associated_types), + reflectionSectionFromLocalAndRemote( + Info.builtin_types), + reflectionSectionFromLocalAndRemote( + Info.capture), + reflectionSectionFromLocalAndRemote(Info.type_references), + reflectionSectionFromLocalAndRemote( + Info.reflection_strings)}; + + Context->addReflectionInfo(ContextInfo); +} + int swift_reflection_addImage(SwiftReflectionContextRef ContextRef, swift_addr_t imageStart) { diff --git a/stdlib/public/core/Misc.swift b/stdlib/public/core/Misc.swift index 4d3526d7fb320..60b13b0c9a1bf 100644 --- a/stdlib/public/core/Misc.swift +++ b/stdlib/public/core/Misc.swift @@ -132,3 +132,19 @@ public func _getTypeByMangledNameInContext( genericContext: UnsafeRawPointer?, genericArguments: UnsafeRawPointer?) -> Any.Type? + + +@_silgen_name("swift_getMetadataSection") +public func _getMetadataSection( + _ index: UInt) + -> UnsafeRawPointer? + +@_silgen_name("swift_getMetadataSectionCount") +public func _getMetadataSectionCount() + -> UInt + +@_silgen_name("swift_getMetadataSectionName") +public func _getMetadataSectionName( + _ metadata_section: UnsafeRawPointer) + -> UnsafePointer + diff --git a/stdlib/public/runtime/ImageInspectionCommon.cpp b/stdlib/public/runtime/ImageInspectionCommon.cpp index 6a5cce64681f7..9054fafb4d677 100644 --- a/stdlib/public/runtime/ImageInspectionCommon.cpp +++ b/stdlib/public/runtime/ImageInspectionCommon.cpp @@ -45,14 +45,13 @@ void record(swift::MetadataSections *sections) { SWIFT_RUNTIME_EXPORT void swift_addNewDSOImage(const void *addr) { - const swift::MetadataSections *sections = - static_cast(addr); - // We cast off the const in order to update the linked list // data structure. This is safe to do since we don't touch // any other fields. - auto casted_sections = const_cast(sections); - record(casted_sections); + swift::MetadataSections *sections = + static_cast(const_cast(addr)); + + record(sections); const auto &protocols_section = sections->swift5_protocols; const void *protocols = reinterpret_cast(protocols_section.start); @@ -138,6 +137,55 @@ void *swift::lookupSection(const char *segment, const char *section, size_t *out return nullptr; } +SWIFT_RUNTIME_EXPORT +const swift::MetadataSections *swift_getMetadataSection(size_t index) { + #ifndef NDEBUG + if (swift::registered == nullptr) { + return nullptr; + } + + auto selected = swift::registered; + while (index > 0) { + selected = selected->next; + if (selected == swift::registered) { + return nullptr; + } + --index; + } + return selected; + #else // NDEBUG + return nullptr; + #endif // else NDEBUG +} + +SWIFT_RUNTIME_EXPORT +const char *swift_getMetadataSectionName(void *metadata_section) { + #ifndef NDEBUG + swift::SymbolInfo info; + if (lookupSymbol(metadata_section, &info)) { + if (info.fileName) { + return info.fileName; + } + } + #endif // NDEBUG + return ""; +} + +SWIFT_RUNTIME_EXPORT +size_t swift_getMetadataSectionCount() { + #ifndef NDEBUG + if (swift::registered == nullptr) + return 0; + + size_t count = 1; + for (const auto *current = swift::registered->next; + current != swift::registered; current = current->next, ++count); + + return count; + #else // NDEBUG + return 0; + #endif // else NDEBUG +} #endif // !defined(__MACH__) -#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H +#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H \ No newline at end of file diff --git a/stdlib/public/runtime/ImageInspectionCommon.h b/stdlib/public/runtime/ImageInspectionCommon.h index e0cf26a270fa3..4166adcf1c90f 100644 --- a/stdlib/public/runtime/ImageInspectionCommon.h +++ b/stdlib/public/runtime/ImageInspectionCommon.h @@ -12,7 +12,7 @@ /// /// \file /// -/// This file unifies common ELF and COFF image inspection routines +/// This file unifies common ELF and COFF image inspection routines. /// //===----------------------------------------------------------------------===// @@ -27,6 +27,7 @@ #include "../SwiftShims/Visibility.h" #include +#include namespace swift { struct MetadataSections; @@ -42,6 +43,16 @@ struct SectionInfo { SWIFT_RUNTIME_EXPORT void swift_addNewDSOImage(const void *addr); +#ifndef NDEBUG + +SWIFT_RUNTIME_EXPORT +const char *swift_getMetadataSectionName(void *metadata_section); + +SWIFT_RUNTIME_EXPORT +size_t swift_getMetadataSectionCount(); + +#endif // NDEBUG + #endif // !defined(__MACH__) -#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H \ No newline at end of file +#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H diff --git a/stdlib/tools/swift-reflection-test/swift-reflection-test.c b/stdlib/tools/swift-reflection-test/swift-reflection-test.c index 4e3d143174ced..3293b90df6bad 100644 --- a/stdlib/tools/swift-reflection-test/swift-reflection-test.c +++ b/stdlib/tools/swift-reflection-test/swift-reflection-test.c @@ -15,6 +15,7 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) +#define SECTIONS_PER_INFO 6 #include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h" #include "swift/Demangling/ManglingMacros.h" @@ -55,22 +56,6 @@ typedef struct PipeMemoryReader { int from_child[2]; } PipeMemoryReader; -typedef struct RemoteSection { - uintptr_t StartAddress; - uintptr_t Size; - uintptr_t EndAddress; -} RemoteSection; - -typedef struct RemoteReflectionInfo { - RemoteSection fieldmd; - RemoteSection assocty; - RemoteSection builtin; - RemoteSection capture; - RemoteSection typeref; - RemoteSection reflstr; - uintptr_t StartAddress; - size_t TotalSize; -} RemoteReflectionInfo; NORETURN static void errorAndExit(const char *message) { @@ -317,88 +302,64 @@ PipeMemoryReader_receiveImages(SwiftReflectionContextRef RC, #else static swift_reflection_section_t -makeLocalSection(const void *Buffer, RemoteSection Section, - RemoteReflectionInfo Info) { +makeLocalSection(const void *Buffer, + swift_remote_reflection_section_t Section) { if (Section.Size == 0) { swift_reflection_section_t LS = {NULL, NULL}; return LS; } - uintptr_t Base - = (uintptr_t)Buffer + Section.StartAddress - Info.StartAddress; - swift_reflection_section_t LS = { - (void *)Base, - (void *)(Base + Section.Size) - }; + swift_reflection_section_t LS = {(void *)Buffer, + (void *)(Buffer + Section.Size)}; return LS; } -static -uintptr_t getStartAddress(const RemoteSection Sections[], size_t Count) { - uintptr_t Start = 0; - for (size_t i = 0; i < Count; ++i) { - if (Sections[i].StartAddress != 0) { - if (Start != 0) - Start = MIN(Start, Sections[i].StartAddress); - else - Start = Sections[i].StartAddress; - } +static swift_reflection_mapping_info_t makeNonContiguousReflectionInfo( + swift_remote_reflection_section_t *remote_sections, + swift_reflection_section_t *local_sections) { + swift_reflection_section_mapping_t sections[SECTIONS_PER_INFO]; + for (size_t i = 0; i < SECTIONS_PER_INFO; ++i) { + swift_reflection_section_mapping_t section = {local_sections[i], + remote_sections[i]}; + sections[i] = section; } - return Start; -} -static -uintptr_t getEndAddress(const RemoteSection Sections[], size_t Count) { - uintptr_t End = 0; - for (size_t i = 0; i < Count; ++i) { - if (Sections[i].StartAddress != 0) - End = MAX(End, Sections[i].EndAddress); - } - return End; -} + swift_reflection_mapping_info_t ReflectionMappingInfo = { + sections[0], sections[1], sections[2], + sections[3], sections[4], sections[5]}; -static -RemoteReflectionInfo makeRemoteReflectionInfo(RemoteSection fieldmd, - RemoteSection assocty, - RemoteSection builtin, - RemoteSection capture, - RemoteSection typeref, - RemoteSection reflstr) { - RemoteReflectionInfo Info = { - fieldmd, - assocty, - builtin, - capture, - typeref, - reflstr, - 0, - 0 - }; - - const RemoteSection Sections[6] = { - fieldmd, assocty, builtin, capture, typeref, reflstr - }; - - Info.StartAddress = getStartAddress(Sections, 6); - - uintptr_t EndAddress = getEndAddress(Sections, 6); - Info.TotalSize = EndAddress - Info.StartAddress; - - return Info; + return ReflectionMappingInfo; } -static -RemoteSection makeRemoteSection(const PipeMemoryReader *Reader) { +static swift_remote_reflection_section_t +makeRemoteSection(const PipeMemoryReader *Reader) { uintptr_t Start; size_t Size; PipeMemoryReader_collectBytesFromPipe(Reader, &Start, sizeof(Start)); PipeMemoryReader_collectBytesFromPipe(Reader, &Size, sizeof(Size)); - RemoteSection RS = {Start, Size, Start + Size}; + swift_remote_reflection_section_t RS = {Start, Size}; + DEBUG_LOG("Making remote section with Start = 0x%" PRIxPTR + " End = 0x%" PRIxPTR " and Size = %lu", + RS.StartAddress, RS.StartAddress + RS.Size, RS.Size); + return RS; } +static const void *PipeMemoryReader_readRemoteSection( + const PipeMemoryReader *Reader, + swift_remote_reflection_section_t *RemoteSection, void **outFreeContext) { + + const void *Buffer = + PipeMemoryReader_readBytes((void *)Reader, RemoteSection->StartAddress, + RemoteSection->Size, outFreeContext); + if (!Buffer) + errorAndExit("Couldn't read reflection information"); + + return Buffer; +} + static void PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC, const PipeMemoryReader *Reader) { @@ -411,48 +372,39 @@ PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC, if (NumReflectionInfos == 0) return; - RemoteReflectionInfo *RemoteInfos = calloc(NumReflectionInfos, - sizeof(RemoteReflectionInfo)); - if (RemoteInfos == NULL) + swift_remote_reflection_section_t *RemoteSections = + calloc(NumReflectionInfos * SECTIONS_PER_INFO, + sizeof(swift_remote_reflection_section_t)); + if (RemoteSections == NULL) errnoAndExit("malloc failed"); - for (size_t i = 0; i < NumReflectionInfos; ++i) { - RemoteInfos[i] = makeRemoteReflectionInfo( - makeRemoteSection(Reader), - makeRemoteSection(Reader), - makeRemoteSection(Reader), - makeRemoteSection(Reader), - makeRemoteSection(Reader), - makeRemoteSection(Reader)); + // We first read all remote reflection sections, there are 6 for every + // complete reflection info. + // They come ordered as: fieldmd, assocty, builtin, capture, typeref, reflstr. + for (size_t i = 0; i < NumReflectionInfos * SECTIONS_PER_INFO; ++i) { + RemoteSections[i] = makeRemoteSection(Reader); } - // Now pull in the remote sections into our address space. - - for (size_t i = 0; i < NumReflectionInfos; ++i) { - RemoteReflectionInfo RemoteInfo = RemoteInfos[i]; - + swift_reflection_section_t *LocalSections = + calloc(NumReflectionInfos * SECTIONS_PER_INFO, + sizeof(swift_reflection_section_t)); + for (size_t i = 0; i < NumReflectionInfos * SECTIONS_PER_INFO; ++i) { void *outFreeContext = NULL; - const void *Buffer = PipeMemoryReader_readBytes((void *)Reader, - RemoteInfo.StartAddress, - RemoteInfo.TotalSize, - &outFreeContext); - if (!Buffer) - errorAndExit("Couldn't read reflection information"); - - swift_reflection_info_t Info = { - {makeLocalSection(Buffer, RemoteInfo.fieldmd, RemoteInfo), 0}, - {makeLocalSection(Buffer, RemoteInfo.assocty, RemoteInfo), 0}, - {makeLocalSection(Buffer, RemoteInfo.builtin, RemoteInfo), 0}, - {makeLocalSection(Buffer, RemoteInfo.capture, RemoteInfo), 0}, - {makeLocalSection(Buffer, RemoteInfo.typeref, RemoteInfo), 0}, - {makeLocalSection(Buffer, RemoteInfo.reflstr, RemoteInfo), 0}, - /*LocalStartAddress*/ (uintptr_t) Buffer, - /*RemoteStartAddress*/ RemoteInfo.StartAddress, - }; - swift_reflection_addReflectionInfo(RC, Info); + const void *Buffer = PipeMemoryReader_readRemoteSection( + (void *)Reader, &RemoteSections[i], &outFreeContext); + LocalSections[i] = makeLocalSection(Buffer, RemoteSections[i]); + } + + // Finally, we zip them in a complete reflection info, with a stride of 6. + for (size_t i = 0; i < NumReflectionInfos * SECTIONS_PER_INFO; + i += SECTIONS_PER_INFO) { + swift_reflection_mapping_info_t Info = + makeNonContiguousReflectionInfo(&RemoteSections[i], &LocalSections[i]); + swift_reflection_addReflectionMappingInfo(RC, Info); } - free(RemoteInfos); + free(RemoteSections); + free(LocalSections); } #endif diff --git a/test/api-digester/stability-stdlib-abi-with-asserts.test b/test/api-digester/stability-stdlib-abi-with-asserts.test index 141d499d154d1..08ccb2c195c26 100644 --- a/test/api-digester/stability-stdlib-abi-with-asserts.test +++ b/test/api-digester/stability-stdlib-abi-with-asserts.test @@ -39,3 +39,6 @@ Struct _ObjectRuntimeFunctionCountersState is a new API without @available attri Struct _RuntimeFunctionCounters is a new API without @available attribute Func _swift_isImmutableCOWBuffer(_:) is a new API without @available attribute Func _swift_setImmutableCOWBuffer(_:_:) is a new API without @available attribute +Func _getMetadataSection(_:) is a new API without @available attribute +Func _getMetadataSectionCount() is a new API without @available attribute +Func _getMetadataSectionName(_:) is a new API without @available attribute diff --git a/test/lit.cfg b/test/lit.cfg index 99514d9637758..251985142f7e3 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -1991,3 +1991,10 @@ if copy_env is not None: config.environment[key] = os.environ[key] lit_config.note("Available features: " + ", ".join(sorted(config.available_features))) + +# On macOS reflection information is read through the dyld APIs +# On other platorms, this information is exported through extra +# entry points in the Swift runtime that are only available in debug builds. +# Windows currently does not support basic reflection support. +if 'objc_interop' in config.available_features or ('swift_stdlib_asserts' in config.available_features and not kIsWindows): + config.available_features.add('reflection_test_support') diff --git a/validation-test/Reflection/reflect_UInt16.swift b/validation-test/Reflection/reflect_UInt16.swift index 1ed7849465df0..53f3adbff5e4b 100644 --- a/validation-test/Reflection/reflect_UInt16.swift +++ b/validation-test/Reflection/reflect_UInt16.swift @@ -4,7 +4,7 @@ // RUN: %target-run %target-swift-reflection-test %t/reflect_UInt16 | %FileCheck %s --check-prefix=CHECK-%target-ptrsize -// REQUIRES: objc_interop +// REQUIRES: reflection_test_support // REQUIRES: executable_test // UNSUPPORTED: use_os_stdlib