//===--- swift-reflection-dump.cpp - Reflection testing application -------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// This is a host-side tool to dump remote reflection sections in swift
// binaries.
//===----------------------------------------------------------------------===//

#include "swift/ABI/MetadataValues.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeRef.h"
#include "swift/Reflection/TypeRefBuilder.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/RelocationResolver.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"

#if defined(_WIN32)
#include <io.h>
#else
#include <unistd.h>
#endif

#if defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#endif

#include <algorithm>
#include <csignal>

using llvm::ArrayRef;
using llvm::dyn_cast;
using llvm::StringRef;
using namespace llvm::object;

using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;
using namespace Demangle;

enum class ActionType { DumpReflectionSections, DumpTypeLowering };

namespace options {
static llvm::cl::opt<ActionType> Action(
    llvm::cl::desc("Mode:"),
    llvm::cl::values(
        clEnumValN(ActionType::DumpReflectionSections,
                   "dump-reflection-sections",
                   "Dump the field reflection section"),
        clEnumValN(
            ActionType::DumpTypeLowering, "dump-type-lowering",
            "Dump the field layout for typeref strings read from stdin")),
    llvm::cl::init(ActionType::DumpReflectionSections));

static llvm::cl::list<std::string>
    BinaryFilename("binary-filename",
                   llvm::cl::desc("Filenames of the binary files"),
                   llvm::cl::OneOrMore);

static llvm::cl::opt<std::string>
    Architecture("arch",
                 llvm::cl::desc("Architecture to inspect in the binary"),
                 llvm::cl::Required);
} // end namespace options

template <typename T> static T unwrap(llvm::Expected<T> value) {
  if (value)
    return std::move(value.get());
  llvm::errs() << "swift-reflection-test error: " << toString(value.takeError())
               << "\n";
  exit(EXIT_FAILURE);
}

using ReadBytesResult = swift::remote::MemoryReader::ReadBytesResult;

// Since ObjectMemoryReader maintains ownership of the ObjectFiles and their
// raw data, we can vend ReadBytesResults with no-op destructors.
static void no_op_destructor(const void*) {}

class Image {
private:
  struct Segment {
    uint64_t Addr;
    StringRef Contents;
  };
  const ObjectFile *O;
  uint64_t HeaderAddress;
  std::vector<Segment> Segments;
  struct DynamicRelocation {
    StringRef Symbol;
    uint64_t Offset;
  };
  llvm::DenseMap<uint64_t, DynamicRelocation> DynamicRelocations;
  
  void scanMachO(const MachOObjectFile *O) {
    using namespace llvm::MachO;

    HeaderAddress = UINT64_MAX;
    
    // Collect the segment preferred vm mappings.
    for (const auto &Load : O->load_commands()) {
      if (Load.C.cmd == LC_SEGMENT_64) {
        auto Seg = O->getSegment64LoadCommand(Load);
        if (Seg.filesize == 0)
          continue;
        
        auto contents = O->getData().slice(Seg.fileoff,
                                           Seg.fileoff + Seg.filesize);
        
        if (contents.empty() || contents.size() != Seg.filesize)
          continue;
        
        Segments.push_back({Seg.vmaddr, contents});
        HeaderAddress = std::min(HeaderAddress, Seg.vmaddr);
      } else if (Load.C.cmd == LC_SEGMENT) {
        auto Seg = O->getSegmentLoadCommand(Load);
        if (Seg.filesize == 0)
          continue;
        
        auto contents = O->getData().slice(Seg.fileoff,
                                           Seg.fileoff + Seg.filesize);
        
        if (contents.empty() || contents.size() != Seg.filesize)
          continue;
        
        Segments.push_back({Seg.vmaddr, contents});
        HeaderAddress = std::min(HeaderAddress, (uint64_t)Seg.vmaddr);
      }
    }
    
    // Walk through the bindings list to collect all the external references
    // in the image.
    llvm::Error error = llvm::Error::success();
    auto OO = const_cast<MachOObjectFile*>(O);

    for (auto bind : OO->bindTable(error)) {
      if (error) {
        llvm::consumeError(std::move(error));
        break;
      }
      
      // The offset from the symbol is stored at the target address.
      uint64_t Offset;
      auto OffsetContent = getContentsAtAddress(bind.address(),
                                                O->getBytesInAddress());
      if (OffsetContent.empty())
        continue;
      
      if (O->getBytesInAddress() == 8) {
        memcpy(&Offset, OffsetContent.data(), sizeof(Offset));
      } else if (O->getBytesInAddress() == 4) {
        uint32_t OffsetValue;
        memcpy(&OffsetValue, OffsetContent.data(), sizeof(OffsetValue));
        Offset = OffsetValue;
      } else {
        assert(false && "unexpected word size?!");
      }
      
      DynamicRelocations.insert({bind.address(), {bind.symbolName(), Offset}});
    }
    if (error) {
      llvm::consumeError(std::move(error));
    }
  }
  
