//===--- 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.
//===----------------------------------------------------------------------===//

// 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"
#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeRef.h"
#include "swift/Reflection/TypeRefBuilder.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/CommandLine.h"

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

#include <algorithm>
#include <iostream>
#include <csignal>

using llvm::dyn_cast;
using llvm::StringRef;
using llvm::ArrayRef;
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());
  std::cerr << "swift-reflection-test error: " << toString(value.takeError()) << "\n";
  exit(EXIT_FAILURE);
}

static SectionRef getSectionRef(const ObjectFile *objectFile,
                                ArrayRef<StringRef> anySectionNames) {
  for (auto section : objectFile->sections()) {
    StringRef sectionName;
    section.getName(sectionName);
    for (auto desiredName : anySectionNames) {
      if (sectionName.equals(desiredName)) {
        return section;
      }
    }
  }
  return SectionRef();
}

template <typename Section>
static std::pair<Section, uintptr_t>
findReflectionSection(const ObjectFile *objectFile,
                      ArrayRef<StringRef> anySectionNames) {
  auto sectionRef = getSectionRef(objectFile, anySectionNames);

  if (sectionRef.getObject() == nullptr)
    return {{nullptr, nullptr}, 0};

  StringRef sectionContents;
  sectionRef.getContents(sectionContents);

  uintptr_t Offset = 0;
  if (isa<ELFObjectFileBase>(sectionRef.getObject())) {
    ELFSectionRef S{sectionRef};
    Offset = sectionRef.getAddress() - S.getOffset();
  }

  return {{reinterpret_cast<const void *>(sectionContents.begin()),
           reinterpret_cast<const void *>(sectionContents.end())},
          Offset};
}

static ReflectionInfo findReflectionInfo(const ObjectFile *objectFile) {
  auto fieldSection = findReflectionSection<FieldSection>(
      objectFile, {"__swift4_fieldmd", ".swift4_fieldmd", "swift4_fieldmd"});
  auto associatedTypeSection = findReflectionSection<AssociatedTypeSection>(
      objectFile, {"__swift4_assocty", ".swift4_assocty", "swift4_assocty"});
  auto builtinTypeSection = findReflectionSection<BuiltinTypeSection>(
      objectFile, {"__swift4_builtin", ".swift4_builtin", "swift4_builtin"});
  auto captureSection = findReflectionSection<CaptureSection>(
      objectFile, {"__swift4_capture", ".swift4_capture", "swift4_capture"});
  auto typeRefSection = findReflectionSection<GenericSection>(
      objectFile, {"__swift4_typeref", ".swift4_typeref", "swift4_typeref"});
  auto reflectionStringsSection = findReflectionSection<GenericSection>(
      objectFile, {"__swift4_reflstr", ".swift4_reflstr", "swift4_reflstr"});

  // The entire object file is mapped into this process's memory, so the
  // local/remote mapping is identity.
  auto startAddress = (uintptr_t)objectFile->getData().begin();

  return {
      {fieldSection.first, fieldSection.second},
      {associatedTypeSection.first, associatedTypeSection.second},
      {builtinTypeSection.first, builtinTypeSection.second},
      {captureSection.first, captureSection.second},
      {typeRefSection.first, typeRefSection.second},
      {reflectionStringsSection.first, reflectionStringsSection.second},
      /*LocalStartAddress*/ startAddress,
      /*RemoteStartAddress*/ startAddress,
  };
}

using NativeReflectionContext
  = ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>;

class ObjectMemoryReader : public MemoryReader {
  const std::vector<const ObjectFile *> &ObjectFiles;
public:
  ObjectMemoryReader(const std::vector<const ObjectFile *> &ObjectFiles)
    : ObjectFiles(ObjectFiles)
  {
  }

  bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
                       void *outBuffer) override {
    switch (type) {
      case DLQ_GetPointerSize: {
        auto result = static_cast<uint8_t *>(outBuffer);
        *result = sizeof(void *);
        return true;
      }
      case DLQ_GetSizeSize: {
        auto result = static_cast<uint8_t *>(outBuffer);
        *result = sizeof(size_t);
        return true;
      }
    }

    return false;
  }

  RemoteAddress getSymbolAddress(const std::string &name) override {
    for (auto &object : ObjectFiles) {
      for (auto &symbol : object->symbols()) {
        if (unwrap(symbol.getName()).equals(name)) {
          // TODO: Account for offset in ELF binaries
          return RemoteAddress(unwrap(symbol.getAddress()));
        }
      }
    }
    return RemoteAddress(nullptr);
  }
  
  bool isAddressValid(RemoteAddress addr, uint64_t size) const {
    // TODO: Account for offset in ELF binaries

    auto src = addr.getAddressData();
    
    // Check that the source is in bounds of one of the object files.
    for (auto &object : ObjectFiles) {
      if ((uint64_t)object->getData().bytes_begin() <= src
          && src + size <= (uint64_t)object->getData().bytes_end()) {
        return true;
      }
    }
    return false;
  }
  
  ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
    if (!isAddressValid(address, size))
      return ReadBytesResult(nullptr, [](const void *){});

    // TODO: Account for offset in ELF binaries
    return ReadBytesResult((const void *)address.getAddressData(), [](const void *) {});
  }
  
  bool readString(RemoteAddress address, std::string &dest) override {
    if (!isAddressValid(address, 1))
      return false;
    // TODO: Account for running off the edge of an object, offset in ELF
    // binaries
    auto cString = StringRef((const char*)address.getAddressData());
    dest.append(cString.begin(), cString.end());
    return true;
  }
};

static int doDumpReflectionSections(ArrayRef<std::string> binaryFilenames,
                                    StringRef arch,
                                    ActionType action,
                                    std::ostream &OS) {
  // 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;

  // Construct the ReflectionContext.
  // FIXME: Should pick a Runtime template based on the bitwidth of the target
  // architecture.
  auto reader = std::make_shared<ObjectMemoryReader>(objectFiles);
  NativeReflectionContext context(std::move(reader));

  for (auto 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 *objectFile;

    if (auto o = dyn_cast<ObjectFile>(binaryFile)) {
      objectFile = o;
    } else {
      auto universal = cast<MachOUniversalBinary>(binaryFile);
      objectOwner = unwrap(universal->getObjectForArch(arch));
      objectFile = objectOwner.get();
    }

    // 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) {
  case ActionType::DumpReflectionSections:
    // Dump everything
    context.getBuilder().dumpAllSections(OS);
    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 *typeRef = swift::Demangle::decodeMangledType(context.getBuilder(),
                                                         demangled);
      if (typeRef == nullptr) {
        OS << "Invalid typeref: " << line << "\n";
        continue;
      }

      typeRef->dump(OS);
      auto *typeInfo =
        context.getBuilder().getTypeConverter().getTypeInfo(typeRef);
      if (typeInfo == nullptr) {
        OS << "Invalid lowering\n";
        continue;
      }
      typeInfo->dump(OS);
    }
    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,
                                  std::cout);
}

