Files
eshard-obfuscator-llvm/split/SplitBasicBlocks.cpp
T
2021-10-13 18:16:41 +02:00

141 lines
3.5 KiB
C++

//===- SplitBasicBlock.cpp - SplitBasicBlokc Obfuscation pass--------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the split basic block pass
//
//===----------------------------------------------------------------------===//
#include "SplitBasicBlocks.h"
#include "utils/CryptoUtils.h"
#include "utils/Utils.h"
#define DEBUG_TYPE "split"
using namespace llvm;
using namespace std;
// Stats
STATISTIC(Split, "Basicblock splitted");
static cl::opt<int> SplitNum("split_num", cl::init(2),
cl::desc("Split <split_num> time each BB"));
namespace {
struct SplitBasicBlock : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
bool flag;
SplitBasicBlock() : FunctionPass(ID) {}
SplitBasicBlock(bool flag) : FunctionPass(ID) { this->flag = flag; }
bool runOnFunction(Function &F);
void split(Function *f);
bool containsPHI(BasicBlock *b);
void shuffle(std::vector<int> &vec);
};
} // namespace
char SplitBasicBlock::ID = 0;
static RegisterPass<SplitBasicBlock> X("splitbbl", "BasicBlock splitting");
Pass *llvm::createSplitBasicBlock(bool flag) {
return new SplitBasicBlock(flag);
}
bool SplitBasicBlock::runOnFunction(Function &F) {
// Check if the number of applications is correct
if (!((SplitNum > 1) && (SplitNum <= 10))) {
errs() << "Split application basic block percentage\
-split_num=x must be 1 < x <= 10";
return false;
}
Function *tmp = &F;
// Do we obfuscate
if (toObfuscate(flag, tmp, "split")) {
split(tmp);
++Split;
}
return false;
}
void SplitBasicBlock::split(Function *f) {
std::vector<BasicBlock *> origBB;
int splitN = SplitNum;
// Save all basic blocks
for (Function::iterator I = f->begin(), IE = f->end(); I != IE; ++I) {
origBB.push_back(&*I);
}
for (std::vector<BasicBlock *>::iterator I = origBB.begin(),
IE = origBB.end();
I != IE; ++I) {
BasicBlock *curr = *I;
// No need to split a 1 inst bb
// Or ones containing a PHI node
if (curr->size() < 2 || containsPHI(curr)) {
continue;
}
// Check splitN and current BB size
if ((size_t)splitN > curr->size()) {
splitN = curr->size() - 1;
}
// Generate splits point
std::vector<int> test;
for (unsigned i = 1; i < curr->size(); ++i) {
test.push_back(i);
}
// Shuffle
if (test.size() != 1) {
shuffle(test);
std::sort(test.begin(), test.begin() + splitN);
}
// Split
BasicBlock::iterator it = curr->begin();
BasicBlock *toSplit = curr;
int last = 0;
for (int i = 0; i < splitN; ++i) {
for (int j = 0; j < test[i] - last; ++j) {
++it;
}
last = test[i];
if (toSplit->size() < 2)
continue;
toSplit = toSplit->splitBasicBlock(it, toSplit->getName() + ".split");
}
++Split;
}
}
bool SplitBasicBlock::containsPHI(BasicBlock *b) {
for (BasicBlock::iterator I = b->begin(), IE = b->end(); I != IE; ++I) {
if (isa<PHINode>(I)) {
return true;
}
}
return false;
}
void SplitBasicBlock::shuffle(std::vector<int> &vec) {
int n = vec.size();
for (int i = n - 1; i > 0; --i) {
std::swap(vec[i], vec[cryptoutils->get_uint32_t() % (i + 1)]);
}
}