Merge pull request #14916 from mikeash/remotemirror-hide-reflection-sections

[RemoteMirrors] Improve the API to no longer require clients to know about section names, and make it easier to interoperate with multiple versions of the library.
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index 95aaa18..c46fba2 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -18,6 +18,10 @@
 #ifndef SWIFT_REFLECTION_REFLECTIONCONTEXT_H
 #define SWIFT_REFLECTION_REFLECTIONCONTEXT_H
 
+#if defined(__APPLE__) && defined(__MACH__)
+#include <mach-o/getsect.h>
+#endif
+
 #include "swift/Remote/MemoryReader.h"
 #include "swift/Remote/MetadataReader.h"
 #include "swift/Reflection/Records.h"
@@ -30,6 +34,32 @@
 #include <set>
 #include <vector>
 #include <unordered_map>
+#include <utility>
+
+#if defined(__APPLE__) && defined(__MACH__)
+#ifndef __LP64__
+typedef const struct mach_header MachHeader;
+#else
+typedef const struct mach_header_64 MachHeader;
+#endif
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
+template <typename Section>
+static std::pair<Section, bool> findSection(MachHeader *Header,
+                                            const char *Name) {
+  unsigned long Size;
+  auto Address = getsectiondata(Header, "__TEXT", Name, &Size);
+  if (!Address)
+    return {{nullptr, nullptr}, false};
+
+  auto End = reinterpret_cast<uintptr_t>(Address) + Size;
+
+  return {{reinterpret_cast<const void *>(Address),
+           reinterpret_cast<const void *>(End)},
+          true};
+}
+#endif
 
 namespace swift {
 namespace reflection {
@@ -46,6 +76,11 @@
 
   std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache;
 
+  /// All buffers we need to keep around long term. This will automatically free them
+  /// when this object is destroyed.
+  std::vector<MemoryReader::ReadBytesResult> savedBuffers;
+  std::vector<std::tuple<RemoteAddress, RemoteAddress>> dataSegments;
+
 public:
   using super::getBuilder;
   using super::readDemanglingForContextDescriptor;
@@ -62,7 +97,7 @@
 
   ReflectionContext(const ReflectionContext &other) = delete;
   ReflectionContext &operator=(const ReflectionContext &other) = delete;
-
+  
   MemoryReader &getReader() {
     return *this->Reader;
   }
@@ -76,10 +111,108 @@
     getBuilder().dumpAllSections();
   }
 
+#if defined(__APPLE__) && defined(__MACH__)
+  bool addImage(RemoteAddress ImageStart) {
+    auto Buf = this->getReader().readBytes(ImageStart, sizeof(MachHeader));
+    if (!Buf)
+      return false;
+
+    auto Header = reinterpret_cast<MachHeader *>(Buf.get());
+    if (Header->magic != MH_MAGIC && Header->magic != MH_MAGIC_64) {
+      return false;
+    }
+    auto Length = Header->sizeofcmds;
+
+    // Read the commands.
+    Buf = this->getReader().readBytes(ImageStart, Length);
+    if (!Buf)
+      return false;
+
+    // Find the TEXT segment and figure out where the end is.
+    Header = reinterpret_cast<MachHeader *>(Buf.get());
+    unsigned long TextSize;
+    auto *TextSegment = getsegmentdata(Header, "__TEXT", &TextSize);
+    if (TextSegment == nullptr)
+      return false;
+    
+    auto TextEnd =
+        TextSegment - reinterpret_cast<const uint8_t *>(Buf.get()) + TextSize;
+
+    // Read everything including the TEXT segment.
+    Buf = this->getReader().readBytes(ImageStart, TextEnd);
+    if (!Buf)
+      return false;
+
+    // Read all the metadata parts.
+    Header = reinterpret_cast<MachHeader *>(Buf.get());
+
+    // The docs say "not all sections may be present." We'll succeed if ANY of
+    // them are present. Not sure if that's the right thing to do.
+    auto FieldMd = findSection<FieldSection>(Header, "__swift5_fieldmd");
+    auto AssocTyMd =
+        findSection<AssociatedTypeSection>(Header, "__swift5_assocty");
+    auto BuiltinTyMd =
+        findSection<BuiltinTypeSection>(Header, "__swift5_builtin");
+    auto CaptureMd = findSection<CaptureSection>(Header, "__swift5_capture");
+    auto TyperefMd = findSection<GenericSection>(Header, "__swift5_typeref");
+    auto ReflStrMd = findSection<GenericSection>(Header, "__swift5_reflstr");
+
+    bool success = FieldMd.second || AssocTyMd.second || BuiltinTyMd.second ||
+                   CaptureMd.second || TyperefMd.second || ReflStrMd.second;
+    if (!success)
+      return false;
+
+    auto LocalStartAddress = reinterpret_cast<uintptr_t>(Buf.get());
+    auto RemoteStartAddress = static_cast<uintptr_t>(ImageStart.getAddressData());
+
+    ReflectionInfo info = {
+        {{FieldMd.first.startAddress(), FieldMd.first.endAddress()}, 0},
+        {{AssocTyMd.first.startAddress(), AssocTyMd.first.endAddress()}, 0},
+        {{BuiltinTyMd.first.startAddress(), BuiltinTyMd.first.endAddress()}, 0},
+        {{CaptureMd.first.startAddress(), CaptureMd.first.endAddress()}, 0},
+        {{TyperefMd.first.startAddress(), TyperefMd.first.endAddress()}, 0},
+        {{ReflStrMd.first.startAddress(), ReflStrMd.first.endAddress()}, 0},
+        LocalStartAddress,
+        RemoteStartAddress};
+
+    this->addReflectionInfo(info);
+
+    unsigned long DataSize;
+    auto *DataSegment = getsegmentdata(Header, "__DATA", &DataSize);
+    if (DataSegment != nullptr) {
+      auto DataSegmentStart = DataSegment - reinterpret_cast<const uint8_t *>(Buf.get())
+                            + ImageStart.getAddressData();
+      auto DataSegmentEnd = DataSegmentStart + DataSize;
+      dataSegments.push_back(std::make_tuple(RemoteAddress(DataSegmentStart),
+                                             RemoteAddress(DataSegmentEnd)));
+    }
+    
+    savedBuffers.push_back(std::move(Buf));
+
+    return true;
+  }
+#endif // defined(__APPLE__) && defined(__MACH__)
+  
   void addReflectionInfo(ReflectionInfo I) {
     getBuilder().addReflectionInfo(I);
   }
+  
+  bool ownsObject(RemoteAddress ObjectAddress) {
+    auto MetadataAddress = readMetadataFromInstance(ObjectAddress.getAddressData());
+    if (!MetadataAddress)
+      return 0;
 
+    for (auto Segment : dataSegments) {
+      auto Start = std::get<0>(Segment);
+      auto End = std::get<1>(Segment);
+      if (Start.getAddressData() <= *MetadataAddress
+          && *MetadataAddress < End.getAddressData())
+        return 1;
+    }
+  
+    return 0;
+  }
+  
   /// Return a description of the layout of a class instance with the given
   /// metadata as its isa pointer.
   const TypeInfo *getMetadataTypeInfo(StoredPointer MetadataAddress) {
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index c50af6a..c63b608 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -57,6 +57,10 @@
   const void *startAddress() const {
     return Begin;
   }
+  
+  const void *endAddress() const {
+    return End;
+  }
 
   const_iterator begin() const {
     return const_iterator(Begin, End);
@@ -334,6 +338,10 @@
   void addReflectionInfo(ReflectionInfo I) {
     ReflectionInfos.push_back(I);
   }
+  
+  const std::vector<ReflectionInfo> &getReflectionInfos() {
+    return ReflectionInfos;
+  }
 
 private:
   std::vector<ReflectionInfo> ReflectionInfos;
diff --git a/include/swift/Remote/CMemoryReader.h b/include/swift/Remote/CMemoryReader.h
index a9303e7..a1a168e 100644
--- a/include/swift/Remote/CMemoryReader.h
+++ b/include/swift/Remote/CMemoryReader.h
@@ -62,17 +62,26 @@
     if (!length)
       return false;
 
-    auto buffer = std::unique_ptr<uint8_t>(new uint8_t[length + 1]);
-    if (!readBytes(address, buffer.get(), length + 1))
+    auto Buf = readBytes(address, length);
+    if (!Buf)
       return false;
-
-    dest = std::string(reinterpret_cast<const char *>(buffer.get()));
+    
+    dest = std::string(reinterpret_cast<const char *>(Buf.get()), length);
     return true;
   }
 
-  bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) override {
-    return Impl.readBytes(Impl.reader_context,
-                          address.getAddressData(), dest, size) != 0;
+  ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
+      void *FreeContext;
+      auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(), size,
+                                &FreeContext);
+
+      auto Free = Impl.free;
+      if (Free == nullptr)
+        return ReadBytesResult(Ptr, [](const void *) {});
+      
+      auto ReaderContext = Impl.reader_context;
+      auto freeLambda = [=](const void *Ptr) { Free(ReaderContext, Ptr, FreeContext); };
+      return ReadBytesResult(Ptr, freeLambda);
   }
 };
 
