03-22-2021, 01:58 PM
下面是C++版本,参考的是 llvm/lib/MC/MCDisassembler/Disassembler.cpp 里面反汇编C接口的实现和 llvm/tools/llvm-objdump/llvm-objdump.cpp 反汇编功能的实现。
代码:
// g++ -g -Wall -o disas disas.cc -lLLVM
#include <iostream>
#include <memory>
#include <string>
// TargetRegistry::LookupTarget
// class Target
#include <llvm/Support/TargetRegistry.h>
// LLVMInitializeX86TargetInfo
#include <llvm/Support/TargetSelect.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInst.h>
#include <llvm/ADT/ArrayRef.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCInstPrinter.h>
int main()
{
LLVMInitializeX86TargetInfo();
// needed to create MCSubtargetInfo
LLVMInitializeX86TargetMC();
// MCContext, Disassembler
LLVMInitializeX86Disassembler();
std::string Error;
const llvm::Target *TheTarget = llvm::TargetRegistry::lookupTarget("x86_64", Error);
if (!TheTarget) {
std::cerr << Error << std::endl;
return 1;
}
std::unique_ptr<const llvm::MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo("x86_64", "", ""));
if (!STI) {
std::cerr << "Cannot create MCSubtargetInfo." << std::endl;
return 1;
}
// setup MCContext
std::unique_ptr<const llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo("x86_64"));
if (!MRI) {
std::cerr << "Cannot create MCRegInfo." << std::endl;
return 1;
}
// Get the assembler info needed to setup the MCContext.
llvm::MCTargetOptions MCOptions;
std::unique_ptr<const llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, "x86_64", MCOptions));
if (!MAI) {
std::cerr << "Cannot create MCAsmInfo." << std::endl;
return 1;
}
std::unique_ptr<llvm::MCContext> Ctx(new llvm::MCContext(MAI.get(), MRI.get(), nullptr));
if (!Ctx) {
std::cerr << "Cannot create MCContext." << std::endl;
return 1;
}
std::unique_ptr<llvm::MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, *Ctx));
if (!DisAsm) {
std::cerr << "Cannot create MCContext." << std::endl;
return 1;
}
uint8_t instBytes[] = { 0x48, 0x31, 0xc0, 0xcc }; // xor rax, rax; int3
llvm::ArrayRef<uint8_t> Data(instBytes, 4);
llvm::MCInst Inst;
uint64_t InstSize;
llvm::SmallVector<char, 64> InsnStr;
llvm::raw_svector_ostream Annotations(InsnStr);
llvm::MCDisassembler::DecodeStatus S = DisAsm->getInstruction(Inst, InstSize, Data, /*PC*/ 0, Annotations);
if (S == llvm::MCDisassembler::Success) {
std::cout << "Successfully disassembled " << InstSize << " bytes." << std::endl;
} else {
std::cerr << "Disassembler fails to get instruction." << std::endl;
return 1;
}
// Set up the instruction printer.
std::unique_ptr<const llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
if (!MII) {
std::cerr << "Cannot create MCInstrInfo." << std::endl;
return 1;
}
// int AsmPrinterVariant = MAI->getAssemblerDialect();
int AsmPrinterVariant = 1; // Use Intel style, default is AT&T
std::unique_ptr<llvm::MCInstPrinter> IP(TheTarget->createMCInstPrinter(llvm::Triple("x86_64"), AsmPrinterVariant, *MAI, *MII, *MRI));
if (!IP) {
std::cerr << "Cannot create MCInstPrinter." << std::endl;
return 1;
}
std::string assembly;
llvm::raw_string_ostream asm_stream(assembly);
IP->printInst(&Inst, /*address*/ 0, Annotations.str(), *STI, asm_stream);
std::cout << assembly << std::endl;
}