| //===--- SwiftRemoteMirrorLegacyInterop.h - Interop with legacy libs. -*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This header provides an interface for using multiple versions of the Swift remote |
| /// mirror library to inspect processes built with different versions of Swift, or |
| /// processes where different libraries are built with different versions of Swift. |
| /// |
| //===----------------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_REMOTE_MIRROR_LEGACY_INTEROP_H |
| #define SWIFT_REMOTE_MIRROR_LEGACY_INTEROP_H |
| |
| #if defined(__APPLE__) && defined(__MACH__) |
| |
| #include "SwiftRemoteMirrorLegacyInteropTypes.h" |
| #include "SwiftRemoteMirror.h" |
| |
| #include <string.h> |
| #include <dlfcn.h> |
| #include <mach-o/getsect.h> |
| |
| #include <CoreFoundation/CFDictionary.h> |
| #include <TargetConditionals.h> |
| |
| /// The "public" interface follows. All of these functions are the same |
| /// as the corresponding swift_reflection_* functions, except for taking |
| /// or returning _interop data types in some circumstances. |
| |
| static inline SwiftReflectionInteropContextRef |
| swift_reflection_interop_createReflectionContext( |
| void *ReaderContext, |
| uint8_t PointerSize, |
| FreeBytesFunction FreeBytes, |
| ReadBytesFunction ReadBytes, |
| GetStringLengthFunction GetStringLength, |
| GetSymbolAddressFunction GetSymbolAddress); |
| |
| static inline SwiftReflectionInteropContextRef |
| swift_reflection_interop_createReflectionContextWithDataLayout( |
| void *ReaderContext, |
| QueryDataLayoutFunction DataLayout, |
| FreeBytesFunction FreeBytes, |
| ReadBytesFunction ReadBytes, |
| GetStringLengthFunction GetStringLength, |
| GetSymbolAddressFunction GetSymbolAddress); |
| |
| /// Add a library handle to the interop context. Returns 1 if the |
| /// library was added successfully, 0 if a symbol couldn't be looked up |
| /// or the reported metadata version is too old. |
| static inline int |
| swift_reflection_interop_addLibrary( |
| SwiftReflectionInteropContextRef ContextRef, void *LibraryHandle); |
| |
| static inline void |
| swift_reflection_interop_destroyReflectionContext( |
| SwiftReflectionInteropContextRef ContextRef); |
| |
| /// Set the is-Swift mask for the stable ABI on the current system. |
| /// NOTE: must be called after interop_addLibrary is used to add the |
| /// stable ABI remote mirror library in order to take effect. |
| static inline void |
| swift_reflection_interop_setClassIsSwiftMask( |
| SwiftReflectionInteropContextRef ContextRef, uint64_t mask); |
| |
| static inline int |
| swift_reflection_interop_addImage(SwiftReflectionInteropContextRef ContextRef, |
| swift_addr_t imageStart); |
| |
| static inline int |
| swift_reflection_interop_readIsaMask(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t *outIsaMask); |
| |
| /// Look up a metadata pointer and return an interop structure that can |
| /// be passed to other calls. Returns { 0, 0 } if the metadata pointer |
| /// was not recognized. |
| static inline swift_metadata_interop_t |
| swift_reflection_interop_lookupMetadata(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t RemoteTyperef); |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_typeRefForMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata); |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_typeRefForInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object); |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_typeRefForMangledTypeName( |
| SwiftReflectionInteropContextRef ContextRef, |
| const char *MangledName, |
| uint64_t Length); |
| |
| static inline char * |
| swift_reflection_interop_copyDemangledNameForTypeRef( |
| SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef); |
| |
| static inline swift_typeinfo_t |
| swift_reflection_interop_infoForTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef); |
| |
| static inline swift_childinfo_interop_t |
| swift_reflection_interop_childOfTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef, |
| unsigned Index); |
| |
| static inline swift_typeinfo_interop_t |
| swift_reflection_interop_infoForMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata); |
| |
| static inline swift_childinfo_interop_t |
| swift_reflection_interop_childOfMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata, |
| unsigned Index); |
| |
| static inline swift_typeinfo_interop_t |
| swift_reflection_interop_infoForInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object); |
| |
| static inline swift_childinfo_interop_t |
| swift_reflection_interop_childOfInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object, |
| unsigned Index); |
| |
| static inline unsigned |
| swift_reflection_interop_genericArgumentCountOfTypeRef( |
| SwiftReflectionInteropContextRef ContextRef, swift_typeref_interop_t OpaqueTypeRef); |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_genericArgumentOfTypeRef( |
| SwiftReflectionInteropContextRef ContextRef, swift_typeref_interop_t OpaqueTypeRef, |
| unsigned Index); |
| |
| static inline int |
| swift_reflection_interop_projectExistential(SwiftReflectionInteropContextRef ContextRef, |
| swift_addr_t ExistentialAddress, |
| swift_typeref_interop_t ExistentialTypeRef, |
| swift_typeref_interop_t *OutInstanceTypeRef, |
| swift_addr_t *OutStartOfInstanceData); |
| |
| static inline void |
| swift_reflection_interop_dumpTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef); |
| |
| static inline void |
| swift_reflection_interop_dumpInfoForTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef); |
| |
| static inline void |
| swift_reflection_interop_dumpInfoForMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata); |
| |
| static inline void |
| swift_reflection_interop_dumpInfoForInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object); |
| |
| static inline size_t |
| swift_reflection_interop_demangle(SwiftReflectionInteropContextRef ContextRef, |
| const char *MangledName, |
| size_t Length, |
| char *OutDemangledName, |
| size_t MaxLength); |
| |
| |
| |
| /// \name Internal implementation details, clients don't need to use these. |
| /// @{ |
| |
| /// The minimum supported metadata version for the legacy library. |
| #define SWIFT_LEGACY_METADATA_MIN_VERSION 3 |
| |
| /// The legacy reflection info struct. |
| typedef struct swift_reflection_legacy_info { |
| swift_reflection_section_t fieldmd; |
| swift_reflection_section_t assocty; |
| swift_reflection_section_t builtin; |
| swift_reflection_section_t capture; |
| swift_reflection_section_t typeref; |
| swift_reflection_section_t reflstr; |
| uintptr_t LocalStartAddress; |
| uintptr_t RemoteStartAddress; |
| } swift_reflection_legacy_info_t; |
| |
| /// The signature of the legacy ReadBytesFunction. |
| typedef int (*ReadBytesFunctionLegacy)(void *reader_context, swift_addr_t address, |
| void *dest, uint64_t size); |
| |
| struct SwiftReflectionFunctions { |
| unsigned long long *classIsSwiftMaskPtr; |
| |
| uint16_t (*getSupportedMetadataVersion)(void); |
| |
| SwiftReflectionContextRef (*createReflectionContext)( |
| void *ReaderContext, |
| uint8_t PointerSize, |
| FreeBytesFunction FreeBytes, |
| ReadBytesFunction ReadBytes, |
| GetStringLengthFunction GetStringLength, |
| GetSymbolAddressFunction GetSymbolAddress); |
| |
| // Optional creation function that takes a data layout query function. |
| SwiftReflectionContextRef (*createReflectionContextWithDataLayout)( |
| void *ReaderContext, |
| QueryDataLayoutFunction DataLayout, |
| FreeBytesFunction FreeBytes, |
| ReadBytesFunction ReadBytes, |
| GetStringLengthFunction GetStringLength, |
| GetSymbolAddressFunction GetSymbolAddress); |
| |
| SwiftReflectionContextRef (*createReflectionContextLegacy)( |
| void *ReaderContext, |
| PointerSizeFunction getPointerSize, |
| SizeSizeFunction getSizeSize, |
| ReadBytesFunctionLegacy readBytes, |
| GetStringLengthFunction getStringLength, |
| GetSymbolAddressFunction getSymbolAddress); |
| |
| void (*destroyReflectionContext)(SwiftReflectionContextRef Context); |
| |
| void (*addReflectionInfo)(SwiftReflectionContextRef Context, |
| swift_reflection_info_t Info); |
| |
| void (*addReflectionInfoLegacy)(SwiftReflectionContextRef Context, |
| swift_reflection_legacy_info_t Info); |
| |
| int (*addImage)(SwiftReflectionContextRef ContextRef, |
| swift_addr_t imageStart); |
| |
| int (*readIsaMask)(SwiftReflectionContextRef ContextRef, uintptr_t *outIsaMask); |
| |
| swift_typeref_t (*typeRefForMetadata)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Metadata); |
| |
| int (*ownsObject)(SwiftReflectionContextRef ContextRef, uintptr_t Object); |
| |
| int (*ownsAddress)(SwiftReflectionContextRef ContextRef, uintptr_t Address); |
| |
| uintptr_t (*metadataForObject)(SwiftReflectionContextRef ContextRef, uintptr_t Object); |
| |
| swift_typeref_t (*typeRefForInstance)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Object); |
| |
| swift_typeref_t (*typeRefForMangledTypeName)(SwiftReflectionContextRef ContextRef, |
| const char *MangledName, |
| uint64_t Length); |
| |
| char * (*copyDemangledNameForTypeRef)( |
| SwiftReflectionContextRef ContextRef, swift_typeref_t OpaqueTypeRef); |
| |
| swift_typeinfo_t (*infoForTypeRef)(SwiftReflectionContextRef ContextRef, |
| swift_typeref_t OpaqueTypeRef); |
| |
| swift_childinfo_t (*childOfTypeRef)(SwiftReflectionContextRef ContextRef, |
| swift_typeref_t OpaqueTypeRef, |
| unsigned Index); |
| |
| swift_typeinfo_t (*infoForMetadata)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Metadata); |
| |
| swift_childinfo_t (*childOfMetadata)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Metadata, |
| unsigned Index); |
| swift_typeinfo_t (*infoForInstance)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Object); |
| |
| swift_childinfo_t (*childOfInstance)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Object, |
| unsigned Index); |
| |
| unsigned (*genericArgumentCountOfTypeRef)(swift_typeref_t OpaqueTypeRef); |
| |
| swift_typeref_t (*genericArgumentOfTypeRef)(swift_typeref_t OpaqueTypeRef, |
| unsigned Index); |
| |
| int (*projectExistential)(SwiftReflectionContextRef ContextRef, |
| swift_addr_t ExistentialAddress, |
| swift_typeref_t ExistentialTypeRef, |
| swift_typeref_t *OutInstanceTypeRef, |
| swift_addr_t *OutStartOfInstanceData); |
| |
| void (*dumpTypeRef)(swift_typeref_t OpaqueTypeRef); |
| |
| void (*dumpInfoForTypeRef)(SwiftReflectionContextRef ContextRef, |
| swift_typeref_t OpaqueTypeRef); |
| |
| void (*dumpInfoForMetadata)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Metadata); |
| |
| void (*dumpInfoForInstance)(SwiftReflectionContextRef ContextRef, |
| uintptr_t Object); |
| |
| size_t (*demangle)(const char *MangledName, |
| size_t Length, |
| char *OutDemangledName, |
| size_t MaxLength); |
| }; |
| |
| struct SwiftReflectionInteropContextLibrary { |
| SwiftReflectionContextRef Context; |
| struct SwiftReflectionFunctions Functions; |
| int IsLegacy; |
| }; |
| |
| struct SwiftReflectionInteropContextFreeList { |
| struct SwiftReflectionInteropContextFreeList *Next; |
| const void *Pointer; |
| void *Context; |
| }; |
| |
| struct SwiftReflectionInteropContextLegacyImageRangeList { |
| struct SwiftReflectionInteropContextLegacyImageRangeList *Next; |
| swift_addr_t Start, End; |
| }; |
| |
| struct SwiftReflectionInteropContext { |
| void *ReaderContext; |
| QueryDataLayoutFunction DataLayout; |
| FreeBytesFunction FreeBytes; |
| ReadBytesFunction ReadBytes; |
| uint64_t (*GetStringLength)(void *reader_context, |
| swift_addr_t address); |
| swift_addr_t (*GetSymbolAddress)(void *reader_context, |
| const char *name, |
| uint64_t name_length); |
| |
| struct SwiftReflectionInteropContextLibrary *Libraries; |
| int LibraryCount; |
| |
| struct SwiftReflectionInteropContextFreeList *FreeList; |
| struct SwiftReflectionInteropContextLegacyImageRangeList *LegacyImageRangeList; |
| |
| CFMutableDictionaryRef AddressToLibraryCache; |
| }; |
| |
| #define FOREACH_LIBRARY \ |
| for (struct SwiftReflectionInteropContextLibrary *Library = &ContextRef->Libraries[0]; \ |
| Library < &ContextRef->Libraries[ContextRef->LibraryCount]; \ |
| ++Library) |
| #define LIBRARY_INDEX (Library - ContextRef->Libraries) |
| #define DECLARE_LIBRARY(index) \ |
| struct SwiftReflectionInteropContextLibrary *Library = &ContextRef->Libraries[index] |
| |
| static inline int |
| swift_reflection_interop_libraryOwnsAddress( |
| struct SwiftReflectionInteropContext *ContextRef, |
| struct SwiftReflectionInteropContextLibrary *Library, |
| uintptr_t Address) { |
| if (!Library->IsLegacy) |
| return Library->Functions.ownsAddress(Library->Context, Address); |
| |
| // Search the images list to see if the address is in one of them. |
| struct SwiftReflectionInteropContextLegacyImageRangeList *Node = |
| ContextRef->LegacyImageRangeList; |
| while (Node != NULL) { |
| if (Node->Start <= Address && Address < Node->End) |
| return 1; |
| Node = Node->Next; |
| } |
| return 0; |
| } |
| |
| static inline struct SwiftReflectionInteropContextLibrary * |
| swift_reflection_interop_libraryForAddress( |
| struct SwiftReflectionInteropContext *ContextRef, |
| uintptr_t Address) { |
| uintptr_t cachedIndex; |
| if (CFDictionaryGetValueIfPresent(ContextRef->AddressToLibraryCache, |
| (void *)Address, |
| (const void **)&cachedIndex)) { |
| return &ContextRef->Libraries[cachedIndex]; |
| } |
| |
| FOREACH_LIBRARY { |
| if (swift_reflection_interop_libraryOwnsAddress(ContextRef, Library, Address)) { |
| CFDictionarySetValue(ContextRef->AddressToLibraryCache, |
| (void *)Address, |
| (void *)LIBRARY_INDEX); |
| return Library; |
| } |
| } |
| return NULL; |
| } |
| |
| static inline uintptr_t |
| swift_reflection_interop_metadataForObject( |
| struct SwiftReflectionInteropContext *ContextRef, |
| uintptr_t Object) { |
| FOREACH_LIBRARY { |
| if (Library->IsLegacy) |
| continue; |
| uintptr_t Metadata = Library->Functions.metadataForObject(Library->Context, Object); |
| if (Metadata != 0) |
| return Metadata; |
| } |
| return 0; |
| } |
| |
| static inline struct SwiftReflectionInteropContextLibrary * |
| swift_reflection_interop_libraryForObject( |
| struct SwiftReflectionInteropContext *ContextRef, |
| uintptr_t Object) { |
| uintptr_t Metadata = swift_reflection_interop_metadataForObject(ContextRef, Object); |
| if (Metadata == 0) { |
| // If we couldn't retrieve metadata, assume it belongs to a legacy library. |
| FOREACH_LIBRARY { |
| if (Library->IsLegacy) |
| return Library; |
| } |
| return NULL; |
| } |
| |
| return swift_reflection_interop_libraryForAddress(ContextRef, Metadata); |
| } |
| |
| static inline int |
| swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Context, |
| void *Handle) { |
| if (Handle == NULL) |
| return 0; |
| |
| struct SwiftReflectionInteropContextLibrary *Library = &Context |
| ->Libraries[Context->LibraryCount]; |
| struct SwiftReflectionFunctions *Functions = &Library->Functions; |
| |
| #ifndef __cplusplus |
| #define decltype(x) void * |
| #endif |
| #define LOAD_NAMED(field, symbol, required) do { \ |
| Functions->field = (decltype(Functions->field))dlsym(Handle, symbol); \ |
| if (required && Functions->field == NULL) return 0; \ |
| } while (0) |
| #define LOAD(name) LOAD_NAMED(name, "swift_reflection_" #name, 1) |
| #define LOAD_OPT(name) LOAD_NAMED(name, "swift_reflection_" #name, 0) |
| |
| Functions->classIsSwiftMaskPtr = |
| (unsigned long long *)dlsym(Handle, "swift_reflection_classIsSwiftMask"); |
| LOAD(getSupportedMetadataVersion); |
| uint16_t version = Functions->getSupportedMetadataVersion(); |
| if (version < SWIFT_LEGACY_METADATA_MIN_VERSION) |
| return 0; |
| |
| int IsLegacy = dlsym(Handle, "swift_reflection_addImage") == NULL; |
| |
| if (IsLegacy) { |
| LOAD_NAMED(createReflectionContextLegacy, "swift_reflection_createReflectionContext", 1); |
| LOAD_NAMED(addReflectionInfoLegacy, "swift_reflection_addReflectionInfo", 1); |
| } else { |
| LOAD(createReflectionContext); |
| LOAD(addReflectionInfo); |
| LOAD(addImage); |
| LOAD(ownsObject); |
| LOAD(ownsAddress); |
| LOAD(metadataForObject); |
| |
| // Optional creation function. |
| LOAD_OPT(createReflectionContextWithDataLayout); |
| } |
| |
| LOAD(destroyReflectionContext); |
| LOAD(readIsaMask); |
| LOAD(typeRefForMetadata); |
| LOAD(typeRefForInstance); |
| LOAD(typeRefForMangledTypeName); |
| LOAD_OPT(copyDemangledNameForTypeRef); |
| LOAD(infoForTypeRef); |
| LOAD(childOfTypeRef); |
| LOAD(infoForMetadata); |
| LOAD(childOfMetadata); |
| LOAD(infoForInstance); |
| LOAD(childOfInstance); |
| LOAD(genericArgumentCountOfTypeRef); |
| LOAD(genericArgumentOfTypeRef); |
| LOAD(projectExistential); |
| LOAD(dumpTypeRef); |
| LOAD(dumpInfoForTypeRef); |
| |
| Library->IsLegacy = IsLegacy; |
| ++Context->LibraryCount; |
| |
| return 1; |
| |
| #undef LOAD |
| #undef LOAD_NAMED |
| #ifndef __cplusplus |
| #undef decltype |
| #endif |
| } |
| |
| static inline int |
| swift_reflection_interop_readBytesAdapter(void *reader_context, |
| swift_addr_t address, |
| void *dest, |
| uint64_t size) { |
| SwiftReflectionInteropContextRef Context = |
| (SwiftReflectionInteropContextRef)reader_context; |
| |
| void *FreeContext; |
| const void *ptr = Context->ReadBytes(Context->ReaderContext, address, size, |
| &FreeContext); |
| if (ptr == NULL) |
| return 0; |
| |
| memcpy(dest, ptr, size); |
| if (Context->FreeBytes != NULL) |
| Context->FreeBytes(Context->ReaderContext, ptr, FreeContext); |
| return 1; |
| } |
| |
| static inline uint8_t |
| swift_reflection_interop_getSizeAdapter(void *reader_context) { |
| // Legacy library doesn't pay attention to these anyway. |
| (void)reader_context; |
| return sizeof(void *); |
| } |
| |
| static inline uint64_t |
| swift_reflection_interop_GetStringLengthAdapter( |
| void *reader_context, swift_addr_t address) { |
| SwiftReflectionInteropContextRef Context = |
| (SwiftReflectionInteropContextRef)reader_context; |
| return Context->GetStringLength(Context->ReaderContext, address); |
| } |
| |
| static inline swift_addr_t |
| swift_reflection_interop_GetSymbolAddressAdapter( |
| void *reader_context, const char *name, uint64_t name_length) { |
| SwiftReflectionInteropContextRef Context = |
| (SwiftReflectionInteropContextRef)reader_context; |
| return Context->GetSymbolAddress(Context->ReaderContext, name, name_length); |
| } |
| |
| static inline int |
| swift_reflection_interop_minimalDataLayoutQueryFunction4( |
| void *ReaderContext, |
| DataLayoutQueryType type, |
| void *inBuffer, void *outBuffer) { |
| (void)ReaderContext; |
| (void)inBuffer; |
| switch (type) { |
| case DLQ_GetPointerSize: |
| case DLQ_GetSizeSize: { |
| uint8_t *result = (uint8_t *)outBuffer; |
| *result = 4; |
| return 1; |
| } |
| case DLQ_GetObjCReservedLowBits: { |
| uint8_t *result = (uint8_t *)outBuffer; |
| // Swift assumes this for all 32-bit platforms, including Darwin |
| *result = 0; |
| return 1; |
| } |
| case DLQ_GetLeastValidPointerValue: { |
| uint64_t *result = (uint64_t *)outBuffer; |
| // Swift assumes this for all 32-bit platforms, including Darwin |
| *result = 0x1000; |
| return 1; |
| } |
| default: |
| return 0; |
| } |
| } |
| |
| static inline int |
| swift_reflection_interop_minimalDataLayoutQueryFunction8( |
| void *ReaderContext, |
| DataLayoutQueryType type, |
| void *inBuffer, void *outBuffer) { |
| (void)ReaderContext; |
| (void)inBuffer; |
| // Caveat: This assumes the process being examined is |
| // running in the same kind of environment as this host code. |
| #if defined(__APPLE__) && __APPLE__ |
| int applePlatform = 1; |
| #else |
| int applePlatform = 0; |
| #endif |
| #if defined(__APPLE__) && __APPLE__ && ((defined(TARGET_OS_IOS) && TARGET_OS_IOS) || (defined(TARGET_OS_IOS) && TARGET_OS_WATCH) || (defined(TARGET_OS_TV) && TARGET_OS_TV) || defined(__arm64__)) |
| int iosDerivedPlatform = 1; |
| #else |
| int iosDerivedPlatform = 0; |
| #endif |
| |
| switch (type) { |
| case DLQ_GetPointerSize: |
| case DLQ_GetSizeSize: { |
| uint8_t *result = (uint8_t *)outBuffer; |
| *result = 8; |
| return 1; |
| } |
| case DLQ_GetObjCReservedLowBits: { |
| uint8_t *result = (uint8_t *)outBuffer; |
| if (applePlatform && !iosDerivedPlatform) { |
| *result = 1; |
| } else { |
| *result = 0; |
| } |
| return 1; |
| } |
| case DLQ_GetLeastValidPointerValue: { |
| uint64_t *result = (uint64_t *)outBuffer; |
| if (applePlatform) { |
| // On 64-bit Apple platforms, Swift reserves the first 4GiB |
| *result = 0x100000000; |
| } else { |
| // Swift reserves the first 4KiB everywhere else. |
| *result = 0x1000; |
| } |
| return 1; |
| } |
| default: |
| return 0; |
| } |
| } |
| |
| static inline SwiftReflectionInteropContextRef |
| swift_reflection_interop_createReflectionContext( |
| void *ReaderContext, |
| uint8_t PointerSize, |
| FreeBytesFunction FreeBytes, |
| ReadBytesFunction ReadBytes, |
| GetStringLengthFunction GetStringLength, |
| GetSymbolAddressFunction GetSymbolAddress) { |
| QueryDataLayoutFunction DataLayout; |
| if (PointerSize == 4) |
| DataLayout = swift_reflection_interop_minimalDataLayoutQueryFunction4; |
| else if (PointerSize == 8) |
| DataLayout = swift_reflection_interop_minimalDataLayoutQueryFunction8; |
| else |
| abort(); // Can't handle sizes other than 4 and 8. |
| |
| return swift_reflection_interop_createReflectionContextWithDataLayout( |
| ReaderContext, |
| DataLayout, |
| FreeBytes, |
| ReadBytes, |
| GetStringLength, |
| GetSymbolAddress); |
| } |
| |
| static inline SwiftReflectionInteropContextRef |
| swift_reflection_interop_createReflectionContextWithDataLayout( |
| void *ReaderContext, |
| QueryDataLayoutFunction DataLayout, |
| FreeBytesFunction FreeBytes, |
| ReadBytesFunction ReadBytes, |
| GetStringLengthFunction GetStringLength, |
| GetSymbolAddressFunction GetSymbolAddress) { |
| |
| SwiftReflectionInteropContextRef ContextRef = |
| (SwiftReflectionInteropContextRef)calloc(sizeof(*ContextRef), 1); |
| |
| ContextRef->ReaderContext = ReaderContext; |
| ContextRef->DataLayout = DataLayout; |
| ContextRef->FreeBytes = FreeBytes; |
| ContextRef->ReadBytes = ReadBytes; |
| ContextRef->GetStringLength = GetStringLength; |
| ContextRef->GetSymbolAddress = GetSymbolAddress; |
| |
| ContextRef->AddressToLibraryCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); |
| |
| return ContextRef; |
| } |
| |
| static inline int |
| swift_reflection_interop_addLibrary( |
| SwiftReflectionInteropContextRef ContextRef, void *LibraryHandle) { |
| size_t NewSize = (ContextRef->LibraryCount + 1) * sizeof(*ContextRef->Libraries); |
| ContextRef->Libraries = realloc(ContextRef->Libraries, NewSize); |
| int Success = swift_reflection_interop_loadFunctions(ContextRef, LibraryHandle); |
| if (Success) { |
| struct SwiftReflectionInteropContextLibrary *Library = |
| &ContextRef->Libraries[ContextRef->LibraryCount - 1]; |
| if (Library->IsLegacy) { |
| Library->Context = Library->Functions.createReflectionContextLegacy( |
| ContextRef, |
| swift_reflection_interop_getSizeAdapter, swift_reflection_interop_getSizeAdapter, |
| swift_reflection_interop_readBytesAdapter, |
| swift_reflection_interop_GetStringLengthAdapter, |
| swift_reflection_interop_GetSymbolAddressAdapter); |
| } else if (Library->Functions.createReflectionContextWithDataLayout) { |
| Library->Context = |
| Library->Functions.createReflectionContextWithDataLayout( |
| ContextRef->ReaderContext, |
| ContextRef->DataLayout, |
| ContextRef->FreeBytes, |
| ContextRef->ReadBytes, |
| ContextRef->GetStringLength, |
| ContextRef->GetSymbolAddress); |
| } else { |
| uint8_t PointerSize; |
| int result = ContextRef->DataLayout( |
| ContextRef->ReaderContext, DLQ_GetPointerSize, NULL, &PointerSize); |
| if (!result) |
| abort(); // We need the pointer size, can't proceed without it. |
| |
| Library->Context = Library->Functions.createReflectionContext( |
| ContextRef->ReaderContext, |
| PointerSize, |
| ContextRef->FreeBytes, |
| ContextRef->ReadBytes, |
| ContextRef->GetStringLength, |
| ContextRef->GetSymbolAddress); |
| } |
| } |
| return Success; |
| } |
| |
| static inline void |
| swift_reflection_interop_destroyReflectionContext( |
| SwiftReflectionInteropContextRef ContextRef) { |
| FOREACH_LIBRARY { |
| Library->Functions.destroyReflectionContext(Library->Context); |
| } |
| free(ContextRef->Libraries); |
| struct SwiftReflectionInteropContextLegacyImageRangeList *LegacyImageRangeList |
| = ContextRef->LegacyImageRangeList; |
| while (LegacyImageRangeList != NULL) { |
| struct SwiftReflectionInteropContextLegacyImageRangeList *Next |
| = LegacyImageRangeList->Next; |
| free(LegacyImageRangeList); |
| LegacyImageRangeList = Next; |
| } |
| struct SwiftReflectionInteropContextFreeList *FreeList = ContextRef->FreeList; |
| while (FreeList != NULL) { |
| ContextRef->FreeBytes(ContextRef->ReaderContext, |
| FreeList->Pointer, FreeList->Context); |
| struct SwiftReflectionInteropContextFreeList *Next = FreeList->Next; |
| free(FreeList); |
| FreeList = Next; |
| } |
| |
| CFRelease(ContextRef->AddressToLibraryCache); |
| |
| free(ContextRef); |
| } |
| |
| static inline void |
| swift_reflection_interop_setClassIsSwiftMask( |
| SwiftReflectionInteropContextRef ContextRef, uint64_t mask) { |
| FOREACH_LIBRARY { |
| if (Library->Functions.classIsSwiftMaskPtr) |
| *Library->Functions.classIsSwiftMaskPtr = mask; |
| } |
| } |
| |
| #ifndef __LP64__ |
| typedef const struct mach_header MachHeader; |
| #else |
| typedef const struct mach_header_64 MachHeader; |
| #endif |
| |
| static inline int |
| swift_reflection_interop_findSection(MachHeader *Header, const char *Name, |
| swift_reflection_section_t *Sect) { |
| unsigned long Size; |
| void *Address = getsectiondata(Header, "__TEXT", Name, &Size); |
| if (!Address) |
| return 0; |
| |
| Sect->Begin = Address; |
| Sect->End = (void *)((uintptr_t)Address + Size); |
| return 1; |
| } |
| |
| static inline int |
| swift_reflection_interop_addImageLegacy( |
| SwiftReflectionInteropContextRef ContextRef, |
| struct SwiftReflectionInteropContextLibrary *Library, |
| swift_addr_t ImageStart) { |
| void *FreeContext; |
| const void *Buf; |
| Buf = ContextRef->ReadBytes(ContextRef->ReaderContext, |
| ImageStart, |
| sizeof(MachHeader), |
| &FreeContext); |
| if (Buf == NULL) |
| return 0; |
| |
| MachHeader *Header = (MachHeader *)Buf; |
| |
| if (Header->magic != MH_MAGIC && Header->magic != MH_MAGIC_64) { |
| if (ContextRef->FreeBytes != NULL) |
| ContextRef->FreeBytes(ContextRef->ReaderContext, Buf, FreeContext); |
| return 0; |
| } |
| |
| // Read the commands. |
| uint32_t Length = Header->sizeofcmds; |
| if (ContextRef->FreeBytes != NULL) |
| ContextRef->FreeBytes(ContextRef->ReaderContext, Buf, FreeContext); |
| |
| Buf = ContextRef->ReadBytes(ContextRef->ReaderContext, |
| ImageStart, |
| Length, |
| &FreeContext); |
| if (Buf == NULL) |
| return 0; |
| Header = (MachHeader *)Buf; |
| |
| // Find the TEXT segment and figure out where the end is. |
| unsigned long TextSize; |
| uint8_t *TextSegment = getsegmentdata(Header, "__TEXT", &TextSize); |
| if (ContextRef->FreeBytes != NULL) |
| ContextRef->FreeBytes(ContextRef->ReaderContext, Buf, FreeContext); |
| |
| if (TextSegment == NULL) { |
| return 0; |
| } |
| unsigned long TextEnd = TextSegment - (uint8_t *)Buf + TextSize; |
| |
| // Read everything including the TEXT segment. |
| Buf = ContextRef->ReadBytes(ContextRef->ReaderContext, |
| ImageStart, |
| TextEnd, |
| &FreeContext); |
| if (Buf == NULL) |
| return 0; |
| Header = (MachHeader *)Buf; |
| |
| // Find all the sections and fill out the reflection info. |
| swift_reflection_legacy_info_t info = {}; |
| |
| int success = 0; |
| success = swift_reflection_interop_findSection(Header, |
| "__swift3_fieldmd", |
| &info.fieldmd) || success; |
| success = swift_reflection_interop_findSection(Header, |
| "__swift3_assocty", |
| &info.assocty) || success; |
| success = swift_reflection_interop_findSection(Header, |
| "__swift3_builtin", |
| &info.builtin) || success; |
| success = swift_reflection_interop_findSection(Header, |
| "__swift3_capture", |
| &info.capture) || success; |
| success = swift_reflection_interop_findSection(Header, |
| "__swift3_typeref", |
| &info.typeref) || success; |
| success = swift_reflection_interop_findSection(Header, |
| "__swift3_reflstr", |
| &info.reflstr) || success; |
| |
| if (!success) { |
| if (ContextRef->FreeBytes != NULL) |
| ContextRef->FreeBytes(ContextRef->ReaderContext, Buf, FreeContext); |
| return 0; |
| } |
| |
| info.LocalStartAddress = (uintptr_t)Buf; |
| info.RemoteStartAddress = (uintptr_t)ImageStart; |
| |
| Library->Functions.addReflectionInfoLegacy(Library->Context, info); |
| |
| // Find the data segment and add it to our list. |
| unsigned long DataSize; |
| const uint8_t *DataSegment = getsegmentdata(Header, "__DATA", &DataSize); |
| uintptr_t DataSegmentStart = (uintptr_t)(DataSegment - (const uint8_t *)Buf + ImageStart); |
| |
| struct SwiftReflectionInteropContextLegacyImageRangeList *Node = |
| (struct SwiftReflectionInteropContextLegacyImageRangeList *)malloc(sizeof(*Node)); |
| Node->Next = ContextRef->LegacyImageRangeList; |
| Node->Start = ImageStart; |
| Node->End = DataSegmentStart + DataSize; |
| ContextRef->LegacyImageRangeList = Node; |
| |
| // If the buffer needs to be freed, save buffer and free context to free it when the |
| // reflection context is destroyed. |
| if (ContextRef->FreeBytes != NULL) { |
| struct SwiftReflectionInteropContextFreeList *FreeListNode = |
| (struct SwiftReflectionInteropContextFreeList *)malloc(sizeof(*FreeListNode)); |
| FreeListNode->Next = ContextRef->FreeList; |
| FreeListNode->Pointer = Buf; |
| FreeListNode->Context = FreeContext; |
| ContextRef->FreeList = FreeListNode; |
| } |
| |
| return 1; |
| } |
| |
| static inline int |
| swift_reflection_interop_addImage(SwiftReflectionInteropContextRef ContextRef, |
| swift_addr_t imageStart) { |
| FOREACH_LIBRARY { |
| int Success; |
| if (Library->IsLegacy) { |
| Success = swift_reflection_interop_addImageLegacy(ContextRef, |
| Library, |
| imageStart); |
| } else { |
| Success = Library->Functions.addImage(Library->Context, imageStart); |
| } |
| if (Success) { |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| static inline int |
| swift_reflection_interop_readIsaMask(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t *outIsaMask) { |
| FOREACH_LIBRARY { |
| int Success = Library->Functions.readIsaMask(Library->Context, outIsaMask); |
| if (Success) |
| return 1; |
| } |
| return 0; |
| } |
| |
| static inline swift_metadata_interop_t |
| swift_reflection_interop_lookupMetadata(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Metadata) { |
| swift_metadata_interop_t Result = {}; |
| struct SwiftReflectionInteropContextLibrary *Library = |
| swift_reflection_interop_libraryForAddress(ContextRef, Metadata); |
| if (Library != NULL) { |
| Result.Metadata = Metadata; |
| Result.Library = (int)LIBRARY_INDEX; |
| } |
| return Result; |
| } |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_typeRefForMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata) { |
| DECLARE_LIBRARY(Metadata.Library); |
| swift_typeref_interop_t Result; |
| Result.Typeref = Library->Functions. |
| typeRefForMetadata(Library->Context, Metadata.Metadata); |
| Result.Library = Metadata.Library; |
| return Result; |
| } |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_typeRefForInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object) { |
| swift_typeref_interop_t Result = {}; |
| struct SwiftReflectionInteropContextLibrary *Library |
| = swift_reflection_interop_libraryForObject(ContextRef, Object); |
| if (Library != NULL) { |
| swift_typeref_t Typeref = Library->Functions.typeRefForInstance(Library->Context, |
| Object); |
| Result.Typeref = Typeref; |
| Result.Library = (int)LIBRARY_INDEX; |
| } |
| return Result; |
| } |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_typeRefForMangledTypeName( |
| SwiftReflectionInteropContextRef ContextRef, |
| const char *MangledName, |
| uint64_t Length) { |
| swift_typeref_interop_t Result; |
| FOREACH_LIBRARY { |
| swift_typeref_t Typeref = Library->Functions.typeRefForMangledTypeName( |
| Library->Context, MangledName, Length); |
| if (Typeref == 0) |
| continue; |
| |
| Result.Typeref = Typeref; |
| Result.Library = (int)LIBRARY_INDEX; |
| return Result; |
| } |
| |
| Result.Typeref = 0; |
| Result.Library = 0; |
| return Result; |
| } |
| |
| static inline char * |
| swift_reflection_interop_copyDemangledNameForTypeRef( |
| SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| if (Library->Functions.copyDemangledNameForTypeRef) |
| return Library->Functions.copyDemangledNameForTypeRef(Library->Context, |
| OpaqueTypeRef.Typeref); |
| return NULL; |
| } |
| |
| static inline swift_typeinfo_t |
| swift_reflection_interop_infoForTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| return Library->Functions.infoForTypeRef(Library->Context, OpaqueTypeRef.Typeref); |
| } |
| |
| static inline swift_childinfo_interop_t |
| swift_reflection_interop_childOfTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef, |
| unsigned Index) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| swift_childinfo_t LibResult = Library->Functions.childOfTypeRef(Library->Context, |
| OpaqueTypeRef.Typeref, |
| Index); |
| swift_childinfo_interop_t Result; |
| Result.Name = LibResult.Name; |
| Result.Offset = LibResult.Offset; |
| Result.Kind = LibResult.Kind; |
| Result.TR.Typeref = LibResult.TR; |
| Result.TR.Library = OpaqueTypeRef.Library; |
| return Result; |
| } |
| |
| static inline swift_typeinfo_interop_t |
| swift_reflection_interop_infoForMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata) { |
| DECLARE_LIBRARY(Metadata.Library); |
| return Library->Functions.infoForMetadata(Library->Context, Metadata.Metadata); |
| } |
| |
| static inline swift_childinfo_interop_t |
| swift_reflection_interop_childOfMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata, |
| unsigned Index) { |
| DECLARE_LIBRARY(Metadata.Library); |
| swift_childinfo_t LibResult = Library->Functions.childOfMetadata(Library->Context, |
| Metadata.Metadata, |
| Index); |
| swift_childinfo_interop_t Result; |
| Result.Name = LibResult.Name; |
| Result.Offset = LibResult.Offset; |
| Result.Kind = LibResult.Kind; |
| Result.TR.Typeref = LibResult.TR; |
| Result.TR.Library = Metadata.Library; |
| return Result; |
| } |
| |
| static inline swift_typeinfo_interop_t |
| swift_reflection_interop_infoForInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object) { |
| swift_typeinfo_t Result = {}; |
| struct SwiftReflectionInteropContextLibrary *Library |
| = swift_reflection_interop_libraryForObject(ContextRef, Object); |
| |
| if (Library != NULL) { |
| Result = Library->Functions.infoForInstance(Library->Context, Object); |
| } else { |
| Result.Kind = SWIFT_UNKNOWN; |
| } |
| |
| return Result; |
| } |
| |
| static inline swift_childinfo_interop_t |
| swift_reflection_interop_childOfInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object, |
| unsigned Index) { |
| swift_childinfo_interop_t Result = {}; |
| struct SwiftReflectionInteropContextLibrary *Library |
| = swift_reflection_interop_libraryForObject(ContextRef, Object); |
| if (Library != NULL) { |
| swift_childinfo_t LibResult = Library->Functions.childOfInstance(Library->Context, |
| Object, Index); |
| Result.Name = LibResult.Name; |
| Result.Offset = LibResult.Offset; |
| Result.Kind = LibResult.Kind; |
| Result.TR.Typeref = LibResult.TR; |
| Result.TR.Library = (int)LIBRARY_INDEX; |
| } else { |
| Result.Kind = SWIFT_UNKNOWN; |
| } |
| return Result; |
| } |
| |
| static inline unsigned |
| swift_reflection_interop_genericArgumentCountOfTypeRef( |
| SwiftReflectionInteropContextRef ContextRef, swift_typeref_interop_t OpaqueTypeRef) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| return Library->Functions.genericArgumentCountOfTypeRef(OpaqueTypeRef.Typeref); |
| } |
| |
| static inline swift_typeref_interop_t |
| swift_reflection_interop_genericArgumentOfTypeRef( |
| SwiftReflectionInteropContextRef ContextRef, swift_typeref_interop_t OpaqueTypeRef, |
| unsigned Index) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| swift_typeref_interop_t Result; |
| Result.Typeref = Library->Functions.genericArgumentOfTypeRef(OpaqueTypeRef.Typeref, |
| Index); |
| Result.Library = OpaqueTypeRef.Library; |
| return Result; |
| } |
| |
| static inline int |
| swift_reflection_interop_projectExistential(SwiftReflectionInteropContextRef ContextRef, |
| swift_addr_t ExistentialAddress, |
| swift_typeref_interop_t ExistentialTypeRef, |
| swift_typeref_interop_t *OutInstanceTypeRef, |
| swift_addr_t *OutStartOfInstanceData) { |
| DECLARE_LIBRARY(ExistentialTypeRef.Library); |
| int Success = Library->Functions.projectExistential(Library->Context, |
| ExistentialAddress, |
| ExistentialTypeRef.Typeref, |
| &OutInstanceTypeRef->Typeref, |
| OutStartOfInstanceData); |
| if (!Success) |
| return 0; |
| |
| OutInstanceTypeRef->Library = ExistentialTypeRef.Library; |
| return 1; |
| } |
| |
| static inline void |
| swift_reflection_interop_dumpTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| Library->Functions.dumpTypeRef(OpaqueTypeRef.Typeref); |
| } |
| |
| static inline void |
| swift_reflection_interop_dumpInfoForTypeRef(SwiftReflectionInteropContextRef ContextRef, |
| swift_typeref_interop_t OpaqueTypeRef) { |
| DECLARE_LIBRARY(OpaqueTypeRef.Library); |
| Library->Functions.dumpInfoForTypeRef(Library->Context, OpaqueTypeRef.Typeref); |
| } |
| |
| static inline void |
| swift_reflection_interop_dumpInfoForMetadata(SwiftReflectionInteropContextRef ContextRef, |
| swift_metadata_interop_t Metadata) { |
| DECLARE_LIBRARY(Metadata.Library); |
| Library->Functions.dumpInfoForMetadata(Library->Context, Metadata.Metadata); |
| } |
| |
| static inline void |
| swift_reflection_interop_dumpInfoForInstance(SwiftReflectionInteropContextRef ContextRef, |
| uintptr_t Object) { |
| struct SwiftReflectionInteropContextLibrary *Library |
| = swift_reflection_interop_libraryForObject(ContextRef, Object); |
| if (Library != NULL) { |
| Library->Functions.dumpInfoForInstance(Library->Context, Object); |
| } |
| } |
| |
| static inline size_t |
| swift_reflection_interop_demangle(SwiftReflectionInteropContextRef ContextRef, |
| const char *MangledName, |
| size_t Length, |
| char *OutDemangledName, |
| size_t MaxLength) { |
| FOREACH_LIBRARY { |
| return Library->Functions.demangle(MangledName, Length, OutDemangledName, MaxLength); |
| } |
| return 0; |
| } |
| |
| #undef FOREACH_LIBRARY |
| #undef LIBRARY_INDEX |
| #undef DECLARE_LIBRARY |
| |
| /// @} |
| |
| #endif // defined(__APPLE__) && defined(__MACH__) |
| |
| #endif // SWIFT_REMOTE_MIRROR_LEGACY_INTEROP_H |
| |