diff --git a/include/swift/Remote/InProcessMemoryReader.h b/include/swift/Remote/InProcessMemoryReader.h
index c1e01a3..e631871 100644
--- a/include/swift/Remote/InProcessMemoryReader.h
+++ b/include/swift/Remote/InProcessMemoryReader.h
@@ -42,9 +42,8 @@
     return true;
   }
 
-  bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) override {
-    std::memcpy(dest, address.getLocalPointer<void>(), (size_t) size);
-    return true;
+  ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
+    return ReadBytesResult(address.getLocalPointer<void>(), [](const void *) {});
   }
 };
  
diff --git a/include/swift/Remote/MemoryReader.h b/include/swift/Remote/MemoryReader.h
index 53e48ca..038ffab 100644
--- a/include/swift/Remote/MemoryReader.h
+++ b/include/swift/Remote/MemoryReader.h
@@ -20,7 +20,11 @@
 
 #include "swift/Remote/RemoteAddress.h"
 
+#include <cstring>
+#include <functional>
+#include <memory>
 #include <string>
+#include <tuple>
 
 namespace swift {
 namespace remote {
@@ -31,6 +35,9 @@
 /// representation of the address space of a remote process.
 class MemoryReader {
 public:
+  /// A convenient name for the return type from readBytes.
+  using ReadBytesResult = std::unique_ptr<const void, std::function<void(const void *)>>;
+
   /// Return the size of an ordinary pointer in the remote process, in bytes.
   virtual uint8_t getPointerSize() = 0;
 
@@ -40,19 +47,12 @@
   /// Look up the given public symbol name in the remote process.
   virtual RemoteAddress getSymbolAddress(const std::string &name) = 0;
 
-  /// Attempts to read 'size' bytes from the given address in the
-  /// remote process.
-  ///
-  /// Returns false if the operation failed.
-  virtual bool readBytes(RemoteAddress address, uint8_t *dest,
-                         uint64_t size) = 0;
-
   /// Attempts to read a C string from the given address in the remote
   /// process.
   ///
   /// Returns false if the operation failed.
   virtual bool readString(RemoteAddress address, std::string &dest) = 0;
-
+  
   /// Attempts to read an integer from the given address in the remote
   /// process.
   ///
@@ -63,6 +63,42 @@
                      sizeof(IntegerType));
   }
 
+  /// Attempts to read 'size' bytes from the given address in the remote process.
+  ///
+  /// Returns a pointer to the requested data and a function that must be called to
+  /// free that data when done. The pointer will be NULL if the operation failed.
+  ///
+  /// NOTE: subclasses MUST override at least one of the readBytes functions. The default
+  /// implementation calls through to the other one.
+  virtual ReadBytesResult
+    readBytes(RemoteAddress address, uint64_t size) {
+    auto *Buf = malloc(size);
+    ReadBytesResult Result(Buf, [](const void *ptr) {
+      free(const_cast<void *>(ptr));
+    });
+    bool success = readBytes(address, reinterpret_cast<uint8_t *>(Buf), size);
+    if (!success) {
+      Result.reset();
+    }
+    return Result;
+  }
+
+  /// Attempts to read 'size' bytes from the given address in the
+  /// remote process.
+  ///
+  /// Returns false if the operation failed.
+  ///
+  /// NOTE: subclasses MUST override at least one of the readBytes functions. The default
+  /// implementation calls through to the other one.
+  virtual bool readBytes(RemoteAddress address, uint8_t *dest, uint64_t size) {
+    auto Ptr = readBytes(address, size);
+    if (!Ptr)
+      return false;
+    
+    memcpy(dest, Ptr.get(), size);
+    return true;
+  }
+          
   virtual ~MemoryReader() = default;
 };
 
diff --git a/include/swift/SwiftRemoteMirror/MemoryReaderInterface.h b/include/swift/SwiftRemoteMirror/MemoryReaderInterface.h
index df98c73..f78fc79 100644
--- a/include/swift/SwiftRemoteMirror/MemoryReaderInterface.h
+++ b/include/swift/SwiftRemoteMirror/MemoryReaderInterface.h
@@ -32,10 +32,13 @@
 // in the system library, so we use 'swift_addr_t'.
 typedef uint64_t swift_addr_t;
 
+typedef void (*FreeBytesFunction)(void *reader_context, const void *bytes, void *context);
+
 typedef uint8_t (*PointerSizeFunction)(void *reader_context);
 typedef uint8_t (*SizeSizeFunction)(void *reader_context);
