/*
 * Copyright 2011-2012, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "bcc/Support/Disassembler.h"

#include "bcc/Config/Config.h"
#if USE_DISASSEMBLER

#include <string>

#include <llvm/IR/LLVMContext.h>

#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCDisassembler.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCInstPrinter.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/MC/MCSubtargetInfo.h>

#include <llvm/Support/MemoryObject.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/raw_ostream.h>

#include "bcc/Support/OutputFile.h"
#include "bcc/Support/Log.h"

namespace {

class BufferMemoryObject : public llvm::MemoryObject {
private:
  const uint8_t *mBytes;
  uint64_t mLength;

public:
  BufferMemoryObject(const uint8_t *pBytes, uint64_t pLength)
    : mBytes(pBytes), mLength(pLength) {
  }

  virtual uint64_t getBase() const { return 0; }
  virtual uint64_t getExtent() const { return mLength; }

  virtual int readByte(uint64_t pAddr, uint8_t *pByte) const {
    if (pAddr > getExtent())
      return -1;
    *pByte = mBytes[pAddr];
    return 0;
  }
};

} // namespace anonymous

namespace bcc {

DisassembleResult Disassemble(llvm::raw_ostream &pOutput, const char *pTriple,
                              const char *pFuncName, const uint8_t *pFunc,
                              size_t pFuncSize) {
  DisassembleResult result = kDisassembleSuccess;
  uint64_t i = 0;

  const llvm::MCSubtargetInfo *subtarget_info = nullptr;
  const llvm::MCDisassembler *disassembler = nullptr;
  const llvm::MCInstrInfo *mc_inst_info = nullptr;
  const llvm::MCRegisterInfo *mc_reg_info = nullptr;
  const llvm::MCAsmInfo *asm_info = nullptr;
  llvm::MCInstPrinter *inst_printer = nullptr;

  BufferMemoryObject *input_function = nullptr;

  std::string error;
  const llvm::Target* target =
      llvm::TargetRegistry::lookupTarget(pTriple, error);

  if (target == nullptr) {
    ALOGE("Invalid target triple for disassembler: %s (%s)!",
          pTriple, error.c_str());
    return kDisassembleUnknownTarget;
  }

  subtarget_info =
      target->createMCSubtargetInfo(pTriple, /* CPU */"", /* Features */"");;

  if (subtarget_info == nullptr) {
    result = kDisassembleFailedSetup;
    goto bail;
  }

  disassembler = target->createMCDisassembler(*subtarget_info);

  mc_inst_info = target->createMCInstrInfo();

  mc_reg_info = target->createMCRegInfo(pTriple);

  asm_info = target->createMCAsmInfo(pTriple);

  if ((disassembler == nullptr) || (mc_inst_info == nullptr) ||
      (mc_reg_info == nullptr) || (asm_info == nullptr)) {
    result = kDisassembleFailedSetup;
    goto bail;
  }

  inst_printer = target->createMCInstPrinter(asm_info->getAssemblerDialect(),
                                             *asm_info, *mc_inst_info,
                                             *mc_reg_info, *subtarget_info);

  if (inst_printer == nullptr) {
    result = kDisassembleFailedSetup;
    goto bail;
  }

  input_function = new (std::nothrow) BufferMemoryObject(pFunc, pFuncSize);

  if (input_function == nullptr) {
    result = kDisassembleOutOfMemory;
    goto bail;
  }

  // Disassemble the given function
  pOutput << "Disassembled code: " << pFuncName << "\n";

  while (i < pFuncSize) {
    llvm::MCInst inst;
    uint64_t inst_size;

    llvm::MCDisassembler::DecodeStatus decode_result =
        disassembler->getInstruction(inst, inst_size, *input_function, i,
                                     llvm::nulls(), llvm::nulls());

    switch (decode_result) {
      case llvm::MCDisassembler::Fail: {
        ALOGW("Invalid instruction encoding encountered at %llu of function %s "
              "under %s.", i, pFuncName, pTriple);
        i++;
        break;
      }
      case llvm::MCDisassembler::SoftFail: {
        ALOGW("Potentially undefined instruction encoding encountered at %llu "
              "of function %s under %s.", i, pFuncName, pTriple);
        // fall-through
      }
      case llvm::MCDisassembler::Success : {
        const uint8_t *inst_addr = pFunc + i;

        pOutput.indent(4);
        pOutput << "0x";
        pOutput.write_hex(reinterpret_cast<uintptr_t>(inst_addr));
        pOutput << ": 0x";
        pOutput.write_hex(*reinterpret_cast<const uint32_t *>(inst_addr));
        inst_printer->printInst(&inst, pOutput, /* Annot */"");
        pOutput << "\n";

        i += inst_size;
        break;
      }
    }
  }

  pOutput << "\n";

bail:
  // Clean up
  delete input_function;
  delete inst_printer;
  delete asm_info;
  delete mc_reg_info;
  delete mc_inst_info;
  delete disassembler;
  delete subtarget_info;

  return result;
}

DisassembleResult Disassemble(OutputFile &pOutput, const char *pTriple,
                              const char *pFuncName, const uint8_t *pFunc,
                              size_t FuncSize) {
  // Check the state of the specified output file.
  if (pOutput.hasError()) {
    return kDisassembleInvalidOutput;
  }

  // Open the output file decorated in llvm::raw_ostream.
  llvm::raw_ostream *output = pOutput.dup();
  if (output == nullptr) {
    return kDisassembleFailedPrepareOutput;
  }

  // Delegate the request.
  DisassembleResult result =
      Disassemble(*output, pTriple, pFuncName, pFunc, FuncSize);

  // Close the output before return.
  delete output;

  return result;
}

} // namespace bcc

#else

bcc::DisassembleResult Disassemble(llvm::raw_ostream &pOutput,
                                   const char *pTriple, const char *pFuncName,
                                   const uint8_t *pFunc, size_t pFuncSize) {
  return bcc::kDisassemblerNotAvailable;
}

bcc::DisassembleResult bcc::Disassemble(OutputFile &pOutput,
                                        const char *pTriple,
                                        const char *pFuncName,
                                        const uint8_t *pFunc,
                                        size_t pFuncSize) {
  return bcc::kDisassemblerNotAvailable;
}

#endif // USE_DISASSEMBLER
