mirror of
https://github.com/eshard/obfuscator-llvm
synced 2026-06-08 14:07:01 +00:00
5481d0338a
If we don't returns 'true', implicitly, it let means the previous analyses can be preserved which is not the case as split is performing CFG changes. In this case it caused and error when used with clang -fpass-plugin= Error: SplitBasicBlockPass does not invalidate CFG analyses but CFG changes detected in function @NewTreeNode: Different number of non-leaf basic blocks: before=0, after=2 Non-leaf block entry.split<0x55c11c3331d0> is added (1 successors) Non-leaf block entry<0x55c11c2934c0> is added (1 successors) fatal error: error in backend: CFG unexpectedly changed by SplitBasicBlockPass clang-13: error: clang frontend command failed with exit code 70 (use -v to see invocation) clang version 13.0.0 (https://github.com/llvm/llvm-project.git f6b09e394a5fad4b33f8746195377f4f638e2c8d)
148 lines
3.9 KiB
C++
148 lines
3.9 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"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/Passes/PassBuilder.h"
|
|
#include "llvm/Passes/PassPlugin.h"
|
|
|
|
#define DEBUG_TYPE "split"
|
|
|
|
using namespace std;
|
|
|
|
namespace llvm {
|
|
|
|
// Stats
|
|
STATISTIC(Split, "Basicblock splitted");
|
|
|
|
static cl::opt<int> SplitNum("split_num", cl::init(2),
|
|
cl::desc("Split <split_num> time each BB"));
|
|
|
|
struct LegacySplitBasicBlock : public FunctionPass, public SplitBasicBlock {
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
LegacySplitBasicBlock() : FunctionPass(ID) {}
|
|
LegacySplitBasicBlock(bool flag) : FunctionPass(ID) { this->flag = flag; }
|
|
|
|
bool runOnFunction(Function &F);
|
|
};
|
|
|
|
char LegacySplitBasicBlock::ID = 0;
|
|
static RegisterPass<LegacySplitBasicBlock> X("splitbbl",
|
|
"BasicBlock splitting");
|
|
|
|
bool LegacySplitBasicBlock::runOnFunction(Function &F) {
|
|
return runSplitBasicBlock(F);
|
|
}
|
|
|
|
PreservedAnalyses SplitBasicBlockPass::run(Function &F,
|
|
FunctionAnalysisManager &AM) {
|
|
return runSplitBasicBlock(F) ? PreservedAnalyses::none()
|
|
: PreservedAnalyses::all();
|
|
}
|
|
|
|
bool SplitBasicBlock::runSplitBasicBlock(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 true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
SplitBasicBlockPass::SplitBasicBlockPass() { this->flag = true; }
|
|
|
|
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)]);
|
|
}
|
|
}
|
|
} // namespace llvm
|