-typedef int (*ReadBytesFunction)(void *reader_context, swift_addr_t address,
-                                 void *dest, uint64_t size);
+typedef const void *(*ReadBytesFunction)(void *reader_context, swift_addr_t address,
+                                         uint64_t size,
+                                         void **outFreeContext);
 typedef uint64_t (*GetStringLengthFunction)(void *reader_context,
                                             swift_addr_t address);
 typedef swift_addr_t (*GetSymbolAddressFunction)(void *reader_context,
@@ -53,6 +56,9 @@
   /// Get the size in bytes of the target's size type.
   SizeSizeFunction getSizeSize;
 
+  /// Free memory returned from readBytes. May be NULL if memory never needs to be freed.
+  FreeBytesFunction free;
+
   // FIXME: -Wdocumentation complains about \param and \returns on function pointers.
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdocumentation"
@@ -60,9 +66,12 @@
   /// Read a sequence of bytes at an address in the target.
   ///
   /// \param address the address in the target address space
-  /// \param dest the caller-owned buffer into which to store the string
   /// \param size the number of bytes to read
-  /// \returns true if the read was successful
+  /// \param outFreeContext on return, an arbitrary context pointer that the caller will
+  ///                       pass to the free function
+  /// \returns A pointer to the requested memory, or NULL if the memory could not be read.
+  ///          The caller must invoke the free function on the returned pointer once it's
+  ///          done using the memory.
   ReadBytesFunction readBytes;
 
   /// Get the string length at the given address.
diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
index 1909b94..3459362 100644
--- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
+++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
@@ -17,8 +17,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef SWIFT_REFLECTION_SWIFT_REFLECTION_H
-#define SWIFT_REFLECTION_SWIFT_REFLECTION_H
+#ifndef SWIFT_REMOTE_MIRROR_H
+#define SWIFT_REMOTE_MIRROR_H
 
 #include "Platform.h"
 #include "MemoryReaderInterface.h"
@@ -45,11 +45,11 @@
 SWIFT_REMOTE_MIRROR_LINKAGE
 SwiftReflectionContextRef
 swift_reflection_createReflectionContext(void *ReaderContext,
-                                         PointerSizeFunction getPointerSize,
-                                         SizeSizeFunction getSizeSize,
-                                         ReadBytesFunction readBytes,
-                                         GetStringLengthFunction getStringLength,
-                                         GetSymbolAddressFunction getSymbolAddress);
+                                         uint8_t PointerSize,
+                                         FreeBytesFunction Free,
+                                         ReadBytesFunction ReadBytes,
+                                         GetStringLengthFunction GetStringLength,
+                                         GetSymbolAddressFunction GetSymbolAddress);
 
 /// Destroys an opaque reflection context.
 SWIFT_REMOTE_MIRROR_LINKAGE
@@ -58,8 +58,18 @@
 
 /// Add reflection sections for a loaded Swift image.
 SWIFT_REMOTE_MIRROR_LINKAGE
-void swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
-                                        swift_reflection_info_t Info);
+void
+swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
+                                   swift_reflection_info_t Info);
+
+#if defined(__APPLE__) && defined(__MACH__)
+/// 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
+int
+swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
+                          swift_addr_t imageStart);
+#endif
 
 /// Returns a boolean indicating if the isa mask was successfully
 /// read, in which case it is stored in the isaMask out parameter.
@@ -78,6 +88,24 @@
 swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
                                     uintptr_t Metadata);
 
+/// Returns whether the given object appears to have metadata understood
+/// by this library. Images must be added using
+/// swift_reflection_addImage, not swift_reflection_addReflectionInfo,
+/// for this function to work properly. If addImage is used, a negative
+/// result is always correct, but a positive result may be a false
+/// positive if the address in question is not really a Swift or
+/// Objective-C object. If addReflectionInfo is used, the return value
+/// will always be false.
+SWIFT_REMOTE_MIRROR_LINKAGE
+int
+swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object);
+
+/// Returns the metadata pointer for a given object.
+SWIFT_REMOTE_MIRROR_LINKAGE
+uintptr_t
+swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
+                                   uintptr_t Object);
+
 /// Returns an opaque type reference for a class or closure context
 /// instance pointer, or NULL if one can't be constructed.
 ///
diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h
new file mode 100644
index 0000000..631df0d
--- /dev/null
+++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h
@@ -0,0 +1,887 @@
+//===--- 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 <dlfcn.h>
+#include <mach-o/getsect.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,
+    void *LibraryHandle,
+    void *LegacyLibraryHandle,
+    uint8_t PointerSize,
+    FreeBytesFunction FreeBytes,
+    ReadBytesFunction ReadBytes,
+    GetStringLengthFunction GetStringLength,
+    GetSymbolAddressFunction GetSymbolAddress);
+
+static inline void
+swift_reflection_interop_destroyReflectionContext(
+  SwiftReflectionInteropContextRef ContextRef);
+
+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);
+
+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 swift_typeinfo_t
+swift_reflection_interop_infoForTypeRef(SwiftReflectionInteropContextRef ContextRef,
+                                        swift_typeref_interop_t OpaqueTypeRef);
+
+static inline swift_childinfo_t
+swift_reflection_interop_childOfTypeRef(SwiftReflectionInteropContextRef ContextRef,
+                                       swift_typeref_interop_t OpaqueTypeRef,
+                                        unsigned Index);
+
+static inline swift_typeinfo_t
+swift_reflection_interop_infoForMetadata(SwiftReflectionInteropContextRef ContextRef,
+                                        swift_metadata_interop_t Metadata);
+
+static inline swift_childinfo_t
+swift_reflection_interop_childOfMetadata(SwiftReflectionInteropContextRef ContextRef,
+                                        swift_metadata_interop_t Metadata,
+                                        unsigned Index);
+
+static inline swift_typeinfo_t
+swift_reflection_interop_infoForInstance(SwiftReflectionInteropContextRef ContextRef,
+                                         uintptr_t Object);
+
+static inline swift_childinfo_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 {
+  uint16_t (*getSupportedMetadataVersion)(void);
+
+  SwiftReflectionContextRef (*createReflectionContext)(
+    void *ReaderContext,
+    uint8_t PointerSize,
+    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);
+  
+  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);
+
+  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 SwiftReflectionInteropContextLegacyDataSegmentList {
+  struct SwiftReflectionInteropContextLegacyDataSegmentList *Next;
+  swift_addr_t Start, End;
+};
+
+struct SwiftReflectionInteropContext {
+  void *ReaderContext;
+  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);
+  
+  // Currently we support at most two libraries.
+  struct SwiftReflectionInteropContextLibrary Libraries[2];
+  int LibraryCount;
+  
+  struct SwiftReflectionInteropContextFreeList *FreeList;
+  struct SwiftReflectionInteropContextLegacyDataSegmentList *LegacyDataSegmentList;
+};
+
+#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_libraryOwnsObject(
+  struct SwiftReflectionInteropContext *ContextRef,
+  struct SwiftReflectionInteropContextLibrary *Library,
+  uintptr_t Object) {
+  if (!Library->IsLegacy)
+    return Library->Functions.ownsObject(Library->Context, Object);
+  
+  // The legacy library doesn't have this. Do it ourselves if we can. We need
+  // metadataForObject from a non-legacy library to do it.
+  uintptr_t Metadata = 0;
+  FOREACH_LIBRARY {
+    if (Library->IsLegacy)
+      continue;
+    
+    Metadata = Library->Functions.metadataForObject(Library->Context, Object);
+    break;
+  }
+  
+  // If we couldn't retrieve metadata, assume it's ours.
+  if (Metadata == 0)
+    return 1;
+  
+  // Search the data segment list to see if the metadata is in one of them.
+  struct SwiftReflectionInteropContextLegacyDataSegmentList *Node =
+    ContextRef->LegacyDataSegmentList;
+  while (Node != NULL) {
+    if (Node->Start <= Metadata && Metadata < Node->End)
+      return 1;
+    Node = Node->Next;
+  }
+  return 0;
+}
+
+static inline void
+swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Context,
+                                       void *Handle,
+                                       int IsLegacy) {
+  if (Handle == NULL)
+    return;
+
+  struct SwiftReflectionInteropContextLibrary *Library = &Context
+    ->Libraries[Context->LibraryCount];
+  struct SwiftReflectionFunctions *Functions = &Library->Functions;
+
+#ifndef __cplusplus
+#define decltype(x) void *
+#endif
+#define LOAD_NAMED(field, symbol) do { \
+    Functions->field = (decltype(Functions->field))dlsym(Handle, symbol); \
+    if (Functions->field == NULL) return; \
+  } while (0)
+#define LOAD(name) LOAD_NAMED(name, "swift_reflection_" #name)
+  
+  LOAD(getSupportedMetadataVersion);
+  uint16_t version = Functions->getSupportedMetadataVersion();
+  if (version < SWIFT_LEGACY_METADATA_MIN_VERSION)
+    return;
+  
+  if (IsLegacy) {
+    LOAD_NAMED(createReflectionContextLegacy, "swift_reflection_createReflectionContext");
+    LOAD_NAMED(addReflectionInfoLegacy, "swift_reflection_addReflectionInfo");
+  } else {
+    LOAD(createReflectionContext);
+    LOAD(addReflectionInfo);
+    LOAD(addImage);
+    LOAD(ownsObject);
+    LOAD(metadataForObject);
+  }
+  
+  LOAD(destroyReflectionContext);
+  LOAD(readIsaMask);
+  LOAD(typeRefForMetadata);
+  LOAD(typeRefForInstance);
+  LOAD(typeRefForMangledTypeName);
+  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;
+  
+#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.
+  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 SwiftReflectionInteropContextRef
+swift_reflection_interop_createReflectionContext(
+    void *ReaderContext,
+    void *LibraryHandle,
+    void *LegacyLibraryHandle,
+    uint8_t PointerSize,
+    FreeBytesFunction FreeBytes,
+    ReadBytesFunction ReadBytes,
+    GetStringLengthFunction GetStringLength,
+    GetSymbolAddressFunction GetSymbolAddress) {
+  
+  SwiftReflectionInteropContextRef ContextRef =
+    (SwiftReflectionInteropContextRef)calloc(sizeof(*ContextRef), 1);
+  
+  swift_reflection_interop_loadFunctions(ContextRef, LibraryHandle, 0);
+  swift_reflection_interop_loadFunctions(ContextRef, LegacyLibraryHandle, 1);
+  
+  if (ContextRef->LibraryCount == 0) {
+    free(ContextRef);
+    return NULL;
+  }
+  
+  FOREACH_LIBRARY {
+    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 {
+      Library->Context = Library->Functions.createReflectionContext(ReaderContext,
+      PointerSize, FreeBytes, ReadBytes, GetStringLength, GetSymbolAddress);
+    }
+  }
+  
+  ContextRef->ReaderContext = ReaderContext;
+  ContextRef->FreeBytes = FreeBytes;
+  ContextRef->ReadBytes = ReadBytes;
+  ContextRef->GetStringLength = GetStringLength;
+  ContextRef->GetSymbolAddress = GetSymbolAddress;
+  
+  return ContextRef;
+}
+
+static inline void
+swift_reflection_interop_destroyReflectionContext(
+  SwiftReflectionInteropContextRef ContextRef) {
+  FOREACH_LIBRARY {
+    Library->Functions.destroyReflectionContext(Library->Context);
+  }
+  struct SwiftReflectionInteropContextLegacyDataSegmentList *LegacyDataSegmentList
+    = ContextRef->LegacyDataSegmentList;
+  while (LegacyDataSegmentList != NULL) {
+    struct SwiftReflectionInteropContextLegacyDataSegmentList *Next
+      = LegacyDataSegmentList->Next;
+    free(LegacyDataSegmentList);
+    LegacyDataSegmentList = 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;
+  }
+  free(ContextRef);
+}
+
+#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 = 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);
+  
+  struct SwiftReflectionInteropContextLegacyDataSegmentList *Node =
+    (struct SwiftReflectionInteropContextLegacyDataSegmentList *)malloc(sizeof(*Node));
+  Node->Next = ContextRef->LegacyDataSegmentList;
+  Node->Start = DataSegment - (const uint8_t *)Buf + ImageStart;
+  Node->End = Node->Start + DataSize;
+  ContextRef->LegacyDataSegmentList = 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 *Node =
+      (struct SwiftReflectionInteropContextFreeList *)malloc(sizeof(*Node));
+    Node->Next = ContextRef->FreeList;
+    Node->Pointer = Buf;
+    Node->Context = FreeContext;
+    ContextRef->FreeList = Node;
+  }
+  
+  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_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;
+  FOREACH_LIBRARY {
+    if (!swift_reflection_interop_libraryOwnsObject(ContextRef, Library, Object))
+      continue;
+    swift_typeref_t Typeref = Library->Functions.typeRefForInstance(Library->Context,
+                                                                     Object);
+    if (Typeref == 0)
+      continue;
+    
+    Result.Typeref = Typeref;
+    Result.Library = LIBRARY_INDEX;
+    return Result;
+  }
+  
+  Result.Typeref = 0;
+  Result.Library = 0;
+  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 = LIBRARY_INDEX;
+    return Result;
+  }
+  
+  Result.Typeref = 0;
+  Result.Library = 0;
+  return Result;
+}
+
+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_t
+swift_reflection_interop_childOfTypeRef(SwiftReflectionInteropContextRef ContextRef,
+                                       swift_typeref_interop_t OpaqueTypeRef,
+                                        unsigned Index) {
+  DECLARE_LIBRARY(OpaqueTypeRef.Library);
+  return Library->Functions.childOfTypeRef(Library->Context,
+                                           OpaqueTypeRef.Typeref,
+                                           Index);
+}
+
+static inline swift_typeinfo_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_t
+swift_reflection_interop_childOfMetadata(SwiftReflectionInteropContextRef ContextRef,
+                                        swift_metadata_interop_t Metadata,
+                                        unsigned Index) {
+  DECLARE_LIBRARY(Metadata.Library);
+  return Library->Functions.childOfMetadata(Library->Context, Metadata.Metadata, Index);
+}
+
+static inline swift_typeinfo_t
+swift_reflection_interop_infoForInstance(SwiftReflectionInteropContextRef ContextRef,
+                                         uintptr_t Object) {
+  swift_typeinfo_t Result = {};
+  FOREACH_LIBRARY {
+    if (!swift_reflection_interop_libraryOwnsObject(ContextRef, Library, Object))
+      continue;
+    
+    Result = Library->Functions.infoForInstance(Library->Context, Object);
+    if (Result.Kind == SWIFT_UNKNOWN)
+      continue;
+    
+    return Result;
+  }
+  
+  Result.Kind = SWIFT_UNKNOWN;
+  return Result;
+}
+
+static inline swift_childinfo_t
+swift_reflection_interop_childOfInstance(SwiftReflectionInteropContextRef ContextRef,
+                                         uintptr_t Object,
+                                         unsigned Index) {
+  FOREACH_LIBRARY {
+    if (!swift_reflection_interop_libraryOwnsObject(ContextRef, Library, Object))
+      continue;
+    
+    return Library->Functions.childOfInstance(Library->Context, Object, Index);
+  }
+  
+  swift_childinfo_t Result = {};
+  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) {
+  FOREACH_LIBRARY {
+    if (!swift_reflection_interop_libraryOwnsObject(ContextRef, Library, Object))
+      continue;
+    
+    Library->Functions.dumpInfoForInstance(Library->Context, Object);
+    return;
+  }
+}
+
+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
+
diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInteropTypes.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInteropTypes.h
new file mode 100644
index 0000000..934bf34
--- /dev/null
+++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInteropTypes.h
@@ -0,0 +1,43 @@
+//===--- SwiftRemoteMirrorLegacyInteropTypes.h - Legacy lib interop types. ------===//
+//
+// 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_TYPES_H
+#define SWIFT_REMOTE_MIRROR_LEGACY_INTEROP_TYPES_H
+
+#include "SwiftRemoteMirror.h"
+
+/// The remote representation of a Swift metada pointer as returned by
+/// interop wrappers.
+typedef struct swift_metadata_interop {
+  uintptr_t Metadata;
+  int Library;
+} swift_metadata_interop_t;
+
+/// The remote representation of a Swift typeref as returned by interop
+/// wrappers.
+typedef struct swift_typeref_interop {
+  swift_typeref_t Typeref;
+  int Library;
+} swift_typeref_interop_t;
+
+/// An opaque reflection context object.
+typedef struct SwiftReflectionInteropContext *SwiftReflectionInteropContextRef;
+
+#endif // SWIFT_REMOTE_MIRROR_LEGACY_INTEROP_TYPES_H
+
diff --git a/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift b/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift
index eb98ce8..ecb24b6 100644
--- a/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift
+++ b/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift
@@ -24,6 +24,7 @@
 let RequestInstanceKind = "k"
 let RequestInstanceAddress = "i"
 let RequestReflectionInfos = "r"
