#include #include #include #include #include #include #if LLVM_VERSION_MAJOR >= 14 #include #if LLVM_VERSION_MAJOR >= 15 #include #endif #else #include #endif #include #include #include #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) { // llvm::InitializeAllTargetInfos(); // llvm::InitializeAllTargetMCs(); // llvm::InitializeAllAsmParsers(); // llvm::InitializeAllDisassemblers(); LLVMInitializeRISCVTargetInfo(); LLVMInitializeRISCVTargetMC(); LLVMInitializeRISCVAsmParser(); LLVMInitializeRISCVDisassembler(); 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 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; }