  template<typename ELFT>
  void scanELFType(const ELFObjectFile<ELFT> *O) {
    using namespace llvm::ELF;

    HeaderAddress = UINT64_MAX;

    auto phdrs = O->getELFFile()->program_headers();
    if (!phdrs) {
      llvm::consumeError(phdrs.takeError());
    }

    for (auto &ph : *phdrs) {
      if (ph.p_filesz == 0)
        continue;
      
      auto contents = O->getData().slice(ph.p_offset,
                                         ph.p_offset + ph.p_filesz);
      if (contents.empty() || contents.size() != ph.p_filesz)
        continue;
      
      Segments.push_back({ph.p_vaddr, contents});
      HeaderAddress = std::min(HeaderAddress, (uint64_t)ph.p_vaddr);
    }
        
    // Collect the dynamic relocations.
    auto resolver = getRelocationResolver(*O);
    auto resolverSupports = resolver.first;
    auto resolve = resolver.second;
    
    if (!resolverSupports || !resolve)
      return;
    
    auto machine = O->getELFFile()->getHeader()->e_machine;
    auto relativeRelocType = getELFRelativeRelocationType(machine);
    
    for (auto &S : static_cast<const ELFObjectFileBase*>(O)
                                             ->dynamic_relocation_sections()) {
      bool isRela = O->getSection(S.getRawDataRefImpl())->sh_type
        == llvm::ELF::SHT_RELA;

      for (const RelocationRef &R : S.relocations()) {
        // `getRelocationResolver` doesn't handle RELATIVE relocations, so we
        // have to do that ourselves.
        if (isRela && R.getType() == relativeRelocType) {
          auto rela = O->getRela(R.getRawDataRefImpl());
          DynamicRelocations.insert({R.getOffset(),
            {{}, HeaderAddress + rela->r_addend}});
          continue;
        }
        
        if (!resolverSupports(R.getType()))
          continue;
        auto symbol = R.getSymbol();
        auto name = symbol->getName();
        if (!name) {
          llvm::consumeError(name.takeError());
          continue;
        }
        uint64_t offset = resolve(R, 0, 0);
        DynamicRelocations.insert({R.getOffset(), {*name, offset}});
      }
    }
  }
  
  void scanELF(const ELFObjectFileBase *O) {
    if (auto le32 = dyn_cast<ELFObjectFile<ELF32LE>>(O)) {
      scanELFType(le32);
    } else if (auto be32 = dyn_cast<ELFObjectFile<ELF32BE>>(O)) {
      scanELFType(be32);
    } else if (auto le64 = dyn_cast<ELFObjectFile<ELF64LE>>(O)) {
      scanELFType(le64);
    } else if (auto be64 = dyn_cast<ELFObjectFile<ELF64BE>>(O)) {
      scanELFType(be64);
    } else {
      return;
    }
    
    // FIXME: ReflectionContext tries to read bits of the ELF structure that
    // aren't normally mapped by a phdr. Until that's fixed,
    // allow access to the whole file 1:1 in address space that isn't otherwise
    // mapped.
    Segments.push_back({HeaderAddress, O->getData()});
  }
  