+let RequestImages = "m"
 let RequestReadBytes = "b"
 let RequestSymbolAddress = "s"
 let RequestStringLength = "l"
@@ -137,6 +138,21 @@
                         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<UInt8>?, size: UInt) {
+  debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
+  let header = unsafeBitCast(_dyld_get_image_header(i),
+    to: UnsafePointer<MachHeader>.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 sendBytes<T>(from address: UnsafePointer<T>, count: Int) {
   var source = address
   var bytesLeft = count
@@ -194,6 +210,21 @@
   }
 }
 
+/// Send all loadedimages loaded in the current process.
+internal func sendImages() {
+  debugLog("BEGIN \(#function)"); defer { debugLog("END \(#function)") }
+  let infos = (0..<_dyld_image_count()).map(getAddressInfoForImage)
+
+  debugLog("\(infos.count) reflection info bundles.")
+  precondition(infos.count >= 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)!
@@ -256,8 +287,7 @@
 /// This is the main "run loop" of the test harness.
 ///
 /// The parent will necessarily need to:
-/// - Get the addresses of all of the reflection sections for any swift dylibs
-///   that are loaded, where applicable.
+/// - Get the addresses of any swift dylibs that are loaded, where applicable.
 /// - Get the address of the `instance`
 /// - Get the pointer size of this process, which affects assumptions about the
 ///   the layout of runtime structures with pointer-sized fields.
@@ -275,6 +305,8 @@
       sendValue(instanceAddress)
     case String(validatingUTF8: RequestReflectionInfos)!:
       sendReflectionInfos()
+    case String(validatingUTF8: RequestImages)!:
+      sendImages()
     case String(validatingUTF8: RequestReadBytes)!:
       sendBytes()
     case String(validatingUTF8: RequestSymbolAddress)!:
diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp
index 58277cf..371df87 100644
--- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp
+++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp
@@ -16,6 +16,10 @@
 #include "swift/Runtime/Unreachable.h"
 #include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"
 
+#if defined(__APPLE__) && defined(__MACH__)
+#include <mach-o/getsect.h>
+#endif
+
 using namespace swift;
 using namespace swift::reflection;
 using namespace swift::remote;
@@ -23,6 +27,24 @@
 using NativeReflectionContext
   = ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>;
 
+struct SwiftReflectionContext {
+  NativeReflectionContext *nativeContext;
+  std::vector<std::function<void()>> freeFuncs;
+  std::vector<std::tuple<swift_addr_t, swift_addr_t>> dataSegments;
+  
+  SwiftReflectionContext(MemoryReaderImpl impl) {
+    auto Reader = std::make_shared<CMemoryReader>(impl);
+    nativeContext = new NativeReflectionContext(Reader);
+  }
+  
+  ~SwiftReflectionContext() {
+    delete nativeContext;
+    for (auto f : freeFuncs)
+      f();
+  }
+};
+
+
 uint16_t
 swift_reflection_getSupportedMetadataVersion() {
   return SWIFT_REFLECTION_METADATA_VERSION;
@@ -30,42 +52,78 @@
 
 SwiftReflectionContextRef
 swift_reflection_createReflectionContext(void *ReaderContext,
-                                         PointerSizeFunction getPointerSize,
-                                         SizeSizeFunction getSizeSize,
-                                         ReadBytesFunction readBytes,
-                                         GetStringLengthFunction getStringLength,
-                                         GetSymbolAddressFunction getSymbolAddress) {
+                                         uint8_t PointerSize,
+                                         FreeBytesFunction Free,
+                                         ReadBytesFunction ReadBytes,
+                                         GetStringLengthFunction GetStringLength,
+                                         GetSymbolAddressFunction GetSymbolAddress) {
+  assert((PointerSize == 4 || PointerSize == 8) && "We only support 32-bit and 64-bit.");
+  assert(PointerSize == sizeof(uintptr_t) &&
+         "We currently only support the pointer size this file was compiled with.");
+  
+  auto GetSize = PointerSize == 4
+    ? [](void *){ return (uint8_t)4; }
+    : [](void *){ return (uint8_t)8; };
   MemoryReaderImpl ReaderImpl {
     ReaderContext,
-    getPointerSize,
-    getSizeSize,
-    readBytes,
-    getStringLength,
-    getSymbolAddress
+    GetSize,
+    GetSize,
+    Free,
+    ReadBytes,
+    GetStringLength,
+    GetSymbolAddress
   };
 
-  auto Reader = std::make_shared<CMemoryReader>(ReaderImpl);
-  auto Context
-    = new swift::reflection::ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>(Reader);
-  return reinterpret_cast<SwiftReflectionContextRef>(Context);
+  return new SwiftReflectionContext(ReaderImpl);
 }
 
 void swift_reflection_destroyReflectionContext(SwiftReflectionContextRef ContextRef) {
-  auto Context = reinterpret_cast<swift::reflection::ReflectionContext<InProcess> *>(ContextRef);
-  delete Context;
+  delete ContextRef;
 }
 
 void
 swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
                                    swift_reflection_info_t Info) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
+  
   Context->addReflectionInfo(*reinterpret_cast<ReflectionInfo *>(&Info));
 }
 
+#if defined(__APPLE__) && defined(__MACH__)
+#ifndef __LP64__
+typedef const struct mach_header MachHeader;
+#else
+typedef const struct mach_header_64 MachHeader;
+#endif
+
+template <typename Section>
+static bool findSection(MachHeader *Header, const char *Name,
+                        Section &Sect) {
+  unsigned long Size;
+  auto Address = getsectiondata(Header, "__TEXT", Name, &Size);
+  if (!Address)
+    return false;
+  
+  Sect.section.Begin = Address;
+  auto End = reinterpret_cast<uintptr_t>(Address) + Size;
+  Sect.section.End = reinterpret_cast<void *>(End);
+  Sect.offset = 0;
+  
+  return true;
+}
+
+int
+swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
+                          swift_addr_t imageStart) {
+  auto Context = ContextRef->nativeContext;
+  return Context->addImage(RemoteAddress(imageStart));
+}
+#endif
+
 int
 swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
                              uintptr_t *outIsaMask) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto isaMask = Context->readIsaMask();
   if (isaMask) {
     *outIsaMask = *isaMask;
@@ -78,15 +136,31 @@
 swift_typeref_t
 swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
                                     uintptr_t Metadata) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TR = Context->readTypeFromMetadata(Metadata);
   return reinterpret_cast<swift_typeref_t>(TR);
 }
 
