Loading...
common/SwiftVisitor.cpp /dev/null dyld-1122.1
--- /dev/null
+++ dyld/dyld-1122.1/common/SwiftVisitor.cpp
@@ -0,0 +1,379 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) 2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <TargetConditionals.h>
+
+#if !TARGET_OS_EXCLAVEKIT
+
+#include "SwiftVisitor.h"
+
+#if SUPPORT_VM_LAYOUT
+#include "MachOAnalyzer.h"
+#endif
+
+#include <assert.h>
+
+using namespace metadata_visitor;
+
+//
+// MARK: --- SwiftVisitor methods ---
+//
+
+void SwiftVisitor::forEachProtocolConformance(void (^callback)(const SwiftConformance& swiftConformance,
+                                                               bool& stopConformance)) const
+{
+    SwiftConformanceList swiftConformanceList = this->getSwiftConformances();
+
+    for ( uint32_t i = 0, e = swiftConformanceList.numConformances(); i != e; ++i ) {
+        SwiftConformance swiftConformance = swiftConformanceList.getConformance(*this, i);
+
+        bool stop = false;
+        callback(swiftConformance, stop);
+        if ( stop )
+            break;
+    }
+}
+
+SwiftConformanceList SwiftVisitor::getSwiftConformances() const
+{
+    std::optional<SectionContent> protoListSection = findTextSection("__swift5_proto");
+    if ( !protoListSection.has_value() )
+        return SwiftConformanceList(std::nullopt, 0);
+
+    assert((protoListSection->sectSize % 4) == 0);
+    uint64_t numElements = protoListSection->sectSize / 4;
+    const ResolvedValue& sectionValue = protoListSection->sectionBase;
+    return SwiftConformanceList(sectionValue, (uint32_t)numElements);
+}
+
+std::optional<SwiftVisitor::SectionContent> SwiftVisitor::findTextSection(const char *sectionName) const
+{
+#if SUPPORT_VM_LAYOUT
+    const dyld3::MachOFile* mf = this->dylibMA;
+#else
+    const dyld3::MachOFile* mf = this->dylibMF;
+#endif
+
+    __block std::optional<SwiftVisitor::SectionContent> sectionContent;
+    mf->forEachSection(^(const dyld3::MachOFile::SectionInfo& sectInfo, bool malformedSectionRange, bool& stop) {
+        if ( (strcmp(sectInfo.segInfo.segName, "__TEXT") != 0) )
+            return;
+        if ( strcmp(sectInfo.sectName, sectionName) != 0 )
+            return;
+
+#if SUPPORT_VM_LAYOUT
+        const void* targetValue = (const void*)(sectInfo.sectAddr + this->dylibMA->getSlide());
+        ResolvedValue target(targetValue, VMAddress(sectInfo.sectAddr));
+#else
+        VMOffset offsetInSegment(sectInfo.sectAddr - sectInfo.segInfo.vmAddr);
+        ResolvedValue target(this->segments[sectInfo.segInfo.segIndex], offsetInSegment);
+#endif
+        sectionContent.emplace(std::move(target));
+        sectionContent->sectSize       = sectInfo.sectSize;
+
+        stop = true;
+    });
+    return sectionContent;
+}
+
+//
+// MARK: --- SwiftConformanceList methods ---
+//
+
+SwiftConformance SwiftConformanceList::getConformance(const Visitor &swiftVisitor, uint32_t i) const
+{
+    // Protocol conformances are a 32-bit offset from the list entry
+    const uint8_t* fieldPos = (const uint8_t*)this->conformanceListPos->value() + (i * sizeof(int32_t));
+
+    int64_t relativeOffsetFromField = (int64_t)*(int32_t*)fieldPos;
+    VMOffset relativeOffsetFromList((uint64_t)relativeOffsetFromField + (i * 4));
+
+    VMAddress listVMAddr = this->conformanceListPos->vmAddress();
+    VMAddress conformanceVMAddr = listVMAddr + relativeOffsetFromList;
+
+    ResolvedValue conformanceValue = swiftVisitor.getValueFor(conformanceVMAddr);
+    return SwiftConformance(conformanceValue);
+}
+
+uint32_t SwiftConformanceList::numConformances() const
+{
+    return this->numElements;
+}
+
+//
+// MARK: --- SwiftConformance methods ---
+//
+
+std::optional<VMAddress> SwiftConformance::getProtocolVMAddr(const SwiftVisitor& swiftVisitor) const
+{
+    const conformance_t* rawConformance = (const conformance_t*)this->getLocation();
+
+    // The protocol is found via the relative pointer
+    const relative_pointer_t* relativePtr = &rawConformance->protocolRelativePointer;
+    ResolvedValue relativePtrField = swiftVisitor.getField(this->conformancePos, relativePtr);
+    return SwiftRelativePointer(relativePtrField).getTargetVMAddr(swiftVisitor);
+}
+
+SwiftPointer SwiftConformance::getProtocolPointer(const SwiftVisitor& swiftVisitor) const
+{
+    const conformance_t* rawConformance = (const conformance_t*)this->getLocation();
+
+    // The protocol is found via the relative pointer
+    const relative_pointer_t* relativePtr = &rawConformance->protocolRelativePointer;
+    ResolvedValue relativePtrField = swiftVisitor.getField(this->conformancePos, relativePtr);
+    return SwiftRelativePointer(relativePtrField).getTargetPointer(swiftVisitor);
+}
+
+SwiftConformance::SwiftProtocolConformanceFlags
+SwiftConformance::getProtocolConformanceFlags(const SwiftVisitor& swiftVisitor) const
+{
+    const conformance_t* rawConformance = (const conformance_t*)this->getLocation();
+
+    const protocol_conformance_flags_t* flagsPtr = &rawConformance->flags;
+    ResolvedValue flagsField = swiftVisitor.getField(this->conformancePos, flagsPtr);
+    return SwiftProtocolConformanceFlags(flagsField);
+}
+
+SwiftConformance::SwiftTypeRefPointer
+SwiftConformance::getTypeRef(const SwiftVisitor& swiftVisitor) const
+{
+    const conformance_t* rawConformance = (const conformance_t*)this->getLocation();
+
+    // The typeref is found via the relative pointer
+    const typeref_pointer_t* relativePtr = &rawConformance->typeRef;
+    ResolvedValue relativePtrField = swiftVisitor.getField(this->conformancePos, relativePtr);
+
+    auto kind = getProtocolConformanceFlags(swiftVisitor).typeReferenceKind();
+    return SwiftTypeRefPointer(relativePtrField, kind);
+}
+
+bool SwiftConformance::isNull() const
+{
+    const conformance_t* rawConformance = (const conformance_t*)this->getLocation();
+    uint8_t emptyConformance[sizeof(conformance_t)] = { 0 };
+    return memcmp(rawConformance, emptyConformance, sizeof(conformance_t)) == 0;
+}
+
+VMAddress SwiftConformance::getVMAddress() const
+{
+    return this->conformancePos.vmAddress();
+}
+
+const void* SwiftConformance::getLocation() const
+{
+    return this->conformancePos.value();
+}
+
+//
+// MARK: --- SwiftConformance::SwiftRelativePointer methods ---
+//
+
+std::optional<VMAddress> SwiftConformance::SwiftRelativePointer::getTargetVMAddr(const SwiftVisitor &swiftVisitor) const
+{
+    const relative_pointer_t* relativePtr = (const relative_pointer_t*)this->pos.value();
+    int32_t relativeOffset = relativePtr->relativeOffset;
+    if ( (relativeOffset & 0x1) == 0 ) {
+        // Relative offset directly to the target value
+        int64_t offset64 = (int64_t)relativeOffset;
+        VMAddress targetVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+        return targetVMAddr;
+    } else {
+        // Relative offset to a pointer.  The pointer contains the target value
+        int32_t offset = relativeOffset & ~0x1ULL;
+        int64_t offset64 = (int64_t)offset;
+        VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+        ResolvedValue pointerValue = swiftVisitor.getValueFor(pointerVMAddr);
+
+        // Dereference the pointer to get the final target
+        return swiftVisitor.resolveOptionalRebaseToVMAddress(pointerValue);
+    }
+}
+
+SwiftPointer SwiftConformance::SwiftRelativePointer::getTargetPointer(const SwiftVisitor &swiftVisitor) const
+{
+    const relative_pointer_t* relativePtr = (const relative_pointer_t*)this->pos.value();
+    int32_t relativeOffset = relativePtr->relativeOffset;
+    if ( (relativeOffset & 0x1) == 0 ) {
+        // Relative offset directly to the target value
+        int64_t offset64 = (int64_t)relativeOffset;
+        VMAddress targetVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+        return { true, swiftVisitor.getValueFor(targetVMAddr) };
+    } else {
+        // Relative offset to a pointer.  The pointer contains the target value
+        int32_t offset = relativeOffset & ~0x1ULL;
+        int64_t offset64 = (int64_t)offset;
+        VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+        return { false, swiftVisitor.getValueFor(pointerVMAddr) };
+    }
+}
+
+//
+// MARK: --- SwiftConformance::SwiftProtocolConformanceFlags methods ---
+//
+
+SwiftConformance::SwiftProtocolConformanceFlags::TypeReferenceKind
+SwiftConformance::SwiftProtocolConformanceFlags::typeReferenceKind() const
+{
+    const protocol_conformance_flags_t* flagsPtr = (const protocol_conformance_flags_t*)this->pos.value();
+    uint32_t flags = flagsPtr->flags;
+    return (TypeReferenceKind)((flags & (uint32_t)TypeMetadataKind::mask) >> (uint32_t)TypeMetadataKind::shift);
+}
+
+//
+// MARK: --- SwiftConformance::SwiftProtocolConformanceFlags methods ---
+//
+
+std::optional<ResolvedValue>
+SwiftConformance::SwiftTypeRefPointer::getTypeDescriptor(const SwiftVisitor &swiftVisitor) const
+{
+    assert((this->kind == SwiftProtocolConformanceFlags::TypeReferenceKind::directTypeDescriptor)
+           || (this->kind == SwiftProtocolConformanceFlags::TypeReferenceKind::indirectTypeDescriptor));
+
+    if ( this->kind == SwiftProtocolConformanceFlags::TypeReferenceKind::directTypeDescriptor ) {
+        // Relative offset directly to the target value
+        int32_t relativeOffset = *(int32_t*)this->pos.value();
+        int64_t offset64 = (int64_t)relativeOffset;
+        VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+
+        return swiftVisitor.getValueFor(pointerVMAddr);
+    }
+
+    if ( this->kind == SwiftProtocolConformanceFlags::TypeReferenceKind::indirectTypeDescriptor ) {
+        // Relative offset to a pointer.  The pointer contains the target value
+        int32_t relativeOffset = *(int32_t*)this->pos.value();
+        int32_t offset = relativeOffset & ~0x1ULL;
+        int64_t offset64 = (int64_t)offset;
+        VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+        ResolvedValue pointerValue = swiftVisitor.getValueFor(pointerVMAddr);
+
+        // Dereference the pointer to get the final target
+        return swiftVisitor.resolveOptionalRebase(pointerValue);
+    }
+    return { };
+}
+
+const char*
+SwiftConformance::SwiftTypeRefPointer::getClassName(const SwiftVisitor &swiftVisitor) const
+{
+    assert(this->kind == SwiftProtocolConformanceFlags::TypeReferenceKind::directObjCClassName);
+
+    // Relative offset directly to the class name string
+    int32_t relativeOffset = *(int32_t*)this->pos.value();
+    int64_t offset64 = (int64_t)relativeOffset;
+    VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+
+    ResolvedValue pointerValue = swiftVisitor.getValueFor(pointerVMAddr);
+    return (const char*)pointerValue.value();
+}
+
+std::optional<ResolvedValue>
+SwiftConformance::SwiftTypeRefPointer::getClass(const SwiftVisitor &swiftVisitor) const
+{
+    assert(this->kind == SwiftProtocolConformanceFlags::TypeReferenceKind::indirectObjCClass);
+
+    // Relative offset to a pointer.  The pointer contains the target value
+    int32_t relativeOffset = *(int32_t*)this->pos.value();
+    int32_t offset = relativeOffset & ~0x1ULL;
+    int64_t offset64 = (int64_t)offset;
+    VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+    ResolvedValue pointerValue = swiftVisitor.getValueFor(pointerVMAddr);
+
+    // Dereference the pointer to get the final target
+    return swiftVisitor.resolveOptionalRebase(pointerValue);
+}
+
+SwiftPointer SwiftConformance::SwiftTypeRefPointer::getTargetPointer(const SwiftVisitor &swiftVisitor) const
+{
+    switch ( this->kind ) {
+        case SwiftProtocolConformanceFlags::TypeReferenceKind::directTypeDescriptor: {
+            // Relative offset directly to the target value
+            int32_t relativeOffset = *(int32_t*)this->pos.value();
+            int64_t offset64 = (int64_t)relativeOffset;
+            VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+            return { true, swiftVisitor.getValueFor(pointerVMAddr) };
+        }
+        case SwiftProtocolConformanceFlags::TypeReferenceKind::indirectTypeDescriptor: {
+            // Relative offset to a pointer.  The pointer contains the target value
+            int32_t relativeOffset = *(int32_t*)this->pos.value();
+            int32_t offset = relativeOffset & ~0x1ULL;
+            int64_t offset64 = (int64_t)offset;
+            VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+            return { false, swiftVisitor.getValueFor(pointerVMAddr) };
+        }
+        case SwiftProtocolConformanceFlags::TypeReferenceKind::directObjCClassName: {
+            // Relative offset directly to the class name string
+            int32_t relativeOffset = *(int32_t*)this->pos.value();
+            int64_t offset64 = (int64_t)relativeOffset;
+            VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+            return { true, swiftVisitor.getValueFor(pointerVMAddr) };
+        }
+        case SwiftProtocolConformanceFlags::TypeReferenceKind::indirectObjCClass: {
+            // Relative offset to a pointer.  The pointer contains the target value
+            int32_t relativeOffset = *(int32_t*)this->pos.value();
+            int32_t offset = relativeOffset & ~0x1ULL;
+            int64_t offset64 = (int64_t)offset;
+            VMAddress pointerVMAddr = this->pos.vmAddress() + VMOffset((uint64_t)offset64);
+            return { false, swiftVisitor.getValueFor(pointerVMAddr) };
+        }
+    }
+}
+
+//
+// MARK: --- SwiftConformance::TypeContextDescriptor methods ---
+//
+
+// The most significant two bytes of the flags word, which can have
+// kind-specific meaning.
+uint16_t SwiftConformance::TypeContextDescriptor::getKindSpecificFlags() const {
+    const type_context_descriptor_t* context = (type_context_descriptor_t*)this->pos.value();
+    return (context->flags >> 16u) & 0xFFFFu;
+}
+
+bool SwiftConformance::TypeContextDescriptor::isForeignMetadata() const
+{
+    // The botton 2 bits have the flags
+    return (this->getKindSpecificFlags() & 0x3) == ForeignMetadataInitialization;
+}
+
+bool SwiftConformance::TypeContextDescriptor::hasImportInfo() const
+{
+    // Bit 2 tells us if we have import info, ie, a name containing NULLs
+    return (this->getKindSpecificFlags() & (1 << 2)) != 0;
+}
+
+ResolvedValue SwiftConformance::TypeContextDescriptor::getName(const SwiftVisitor& swiftVisitor) const
+{
+    // The name is found via a relative offset
+    const type_context_descriptor_t* context = (type_context_descriptor_t*)this->pos.value();
+    ResolvedValue nameField = swiftVisitor.getField(this->pos, &context->name.relativeOffset);
+
+    // Add the offset to the field to get the target value
+    int32_t nameOffset = *(int32_t*)nameField.value();
+    int64_t nameOffset64 = (int64_t)nameOffset;
+    VMOffset offsetFromNameField((uint64_t)nameOffset64);
+    VMAddress targetVMAddr = nameField.vmAddress() + offsetFromNameField;
+    return swiftVisitor.getValueFor(targetVMAddr);
+}
+
+#endif // !TARGET_OS_EXCLAVEKIT