[C++实现]遍历LLVM字节码文件的所有Instruction

LLVM提供的工具已经十分丰富,基本上可以满足我们的使用需求,但是使用现成的工具往往会具有一定的局限在性,遇到问题是,我们总是喜欢自己撸代码来完成自己的目标,那么如何编译LLVM字节码文件中的Instruction呢? 且看下面的源代码:

#include <fstream>
#include <iostream>
#include <memory>
#include <iosfwd>
#include <llvm-c/IRReader.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/Instruction.h>
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/FormattedStream.h"

using namespace llvm;
using namespace std;

int main(int argc, char** argv){
if (argc < 2) {
errs() << "Expected an argument - IR file name\n";
exit(1);
}

LLVMContext &Context = getGlobalContext();
SMDiagnostic Err;

std::unique_ptr<llvm::Module> module = parseIRFile(argv[1], Err, Context);
Module* Mod = module.get();

if (!Mod) {
Err.print(argv[0], errs());
return 1;
}

for (Module::iterator FunIt = Mod->begin() ; FunIt != Mod->end() ; ++FunIt) {
for (Function::iterator i = FunIt->begin(), e = FunIt->end(); i != e; ++i) {
std::cout<< "Basic block name=" << i->getName().str() << std::endl;
for(auto j=i->begin(),f=i->end(); j!=f;j++) {
j->dump();
}
}
}

formatted_raw_ostream* Out;
}

这段代码就可以实现遍历LLVM字节码文件,但是现在他还无法通过通过编译,为了编译它,我们还需要创建一个cmakelist.txt文件,将下面的内容添加到这个文件当中

project(llvmtest)
cmake_minimum_required(VERSION 2.8)

find_package(LLVM REQUIRED CONFIG)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

# Needed to use support library

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -std=c++14")

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})

add_executable(llvmtest
DynamicValue.cpp
main.cpp)

llvm_map_components_to_libnames(llvm_libs support core irreader engine nativecodegen)


target_link_libraries(llvmtest
pthread
dl
)

#link llvm component
target_link_libraries(llvmtest ${llvm_libs})

#link llvm library
target_link_libraries(llvmtest
LLVMX86AsmParser # MC, MCParser, Support, X86Desc, X86Info
LLVMX86Desc # MC, Support, X86AsmPrinter, X86Info
LLVMX86AsmPrinter # MC, Support, X86Utils
LLVMX86Info # MC, Support, Target
LLVMX86Utils # Core, Support
LLVMipo
LLVMScalarOpts
LLVMInstCombine
LLVMTransformUtils
LLVMipa
LLVMAnalysis
LLVMTarget
LLVMOption # Support
LLVMMCParser # MC, Support
LLVMMC # Object, Support
LLVMObject # BitReader, Core, Support
LLVMBitReader # Core, Support
LLVMCore # Support
LLVMSupport
LLVMExecutionEngine
LLVMMCJIT
)

接下来就可以编译我们的代码了,编译成功后将生成一个llvmtest的可执行文件,使用它就可以遍历llvm字节码文件了,
例如:

./llvmtest test1.bc