ysyx-workbench/npc/utils/sdb/disasm.cpp

91 lines
2.9 KiB
C++
Raw Normal View History

2024-04-09 09:03:21 +00:00
#include <disasm.hpp>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstPrinter.h>
#include <llvm/Support/raw_ostream.h>
#if LLVM_VERSION_MAJOR >= 14
#include <llvm/MC/TargetRegistry.h>
#if LLVM_VERSION_MAJOR >= 15
#include <llvm/MC/MCSubtargetInfo.h>
#endif
#else
#include <llvm/Support/TargetRegistry.h>
#endif
#include <iostream>
#include <llvm/Support/TargetSelect.h>
#include <sstream>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
#if LLVM_VERSION_MAJOR < 11
#error Please use LLVM with major version >= 11
#endif
Disassembler::Disassembler(std::string triple) : triple(triple) {
2024-04-12 08:39:24 +00:00
// llvm::InitializeAllTargetInfos();
// llvm::InitializeAllTargetMCs();
// llvm::InitializeAllAsmParsers();
// llvm::InitializeAllDisassemblers();
LLVMInitializeRISCVTargetInfo();
LLVMInitializeRISCVTargetMC();
LLVMInitializeRISCVAsmParser();
LLVMInitializeRISCVDisassembler();
2024-04-09 09:03:21 +00:00
std::string errstr;
llvm::MCInstrInfo *gMII = nullptr;
llvm::MCRegisterInfo *gMRI = nullptr;
auto target = llvm::TargetRegistry::lookupTarget(triple, errstr);
if (!target) {
llvm::errs() << "Can't find target for " << triple << ": " << errstr
<< "\n";
assert(0);
}
llvm::MCTargetOptions MCOptions;
gSTI = target->createMCSubtargetInfo(triple, "", "");
std::string isa = target->getName();
if (isa == "riscv32" || isa == "riscv64") {
gSTI->ApplyFeatureFlag("+m");
gSTI->ApplyFeatureFlag("+a");
gSTI->ApplyFeatureFlag("+c");
gSTI->ApplyFeatureFlag("+f");
gSTI->ApplyFeatureFlag("+d");
}
gMII = target->createMCInstrInfo();
gMRI = target->createMCRegInfo(triple);
auto AsmInfo = target->createMCAsmInfo(*gMRI, triple, MCOptions);
#if LLVM_VERSION_MAJOR >= 13
auto llvmTripleTwine = llvm::Twine(triple);
auto llvmtriple = llvm::Triple(llvmTripleTwine);
auto Ctx = new llvm::MCContext(llvmtriple, AsmInfo, gMRI, nullptr);
#else
auto Ctx = new llvm::MCContext(AsmInfo, gMRI, nullptr);
#endif
gDisassembler = target->createMCDisassembler(*gSTI, *Ctx);
gIP = target->createMCInstPrinter(llvm::Triple(triple),
AsmInfo->getAssemblerDialect(), *AsmInfo,
*gMII, *gMRI);
gIP->setPrintImmHex(true);
gIP->setPrintBranchImmAsAddress(true);
if (isa == "riscv32" || isa == "riscv64")
gIP->applyTargetSpecificCLOption("no-aliases");
}
std::string Disassembler::disassemble(uint64_t pc, uint8_t *code, int nbyte) {
llvm::MCInst inst;
llvm::ArrayRef<uint8_t> arr(code, nbyte);
uint64_t dummy_size = 0;
gDisassembler->getInstruction(inst, dummy_size, arr, pc, llvm::nulls());
std::stringstream ss;
ss << "0x" << std::hex << pc << ": ";
std::string s = ss.str();
llvm::raw_string_ostream os{s};
gIP->printInst(&inst, pc, "", *gSTI, os);
return s;
}