2017-01-18 2 views
3

Я хочу манипулировать функцией, переупорядочивая некоторые инструкции или вставляя новый базовый блок.LLVM: изменить инструкцию или базовые блоки в функции

Мой подход можно увидеть ниже.

Я читаю модуль из LLVM IR и затем перебираю его содержимое.

Как я могу изменить его содержимое?

Нужно клонирование, и если да, то как мне вставить новые инструкции?

#include <iostream> 

#include <llvm/IR/Module.h> 
#include <llvm/IRReader/IRReader.h> 
#include <llvm/IR/LLVMContext.h> 
#include <llvm/Support/SourceMgr.h> 
#include <llvm/Bitcode/ReaderWriter.h> 
#include <llvm/Support/FileSystem.h> 
#include <llvm/Transforms/Utils/Cloning.h> 

using namespace llvm; 
int main() 
{ 
    LLVMContext context; 
    SMDiagnostic error; 
    std::unique_ptr<Module> m = parseIRFile("test.ll", error, context); 

    std::error_code EC; 
    llvm::raw_fd_ostream OS("module", EC, llvm::sys::fs::F_None); 
    WriteBitcodeToFile(m.get(), OS); 
    OS.flush(); 

    std::cout << "Successfully read Module:" << std::endl; 
    std::cout << " Name: " << m->getName().str() << std::endl; 
    std::cout << " Target triple: " << m->getTargetTriple() << std::endl; 

    Module* mod = new Module("obfus", getGlobalContext()); 

    for (auto iter1 = m->getFunctionList().begin(); 
     iter1 != m->getFunctionList().end(); iter1++) { 
    Function &f = *iter1; 
    std::cout << " Function: " << f.getName().str() << std::endl; 

    Function* duplicateFunction = CloneFunction(f, nullptr, /*ModuleLevelChanges=*/false); 
    f.getParent()->getFunctionList().push_back(duplicateFunction); 

    for (auto iter2 = f.getBasicBlockList().begin(); 
     iter2 != f.getBasicBlockList().end(); iter2++) { 
     BasicBlock &bb = *iter2; 
     std::cout << " BasicBlock: " << bb.getName().str() << std::endl; 
     for (auto iter3 = bb.begin(); iter3 != bb.end(); iter3++) { 
     Instruction &inst = *iter3; 
     std::cout << " Instruction " << &inst << " : " << inst.getOpcodeName(); 

    unsigned int i = 0; 
    unsigned int opnt_cnt = inst.getNumOperands(); 
     for(; i < opnt_cnt; ++i) 
     { 
     Value *opnd = inst.getOperand(i); 
     std::string o; 
     //   raw_string_ostream os(o); 
     //   opnd->print(os); 
     //opnd->printAsOperand(os, true, m); 
     if (opnd->hasName()) { 
      o = opnd->getName(); 
      std::cout << " " << o << "," ; 
     } else { 
      std::cout << " ptr" << opnd << ","; 
     } 
     } 
     std:: cout << std::endl; 
     } 
    } 
    } 

    return 0; 
} 

ответ

4

Как правило, вам не нужно клонировать или копировать что-либо, если вы не хотите сохранить оригинальную версию.

Основные блоки и инструкции имеют API для вставки, перемещения и замены.

Для управления блоками вы можете использовать следующие методы (учтите, что это может измениться в будущем):

void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr); 
void moveAfter(BasicBlock *MovePos); 
void moveBefore(BasicBlock *MovePos); 
SymbolTableList<BasicBlock>::iterator eraseFromParent(); 
void removeFromParent(); 

То же самое относится и к инструкции:

void removeFromParent(); 
SymbolTableList<Instruction>::iterator eraseFromParent(); 
void insertBefore(Instruction *InsertPos); 
void insertAfter(Instruction *InsertPos); 
void moveBefore(Instruction *MovePos); 
void moveBefore(BasicBlock &BB, SymbolTableList<Instruction>::iterator I); 

Я определенно рекомендую посмотреть на BasiBlock и интерфейсы инструкций, чтобы увидеть, что еще они там есть.