  void scanCOFF(const COFFObjectFile *O) {
    HeaderAddress = O->getImageBase();
    
    for (auto SectionRef : O->sections()) {
      auto Section = O->getCOFFSection(SectionRef);
      
      if (Section->SizeOfRawData == 0)
        continue;
      
      auto SectionBase = O->getImageBase() + Section->VirtualAddress;
      auto SectionContent =
        O->getData().slice(Section->PointerToRawData,
                           Section->PointerToRawData + Section->SizeOfRawData);
      if (SectionContent.empty()
          || SectionContent.size() != Section->SizeOfRawData)
        continue;
      
      Segments.push_back({SectionBase, SectionContent});
    }
    
    // FIXME: We need to map the header at least, but how much of it does
    // Windows typically map?
    Segments.push_back({HeaderAddress, O->getData()});
  }

  bool isMachOWithPtrAuth() const {
    auto macho = dyn_cast<MachOObjectFile>(O);
    if (!macho)
      return false;

    auto &header = macho->getHeader();

    return header.cputype == llvm::MachO::CPU_TYPE_ARM64
      && header.cpusubtype == llvm::MachO::CPU_SUBTYPE_ARM64E;
  }

public:
  explicit Image(const ObjectFile *O) : O(O) {
    // Unfortunately llvm doesn't provide a uniform interface for iterating
    // loadable segments or dynamic relocations in executable images yet.
    if (auto macho = dyn_cast<MachOObjectFile>(O)) {
      scanMachO(macho);
    } else if (auto elf = dyn_cast<ELFObjectFileBase>(O)) {
      scanELF(elf);
    } else if (auto coff = dyn_cast<COFFObjectFile>(O)) {
      scanCOFF(coff);
    } else {
      fputs("unsupported image format\n", stderr);
      abort();
    }
  }

  const ObjectFile *getObjectFile() const { return O; }
  
  unsigned getBytesInAddress() const {
    return O->getBytesInAddress();
  }
    
  uint64_t getStartAddress() const {
    return HeaderAddress;
  }
  
  uint64_t getEndAddress() const {
    uint64_t max = 0;
    for (auto &Segment : Segments) {
      max = std::max(max, Segment.Addr + Segment.Contents.size());
    }
    return max;
  }

  StringRef getContentsAtAddress(uint64_t Addr, uint64_t Size) const {
    for (auto &Segment : Segments) {
      auto addrInSegment = Segment.Addr <= Addr
        && Addr + Size <= Segment.Addr + Segment.Contents.size();
      
      if (!addrInSegment)
        continue;

      auto offset = Addr - Segment.Addr;
      auto result = Segment.Contents.drop_front(offset);
      return result;
    }
    return {};
  }
  
  RemoteAbsolutePointer
  resolvePointer(uint64_t Addr, uint64_t pointerValue) const {
    auto found = DynamicRelocations.find(Addr);
    RemoteAbsolutePointer result;
    if (found == DynamicRelocations.end())
      // In Mach-O images with ptrauth, the pointer value has an offset from
      // the base address in the low 32 bits, and ptrauth discriminator info
      // in the top 32 bits.
      if (isMachOWithPtrAuth()) {
        result = RemoteAbsolutePointer("",
                                HeaderAddress + (pointerValue & 0xffffffffull));
      } else {
        result = RemoteAbsolutePointer("", pointerValue);
      }
    else
      result = RemoteAbsolutePointer(found->second.Symbol,
                                     found->second.Offset);
    return result;
  }
};