+int
+swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object) {
+  auto Context = ContextRef->nativeContext;
+  return Context->ownsObject(RemoteAddress(Object));
+}
+
+uintptr_t
+swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
+                                   uintptr_t Object) {
+  auto Context = ContextRef->nativeContext;
+  auto MetadataAddress = Context->readMetadataFromInstance(Object);
+  if (!MetadataAddress)
+    return 0;
+  return *MetadataAddress;
+}
+
 swift_typeref_t
 swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
                                     uintptr_t Object) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto MetadataAddress = Context->readMetadataFromInstance(Object);
   if (!MetadataAddress)
     return 0;
@@ -98,7 +172,7 @@
 swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
                                            const char *MangledTypeName,
                                            uint64_t Length) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TR = Context->readTypeFromMangledName(MangledTypeName, Length);
   return reinterpret_cast<swift_typeref_t>(TR);
 }
@@ -223,7 +297,7 @@
 swift_typeinfo_t
 swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
                                 swift_typeref_t OpaqueTypeRef) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
   auto TI = Context->getTypeInfo(TR);
   return convertTypeInfo(TI);
@@ -233,7 +307,7 @@
 swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
                                 swift_typeref_t OpaqueTypeRef,
                                 unsigned Index) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
   auto *TI = Context->getTypeInfo(TR);
   return convertChild(TI, Index);
@@ -242,7 +316,7 @@
 swift_typeinfo_t
 swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
                                  uintptr_t Metadata) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto *TI = Context->getMetadataTypeInfo(Metadata);
   return convertTypeInfo(TI);
 }
@@ -251,7 +325,7 @@
 swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
                                  uintptr_t Metadata,
                                  unsigned Index) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto *TI = Context->getMetadataTypeInfo(Metadata);
   return convertChild(TI, Index);
 }
@@ -259,7 +333,7 @@
 swift_typeinfo_t
 swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
                                  uintptr_t Object) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto *TI = Context->getInstanceTypeInfo(Object);
   return convertTypeInfo(TI);
 }
@@ -268,7 +342,7 @@
 swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
                                  uintptr_t Object,
                                  unsigned Index) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto *TI = Context->getInstanceTypeInfo(Object);
   return convertChild(TI, Index);
 }
@@ -278,7 +352,7 @@
                                         swift_typeref_t ExistentialTypeRef,
                                         swift_typeref_t *InstanceTypeRef,
                                         swift_addr_t *StartOfInstanceData) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
   auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
   const TypeRef *InstanceTR = nullptr;
@@ -307,7 +381,7 @@
 
 void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
                                          swift_typeref_t OpaqueTypeRef) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
   auto TI = Context->getTypeInfo(TR);
   if (TI == nullptr) {
@@ -319,7 +393,7 @@
 
 void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
                                           uintptr_t Metadata) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TI = Context->getMetadataTypeInfo(Metadata);
   if (TI == nullptr) {
     std::cout << "<null type info>\n";
@@ -330,7 +404,7 @@
 
 void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
                                           uintptr_t Object) {
-  auto Context = reinterpret_cast<NativeReflectionContext *>(ContextRef);
+  auto Context = ContextRef->nativeContext;
   auto TI = Context->getInstanceTypeInfo(Object);
   if (TI == nullptr) {
     std::cout << "<null type info>\n";
diff --git a/tools/swift-reflection-dump/swift-reflection-dump.cpp b/tools/swift-reflection-dump/swift-reflection-dump.cpp
index e80b8fe..c88912d 100644
--- a/tools/swift-reflection-dump/swift-reflection-dump.cpp
+++ b/tools/swift-reflection-dump/swift-reflection-dump.cpp
@@ -13,6 +13,10 @@
 // binaries.
 //===----------------------------------------------------------------------===//
 
+// FIXME davidino: this needs to be included first to avoid textual
+// replacement. It's silly and needs to be fixed.
+#include "llvm/Object/MachO.h"
+
 #include "swift/ABI/MetadataValues.h"
 #include "swift/Demangling/Demangle.h"
 #include "swift/Basic/LLVMInitialize.h"
@@ -20,7 +24,6 @@
 #include "swift/Reflection/TypeRef.h"
 #include "swift/Reflection/TypeRefBuilder.h"
 #include "llvm/Object/Archive.h"
-#include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Object/ELFObjectFile.h"
@@ -191,15 +194,12 @@
     return false;
   }
   
-  bool readBytes(RemoteAddress address, uint8_t *dest,
-                 uint64_t size) override {
+  ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
     if (!isAddressValid(address, size))
-      return false;
+      return ReadBytesResult(nullptr, [](const void *){});
 
     // TODO: Account for offset in ELF binaries
-    auto src = (const void *)address.getAddressData();
-    memcpy(dest, (const void*)src, size);
-    return true;
+    return ReadBytesResult((const void *)address.getAddressData(), [](const void *) {});
   }
   
   bool readString(RemoteAddress address, std::string &dest) override {
@@ -246,12 +246,12 @@
       objectFile = objectOwner.get();
     }
 
-    context.addReflectionInfo(findReflectionInfo(objectFile));
-
     // Retain the objects that own section memory
     binaryOwners.push_back(std::move(binaryOwner));
     objectOwners.push_back(std::move(objectOwner));
     objectFiles.push_back(objectFile);
+
+    context.addReflectionInfo(findReflectionInfo(objectFile));
   }
 
   switch (action) {
diff --git a/tools/swift-reflection-test/messages.h b/tools/swift-reflection-test/messages.h
index 436c86b..ef61b97 100644
--- a/tools/swift-reflection-test/messages.h
+++ b/tools/swift-reflection-test/messages.h
@@ -13,6 +13,7 @@
 static const char *REQUEST_INSTANCE_KIND = "k\n";
 static const char *REQUEST_INSTANCE_ADDRESS = "i\n";
 static const char *REQUEST_REFLECTION_INFO = "r\n";
+static const char *REQUEST_IMAGES = "m\n";
 static const char *REQUEST_READ_BYTES = "b\n";
 static const char *REQUEST_SYMBOL_ADDRESS = "s\n";
 static const char *REQUEST_STRING_LENGTH = "l\n";
diff --git a/tools/swift-reflection-test/swift-reflection-test.c b/tools/swift-reflection-test/swift-reflection-test.c
index 283919a..e0652f3 100644
--- a/tools/swift-reflection-test/swift-reflection-test.c
+++ b/tools/swift-reflection-test/swift-reflection-test.c
@@ -29,17 +29,17 @@
 #include <string.h>
 #include <unistd.h>
 
+typedef struct PipeMemoryReader {
+  int to_child[2];
+  int from_child[2];
+} PipeMemoryReader;
+
 typedef struct RemoteSection {
   uintptr_t StartAddress;
   uintptr_t Size;
   uintptr_t EndAddress;
 } RemoteSection;
 
-typedef struct PipeMemoryReader {
-  int to_child[2];
-  int from_child[2];
-} PipeMemoryReader;
-
 typedef struct RemoteReflectionInfo {
   RemoteSection fieldmd;
   RemoteSection assocty;
@@ -161,11 +161,6 @@
 }
 
 static
-uint8_t PipeMemoryReader_getSizeSize(void *Context) {
-  return sizeof(size_t);
-}
-
-static
 void PipeMemoryReader_collectBytesFromPipe(const PipeMemoryReader *Reader,
                                            void *Dest, size_t Size) {
   int ReadFD = PipeMemoryReader_getParentReadFD(Reader);
@@ -183,9 +178,15 @@
   }
 }
 
