Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM: Change instruction or basic blocks in a function

Tags:

c++

llvm

I want to manipulate a function by reordering some instructions or inserting a new basic block.

My approach can be seen below.

I read in a module from LLVM IR and then iterate over its contents.

How would I change its contents?

Is cloning necessary, and if so, how would I insert new instructions?

#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;
}
like image 337
Shuzheng Avatar asked Oct 23 '25 03:10

Shuzheng


1 Answers

Generally, you don't need to clone or copy anything, unless you want to preserve original version.

Basic Blocks and Instructions both have APIs for insertions, moves, and replacements.

To manipulate blocks you can use the following methods (note, this may change in future):

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

The same goes for instructions:

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);

I can definitely recommend looking at BasiBlock and Instruction interfaces to see what else they have there.

like image 159
AlexDenisov Avatar answered Oct 25 '25 19:10

AlexDenisov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!