/// MemoryReader that reads from the on-disk representation of an executable
/// or dynamic library image.
///
/// This reader uses a remote addressing scheme where the most significant
/// 16 bits of the address value serve as an index into the array of loaded images,
/// and the low 48 bits correspond to the preferred virtual address mapping of
/// the image.
class ObjectMemoryReader : public MemoryReader {
  struct ImageEntry {
    Image TheImage;
    uint64_t Slide;
  };
  std::vector<ImageEntry> Images;
  
  std::pair<const Image *, uint64_t>
  decodeImageIndexAndAddress(uint64_t Addr) const {
    for (auto &Image : Images) {
      if (Image.TheImage.getStartAddress() + Image.Slide <= Addr
          && Addr < Image.TheImage.getEndAddress() + Image.Slide) {
        return {&Image.TheImage, Addr - Image.Slide};
      }
    }
    return {nullptr, 0};
  }
  
  uint64_t
  encodeImageIndexAndAddress(const Image *image, uint64_t imageAddr) const {
    auto entry = (const ImageEntry*)image;
    return imageAddr + entry->Slide;
  }

  StringRef getContentsAtAddress(uint64_t Addr, uint64_t Size) {
    const Image *image;
    uint64_t imageAddr;
    std::tie(image, imageAddr) = decodeImageIndexAndAddress(Addr);

    if (!image)
      return StringRef();
    
    return image->getContentsAtAddress(imageAddr, Size);
  }
  
public:
  explicit ObjectMemoryReader(
      const std::vector<const ObjectFile *> &ObjectFiles) {
    if (ObjectFiles.empty()) {
      fputs("no object files provided\n", stderr);
      abort();
    }
    unsigned WordSize = 0;
    for (const ObjectFile *O : ObjectFiles) {
      // All the object files we look at should share a word size.
      if (!WordSize) {
        WordSize = O->getBytesInAddress();
      } else if (WordSize != O->getBytesInAddress()) {
        fputs("object files must all be for the same architecture\n", stderr);
        abort();
      }
      Images.push_back({Image(O), 0});
    }
    
    // If there is more than one image loaded, try to fit them into one address
    // space.
    if (Images.size() > 1) {
      uint64_t NextAddrSpace = 0;
      for (auto &Image : Images) {
        Image.Slide = NextAddrSpace - Image.TheImage.getStartAddress();
        NextAddrSpace +=
          Image.TheImage.getEndAddress() - Image.TheImage.getStartAddress();
        NextAddrSpace = (NextAddrSpace + 16383) & ~16383;
      }
      
      if (WordSize < 8 && NextAddrSpace > 0xFFFFFFFFu) {
        fputs("object files did not fit in address space", stderr);
        abort();
      }
    }
  }

  ArrayRef<ImageEntry> getImages() const { return Images; }

  bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
                       void *outBuffer) override {
    auto wordSize = Images.front().TheImage.getBytesInAddress();
    // TODO: The following should be set based on inspecting the image.
    // This code sets it to match the platform this code was compiled for.
#if defined(__APPLE__) && __APPLE__
    auto applePlatform = true;
#else
    auto applePlatform = false;
#endif
#if defined(__APPLE__) && __APPLE__ && ((defined(TARGET_OS_IOS) && TARGET_OS_IOS) || (defined(TARGET_OS_IOS) && TARGET_OS_WATCH) || (defined(TARGET_OS_TV) && TARGET_OS_TV) || defined(__arm64__))
    auto iosDerivedPlatform = true;
#else
    auto iosDerivedPlatform = false;
#endif

    switch (type) {
    case DLQ_GetPointerSize: {
      auto result = static_cast<uint8_t *>(outBuffer);
      *result = wordSize;
      return true;
    }
    case DLQ_GetSizeSize: {
      auto result = static_cast<uint8_t *>(outBuffer);
      *result = wordSize;
      return true;
    }
    case DLQ_GetPtrAuthMask: {
      // We don't try to sign pointers at all in our view of the object
      // mapping.
      if (wordSize == 4) {
        auto result = static_cast<uint32_t *>(outBuffer);
        *result = (uint32_t)~0ull;
        return true;
      } else if (wordSize == 8) {
        auto result = static_cast<uint64_t *>(outBuffer);
        *result = (uint64_t)~0ull;
        return true;
      }
      return false;
    }
    case DLQ_GetObjCReservedLowBits: {
      auto result = static_cast<uint8_t *>(outBuffer);
      if (applePlatform && !iosDerivedPlatform && wordSize == 8) {
        // Obj-C reserves low bit on 64-bit macOS only.
        // Other Apple platforms don't reserve this bit (even when
        // running on x86_64-based simulators).
        *result = 1;
      } else {
        *result = 0;
      }
      return true;
    }
    case DLQ_GetLeastValidPointerValue: {
      auto result = static_cast<uint64_t *>(outBuffer);
      if (applePlatform && wordSize == 8) {
        // Swift reserves the first 4GiB on 64-bit Apple platforms
        *result = 0x100000000;
      } else {
        // Swift reserves the first 4KiB everywhere else
        *result = 0x1000;
      }
      return true;
    }
    }

    return false;
  }
  
  RemoteAddress getImageStartAddress(unsigned i) const {
    assert(i < Images.size());
    
    return RemoteAddress(
           encodeImageIndexAndAddress(&Images[i].TheImage,
                                      Images[i].TheImage.getStartAddress()));
  }

  // TODO: We could consult the dynamic symbol tables of the images to
  // implement this.
  RemoteAddress getSymbolAddress(const std::string &name) override {
    return RemoteAddress(nullptr);
  }

  ReadBytesResult readBytes(RemoteAddress Addr, uint64_t Size) override {
    auto addrValue = Addr.getAddressData();
    auto resultBuffer = getContentsAtAddress(addrValue, Size);
    return ReadBytesResult(resultBuffer.data(), no_op_destructor);
  }

  bool readString(RemoteAddress Addr, std::string &Dest) override {
    auto addrValue = Addr.getAddressData();
    auto resultBuffer = getContentsAtAddress(addrValue, 1);
    if (resultBuffer.empty())
      return false;
    
    // Make sure there's a null terminator somewhere in the contents.
    unsigned i = 0;
    for (unsigned e = resultBuffer.size(); i < e; ++i) {
      if (resultBuffer[i] == 0)
        goto found_terminator;
    }
    return false;
    
  found_terminator:
    Dest.append(resultBuffer.begin(), resultBuffer.begin() + i);
    return true;
  }
  
  RemoteAbsolutePointer resolvePointer(RemoteAddress Addr,
                                       uint64_t pointerValue) override {
    auto addrValue = Addr.getAddressData();
    const Image *image;
    uint64_t imageAddr;
    std::tie(image, imageAddr) =
      decodeImageIndexAndAddress(addrValue);
    
    if (!image)
      return RemoteAbsolutePointer();
    
    auto resolved = image->resolvePointer(imageAddr, pointerValue);
    
    if (resolved && resolved.isResolved()) {
      // Mix in the image index again to produce a remote address pointing into
      // the same image.
      return RemoteAbsolutePointer("", encodeImageIndexAndAddress(image,
                               resolved.getResolvedAddress().getAddressData()));
    }
    // If the pointer is relative to an unresolved relocation, leave it as is.
    return resolved;
  }
};

using ReflectionContextOwner
  = std::unique_ptr<void, void (*)(void*)>;

struct ReflectionContextHolder {
  ReflectionContextOwner Owner;
  TypeRefBuilder &Builder;
  ObjectMemoryReader &Reader;
};