+static void PipeMemoryReader_freeBytes(void *reader_context, const void *bytes,
+                                       void *context) {
+  free((void *)bytes);
+}
+
 static
-int PipeMemoryReader_readBytes(void *Context, swift_addr_t Address, void *Dest,
-                               uint64_t Size) {
+const void *PipeMemoryReader_readBytes(void *Context, swift_addr_t Address,
+                                       uint64_t Size,
+                                       void **outFreeContext) {
   const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context;
   uintptr_t TargetAddress = Address;
   size_t TargetSize = (size_t)Size;
@@ -193,8 +194,13 @@
   write(WriteFD, REQUEST_READ_BYTES, 2);
   write(WriteFD, &TargetAddress, sizeof(TargetAddress));
   write(WriteFD, &TargetSize, sizeof(size_t));
-  PipeMemoryReader_collectBytesFromPipe(Reader, Dest, Size);
-  return 1;
+  
+  void *Buf = malloc(Size);
+  PipeMemoryReader_collectBytesFromPipe(Reader, Buf, Size);
+  
+  *outFreeContext = NULL;
+  
+  return Buf;
 }
 
 static
@@ -259,6 +265,32 @@
   return RS;
 }
 
+#if defined(__APPLE__) && defined(__MACH__)
+static void
+PipeMemoryReader_receiveImages(SwiftReflectionContextRef RC,
+                                       const PipeMemoryReader *Reader) {
+  int WriteFD = PipeMemoryReader_getParentWriteFD(Reader);
+  write(WriteFD, REQUEST_IMAGES, 2);
+  size_t NumReflectionInfos;
+  PipeMemoryReader_collectBytesFromPipe(Reader, &NumReflectionInfos,
+                                        sizeof(NumReflectionInfos));
+
+  if (NumReflectionInfos == 0)
+    return;
+  
+  struct { uintptr_t Start, Size; } *Images;
+  Images = calloc(NumReflectionInfos, sizeof(*Images));
+  PipeMemoryReader_collectBytesFromPipe(Reader, Images,
+                                        NumReflectionInfos * sizeof(*Images));
+  
+  for (size_t i = 0; i < NumReflectionInfos; ++i) {
+    swift_reflection_addImage(RC, Images[i].Start);
+  }
+  
+  free(Images);
+}
+#endif
+
 static void
 PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC,
                                        const PipeMemoryReader *Reader) {
@@ -408,8 +440,8 @@
       close(PipeMemoryReader_getChildWriteFD(&Pipe));
       SwiftReflectionContextRef RC = swift_reflection_createReflectionContext(
         (void*)&Pipe,
-        PipeMemoryReader_getPointerSize,
-        PipeMemoryReader_getSizeSize,
+        sizeof(void *),
+        PipeMemoryReader_freeBytes,
         PipeMemoryReader_readBytes,
         PipeMemoryReader_getStringLength,
         PipeMemoryReader_getSymbolAddress);
@@ -418,7 +450,11 @@
       if (PointerSize != sizeof(uintptr_t))
         errorAndExit("Child process had unexpected architecture");
 
+#if defined(__APPLE__) && defined(__MACH__)
+      PipeMemoryReader_receiveImages(RC, &Pipe);
+#else
       PipeMemoryReader_receiveReflectionInfo(RC, &Pipe);
+#endif
 
       while (1) {
         InstanceKind Kind = PipeMemoryReader_receiveInstanceKind(&Pipe);
diff --git a/unittests/Reflection/RemoteMirrorInterop/test.m b/unittests/Reflection/RemoteMirrorInterop/test.m
new file mode 100644
index 0000000..22bcb95
--- /dev/null
+++ b/unittests/Reflection/RemoteMirrorInterop/test.m
@@ -0,0 +1,131 @@
+//===--- test.m - SwiftRemoteMirrorLegacyInterop test program. ------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 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 is a test program that exercises the SwiftRemoteMirrorLegacyInterop header.
+///
+//===----------------------------------------------------------------------------===//
+
+#import <dlfcn.h>
+#import <Foundation/Foundation.h>
+#import <mach/mach.h>
+#import <mach-o/dyld.h>
+
+#import "SwiftRemoteMirrorLegacyInterop.h"
+
+
+void *Load(char *path) {
+  void *Handle = dlopen(path, RTLD_LAZY);
+  if (Handle == NULL) {
+    fprintf(stderr, "loading %s: %s\n", path, dlerror());
+    exit(1);
+  }
+  return Handle;
+}
+
+void Free(void *reader_context, const void *bytes, void *context) {
+  assert(reader_context == (void *)0xdeadbeef);
+  assert(context == (void *)0xfeedface);
+  free((void *)bytes);
+}
+
+const void *ReadBytes(void *context, swift_addr_t address, uint64_t size,
+                      void **outFreeContext) {
+  assert(context == (void *)0xdeadbeef);
+  *outFreeContext = (void *)0xfeedface;
+
+  void *Buffer = malloc(size);
+  vm_size_t InOutSize = size;
+  kern_return_t result = vm_read_overwrite(mach_task_self(), address, size, (vm_address_t)Buffer, &InOutSize);
+  if (result != KERN_SUCCESS) abort();
+  if (InOutSize != size) abort();
+  return Buffer;
+}
+
+uint64_t GetStringLength(void *context, swift_addr_t address) {
+  assert(context == (void *)0xdeadbeef);
+  return strlen((char *)address);
+}
+
+swift_addr_t GetSymbolAddress(void *context, const char *name, uint64_t name_length) {
+  assert(context == (void *)0xdeadbeef);
+  return (swift_addr_t)dlsym(RTLD_DEFAULT, name);
+}
+
+int main(int argc, char **argv) {
+  if (argc != 4) {
+    fprintf(stderr, "usage: %s <libtestswift.dylib> <libswiftRemoteMirror4.dylib> "
+                    "<libswiftRemoteMirror5.dylib>\n",
+                    argv[0]);
+    exit(1);
+  }
+  
+  char *TestLibPath = argv[1];
+  char *Mirror4Path = argv[2];
+  char *Mirror5Path = argv[3];
+  
+  void *TestHandle = Load(TestLibPath);
+  intptr_t (*Test)(void) = dlsym(TestHandle, "test");
+  
+  uintptr_t Obj = Test();
+  
+  void *Mirror4Handle = Mirror4Path[0] == '-' ? NULL : Load(Mirror4Path);
+  void *Mirror5Handle = Mirror5Path[0] == '-' ? NULL : Load(Mirror5Path);
+  SwiftReflectionInteropContextRef Context =
+    swift_reflection_interop_createReflectionContext(
+      (void *)0xdeadbeef,
+      Mirror5Handle,
+      Mirror4Handle,
+      sizeof(void *),
+      Free,
+      ReadBytes,
+      GetStringLength,
+      GetSymbolAddress);
+  if (Context == NULL) {
+    fprintf(stderr, "Unable to create a reflection context!\n");
+    exit(1);
+  }
+  
+  uint32_t ImageCount = _dyld_image_count();
+  for (uint32_t i = 0; i < ImageCount; i++) {
+    swift_addr_t Image = (swift_addr_t)_dyld_get_image_header(i);
+    swift_reflection_interop_addImage(Context, Image);
+  }
+  
+  swift_typeref_interop_t Type = swift_reflection_interop_typeRefForInstance(Context, Obj);
+  if (Type.Typeref != 0) {
+    swift_typeinfo_t TypeInfo = swift_reflection_interop_infoForTypeRef(Context, Type);
+    printf("Kind:%u Size:%u Alignment:%u Stride:%u NumFields:%u\n",
+           TypeInfo.Kind, TypeInfo.Size, TypeInfo.Alignment, TypeInfo.Stride,
+           TypeInfo.NumFields);
+  } else {
+    printf("Unknown typeref!\n");
+  }
+  
+  swift_typeinfo_t TypeInfo = swift_reflection_interop_infoForInstance(Context, Obj);
+  if (TypeInfo.Kind != SWIFT_UNKNOWN) {
+    printf("Kind:%u Size:%u Alignment:%u Stride:%u NumFields:%u\n",
+           TypeInfo.Kind, TypeInfo.Size, TypeInfo.Alignment, TypeInfo.Stride,
+           TypeInfo.NumFields);
+  
+    for (unsigned i = 0; i < TypeInfo.NumFields; ++i) {
+      swift_childinfo_t ChildInfo = swift_reflection_interop_childOfInstance(
+        Context, Obj, i);
+      printf("  [%u]: %s Offset:%u Kind:%u\n", i,
+             ChildInfo.Name, ChildInfo.Offset, ChildInfo.Kind);
+    }
+  } else {
+    printf("Unknown typeinfo!\n");
+  }
+  
+  swift_reflection_interop_destroyReflectionContext(Context);
+}
diff --git a/unittests/Reflection/RemoteMirrorInterop/test.sh b/unittests/Reflection/RemoteMirrorInterop/test.sh
new file mode 100755
index 0000000..849a9e2
--- /dev/null
+++ b/unittests/Reflection/RemoteMirrorInterop/test.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# Exercise the SwiftRemoteMirrorLegacyInterop API. This requires a build
+# of an old (circa 4.0.3) version of Swift as well as the current one.
+# It then builds Swift code using the old and new compilers, and
+# exercises the Interop API using the old and new remote mirrors
+# libraries.
+
+set -euo pipefail
+
+if [[ $# -ne 4 ]]; then
+  echo -n "Usage: $0 <swiftc4-path> <swiftc5-path> "
+  echo "<libswiftRemoteMirror4.dylib> <libswiftRemoteMirror5.dylib>"
+  exit 1
+fi
+
+swiftc4="$1"
+swiftc5="$2"
+mirrorlib4="$3"
+mirrorlib5="$4"
+
+SDK=`xcrun --show-sdk-path`
+
+cd `dirname $0`
+
+"$swiftc4" -sdk "$SDK" -emit-library test4.swift -o /tmp/libtest4.dylib
+"$swiftc5" -sdk "$SDK" -emit-library test5.swift -o /tmp/libtest5.dylib
+
+clang -framework Foundation -I ../../../include/swift/SwiftRemoteMirror \
+      -o /tmp/test -g test.m 
+
+
+echo "Testing 4 with both mirror libs"
+/tmp/test /tmp/libtest4.dylib "$mirrorlib4" "$mirrorlib5"
+echo ""
+
+echo "Testing 4 with only mirror lib 5"
+/tmp/test /tmp/libtest4.dylib "-" "$mirrorlib5"
+echo ""
+
+echo "Testing 4 with only mirror lib 4"
+/tmp/test /tmp/libtest4.dylib "$mirrorlib4" "-"
+echo ""
+
+echo "Testing 4 with no mirror libs"
+/tmp/test /tmp/libtest4.dylib "-" "-" || true
+echo ""
+
+echo "Testing 5 with both mirror libs"
+/tmp/test /tmp/libtest5.dylib "$mirrorlib4" "$mirrorlib5"
+echo ""
+
+echo "Testing 5 with only mirror lib 5"
+/tmp/test /tmp/libtest5.dylib "-" "$mirrorlib5"
+echo ""
+
+# Not supported (yet?)
+#echo "Testing 5 with only mirror lib 4"
+#/tmp/test /tmp/libtest5.dylib "$mirrorlib4" "-"
+#echo ""
+
+echo "Testing 5 with no mirror libs"
+/tmp/test /tmp/libtest5.dylib "-" "-" || true
diff --git a/unittests/Reflection/RemoteMirrorInterop/test4.swift b/unittests/Reflection/RemoteMirrorInterop/test4.swift
new file mode 100644
index 0000000..da7959c
--- /dev/null
+++ b/unittests/Reflection/RemoteMirrorInterop/test4.swift
@@ -0,0 +1,11 @@
+@_cdecl("test")
+public func test() -> UInt {
+  return unsafeBitCast(c, to: UInt.self)
+}
+
+class C {
+  let x = "123"
+  let y = 456
+}
+
+let c = C()
diff --git a/unittests/Reflection/RemoteMirrorInterop/test5.swift b/unittests/Reflection/RemoteMirrorInterop/test5.swift
new file mode 100644
index 0000000..da7959c
--- /dev/null
+++ b/unittests/Reflection/RemoteMirrorInterop/test5.swift
@@ -0,0 +1,11 @@
+@_cdecl("test")
+public func test() -> UInt {
+  return unsafeBitCast(c, to: UInt.self)
+}
+
+class C {
+  let x = "123"
+  let y = 456
+}
+
+let c = C()