#include "Utils.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" #include namespace llvm { // Shamefully borrowed from ../Scalar/RegToMem.cpp :( bool valueEscapes(Instruction *Inst) { BasicBlock *BB = Inst->getParent(); for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { Instruction *I = cast(*UI); if (I->getParent() != BB || isa(I)) { return true; } } return false; } void fixStack(Function *f) { // Try to remove phi node and demote reg to stack std::vector tmpPhi; std::vector tmpReg; BasicBlock *bbEntry = &*f->begin(); do { tmpPhi.clear(); tmpReg.clear(); for (Function::iterator i = f->begin(); i != f->end(); ++i) { for (BasicBlock::iterator j = i->begin(); j != i->end(); ++j) { if (isa(j)) { PHINode *phi = cast(j); tmpPhi.push_back(phi); continue; } if (!(isa(j) && j->getParent() == bbEntry) && (valueEscapes(&*j) || j->isUsedOutsideOfBlock(&*i))) { tmpReg.push_back(&*j); continue; } } } for (unsigned int i = 0; i != tmpReg.size(); ++i) { DemoteRegToStack(*tmpReg.at(i), false); } for (unsigned int i = 0; i != tmpPhi.size(); ++i) { DemotePHIToStack(tmpPhi.at(i), f->begin()->getTerminator()->getIterator()); } } while (tmpReg.size() != 0 || tmpPhi.size() != 0); } std::string readAnnotate(Function *f) { std::string annotation = ""; // Get annotation variable GlobalVariable *glob = f->getParent()->getGlobalVariable("llvm.global.annotations"); if (glob != NULL) { // Get the array if (ConstantArray *ca = dyn_cast(glob->getInitializer())) { for (unsigned i = 0; i < ca->getNumOperands(); ++i) { // Get the struct if (ConstantStruct *structAn = dyn_cast(ca->getOperand(i))) { if (ConstantExpr *expr = dyn_cast(structAn->getOperand(0))) { // If it's a bitcast we can check if the annotation is concerning // the current function if (expr->getOpcode() == Instruction::BitCast && expr->getOperand(0) == f) { ConstantExpr *note = cast(structAn->getOperand(1)); // If it's a GetElementPtr, that means we found the variable // containing the annotations if (note->getOpcode() == Instruction::GetElementPtr) { if (GlobalVariable *annoteStr = dyn_cast(note->getOperand(0))) { if (ConstantDataSequential *data = dyn_cast( annoteStr->getInitializer())) { if (data->isString()) { annotation += data->getAsString().lower() + " "; } } } } } } } } } } return annotation; } bool toObfuscate(bool flag, Function *f, std::string attribute) { std::string attr = attribute; std::string attrNo = "no" + attr; // Check if declaration if (f->isDeclaration()) { return false; } // Check external linkage if (f->hasAvailableExternallyLinkage() != 0) { return false; } // We have to check the nofla flag first // Because .find("fla") is true for a string like "fla" or // "nofla" if (readAnnotate(f).find(attrNo) != std::string::npos) { return false; } // If fla annotations if (readAnnotate(f).find(attr) != std::string::npos) { return true; } // If fla flag is set if (flag == true) { /* Check if the number of applications is correct if (!((Percentage > 0) && (Percentage <= 100))) { LLVMContext &ctx = llvm::getGlobalContext(); ctx.emitError(Twine("Flattening application function\ percentage -perFLA=x must be 0 < x <= 100")); } // Check name else if (func.size() != 0 && func.find(f->getName()) != std::string::npos) { return true; } if ((((int)llvm::cryptoutils->get_range(100))) < Percentage) { return true; } */ return true; } return false; } } // namespace llvm