template <typename Runtime>
static ReflectionContextHolder makeReflectionContextForMetadataReader(
    std::shared_ptr<ObjectMemoryReader> reader) {
  using ReflectionContext = ReflectionContext<Runtime>;
  auto context = new ReflectionContext(reader);
  auto &builder = context->getBuilder();
  for (unsigned i = 0, e = reader->getImages().size(); i < e; ++i) {
    context->addImage(reader->getImageStartAddress(i));
  }
  return {ReflectionContextOwner(
              context, [](void *x) { delete (ReflectionContext *)x; }),
          builder, *reader};
}

static ReflectionContextHolder makeReflectionContextForObjectFiles(
    const std::vector<const ObjectFile *> &objectFiles) {
  auto Reader = std::make_shared<ObjectMemoryReader>(objectFiles);

  uint8_t pointerSize;
  Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize,
                          nullptr, &pointerSize);
  
  switch (pointerSize) {
  case 4:
    return makeReflectionContextForMetadataReader<External<RuntimeTarget<4>>>
                                                            (std::move(Reader));
  case 8:
    return makeReflectionContextForMetadataReader<External<RuntimeTarget<8>>>
                                                            (std::move(Reader));
  default:
    fputs("unsupported word size in object file\n", stderr);
    abort();
  }
}

static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
                                    StringRef Arch, ActionType Action,
                                    FILE *file) {
  // Note: binaryOrError and objectOrError own the memory for our ObjectFile;
  // once they go out of scope, we can no longer do anything.
  std::vector<OwningBinary<Binary>> BinaryOwners;
  std::vector<std::unique_ptr<ObjectFile>> ObjectOwners;
  std::vector<const ObjectFile *> ObjectFiles;

  for (const std::string &BinaryFilename : BinaryFilenames) {
    auto BinaryOwner = unwrap(createBinary(BinaryFilename));
    Binary *BinaryFile = BinaryOwner.getBinary();

    // The object file we are doing lookups in -- either the binary itself, or
    // a particular slice of a universal binary.
    std::unique_ptr<ObjectFile> ObjectOwner;
    const ObjectFile *O = dyn_cast<ObjectFile>(BinaryFile);
    if (!O) {
      auto Universal = cast<MachOUniversalBinary>(BinaryFile);
      ObjectOwner = unwrap(Universal->getMachOObjectForArch(Arch));
      O = ObjectOwner.get();
    }

    // Retain the objects that own section memory
    BinaryOwners.push_back(std::move(BinaryOwner));
    ObjectOwners.push_back(std::move(ObjectOwner));
    ObjectFiles.push_back(O);
  }
  
  auto context = makeReflectionContextForObjectFiles(ObjectFiles);
  auto &builder = context.Builder;

  switch (Action) {
  case ActionType::DumpReflectionSections:
    // Dump everything
    builder.dumpAllSections(file);
    break;
  case ActionType::DumpTypeLowering: {
    for (std::string Line; std::getline(std::cin, Line);) {
      if (Line.empty())
        continue;

      if (StringRef(Line).startswith("//"))
        continue;

      Demangle::Demangler Dem;
      auto Demangled = Dem.demangleType(Line);
      auto Result = swift::Demangle::decodeMangledType(builder, Demangled);
      if (Result.isError()) {
        auto *error = Result.getError();
        char *str = error->copyErrorString();
        fprintf(file, "Invalid typeref:%s - %s\n", Line.c_str(), str);
        error->freeErrorString(str);
        continue;
      }
      auto TypeRef = Result.getType();

      TypeRef->dump(file);
      auto *TypeInfo = builder.getTypeConverter().getTypeInfo(TypeRef, nullptr);
      if (TypeInfo == nullptr) {
        fprintf(file, "Invalid lowering\n");
        continue;
      }
      TypeInfo->dump(file);
    }
    break;
  }
  }

  return EXIT_SUCCESS;
}

int main(int argc, char *argv[]) {
  PROGRAM_START(argc, argv);
  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift Reflection Dump\n");
  return doDumpReflectionSections(options::BinaryFilename,
                                  options::Architecture, options::Action,
                                  stdout);
}
