Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions passes/ASPIS.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ class EDDI : public PassInfoMixin<EDDI> {
bool isValueDuplicated(Instruction &V);
Function *duplicateFnArgs(Function &Fn, Module &Md);
void CreateErrBB(Module &Md, Function &Fn, BasicBlock *ErrBB);
bool temporaryArgumentDuplication(Module &Md, llvm::Value *value, IRBuilder<> &B);
Value *getDuplicateValue(Value *V, Instruction *I);
bool synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I, bool before);
Value *getDuplicateValue(Value *V, Function *I);
void createCompareOnOperand(std::vector<Value *> *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B);
void compareValues(std::vector<Value *> *CmpInstructions, Value &V1, Value &V2, IRBuilder<> &B);
void fixGlobalCtors(Module &M);
Expand Down
184 changes: 130 additions & 54 deletions passes/EDDI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ EDDI::cloneInstr(Instruction &I) {
return IClone;
}

Value *EDDI::getDuplicateValue(Value *V, Instruction *I) {
Value *EDDI::getDuplicateValue(Value *V, Function *Fn) {
// Fast path if V is a local variable, it should have only one duplicate
if(!isa<GlobalValue>(V) || isa<Argument>(V)) {
assert((DuplicatedInstructionMap.count(V) <= 1) && "Local variable has more than one duplicate");
Expand All @@ -620,7 +620,7 @@ Value *EDDI::getDuplicateValue(Value *V, Instruction *I) {
return duplicate;
} else {
// If it is an instruction, we need to check if it is in the same function of I
if (isa<Instruction>(duplicate) && cast<Instruction>(duplicate)->getParent()->getParent() == I->getParent()->getParent()) {
if (isa<Instruction>(duplicate) && cast<Instruction>(duplicate)->getParent()->getParent() == Fn) {
return duplicate;
}
}
Expand All @@ -643,7 +643,7 @@ void EDDI::duplicateOperands(
BasicBlock &ErrBB) {

// see if I has a clone
Value *Clone = getDuplicateValue(&I, &I);
Value *Clone = getDuplicateValue(&I, I.getFunction());
Instruction *IClone = nullptr;
if(Clone != nullptr && isa<Instruction>(Clone)) {
IClone = cast<Instruction>(Clone);
Expand Down Expand Up @@ -671,7 +671,7 @@ void EDDI::duplicateOperands(
if (IClone != nullptr) {
GEPOperator *GEPOperand = cast<GEPOperator>(IClone->getOperand(J));
Value *PtrOperand = GEPOperand->getPointerOperand();
Value *ClonePtrOperand = getDuplicateValue(PtrOperand, &I);
Value *ClonePtrOperand = getDuplicateValue(PtrOperand, I.getFunction());
// update the duplicate GEP operator using the duplicate of the pointer
// operand
if (ClonePtrOperand != nullptr) {
Expand Down Expand Up @@ -701,12 +701,12 @@ void EDDI::duplicateOperands(
}
} else if (isa<StoreInst>(I) && isa<GlobalVariable>(V) && cast<GlobalVariable>(V)->isConstant()) {
IRBuilder<> B(&I);
temporaryArgumentDuplication(*I.getModule(), V, B);
synchronizeFunctionArguments(*I.getModule(), V, B, &I, true);
}

if (IClone != nullptr) {
// use the duplicated instruction as operand of IClone
Value *CloneOperand = getDuplicateValue(V, &I);
Value *CloneOperand = getDuplicateValue(V, I.getFunction());
if (CloneOperand != nullptr) {
IClone->setOperand(J, CloneOperand); // set the J-th operand with the duplicate value
}
Expand Down Expand Up @@ -780,17 +780,11 @@ void EDDI::comparePtrs(std::vector<Value *> *CmpInstructions, Value &V1, Value &

if(deducedTypes.transparentTypes.find(&V1)->second.size() != 1) {
errs() << "\tMultiple types 1!\n";
for(auto el=deducedTypes.transparentTypes.find(&V1)->second.cbegin(); el != deducedTypes.transparentTypes.find(&V1)->second.cend(); el++) {
errs() << "\t" << el->get()->toString() << "\n";
}
return;
}

if(deducedTypes.transparentTypes.find(&V2)->second.size() != 1) {
errs() << "\tMultiple types 2!\n";
for(auto el=deducedTypes.transparentTypes.find(&V2)->second.cbegin(); el != deducedTypes.transparentTypes.find(&V2)->second.cend(); el++) {
errs() << "\t" << el->get()->toString() << "\n";
}
return;
}

Expand Down Expand Up @@ -853,7 +847,7 @@ void EDDI::comparePtrs(std::vector<Value *> *CmpInstructions, Value &V1, Value &


bool isLocalValueInitializedBefore(Instruction *AI, Instruction *At) {

assert(AI->getParent()->getParent() == At->getParent()->getParent() && "Alloca and Instruction not in the same function!");

std::unordered_set<StoreInst *> storeInsts;
Expand Down Expand Up @@ -913,6 +907,11 @@ bool isLocalValueInitializedBefore(Instruction *AI, Instruction *At) {
if(isa<StoreInst>(I) && storeInsts.find(cast<StoreInst>(I)) != storeInsts.end()) {
break;
}

// return false if we don't have a next node before encountering a store
if(I->getNextNode() == nullptr) {
return false;
}
} while(I = I->getNextNode());
}

Expand Down Expand Up @@ -944,7 +943,7 @@ void EDDI::addConsistencyChecks(

// if the instruction is a call with indirect function, we try to get a compare
if(isa<CallBase>(I) && cast<CallBase>(I).isIndirectCall()) {
Value *Duplicate = getDuplicateValue(cast<CallBase>(I).getCalledOperand(), &I);
Value *Duplicate = getDuplicateValue(cast<CallBase>(I).getCalledOperand(), I.getFunction());
if (Duplicate != nullptr) {
Value *Original = cast<CallBase>(I).getCalledOperand();
Value *Copy = Duplicate;
Expand Down Expand Up @@ -988,10 +987,10 @@ void EDDI::addConsistencyChecks(
}

void EDDI::createCompareOnOperand(std::vector<Value *> *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B) {
auto Duplicate = DuplicatedInstructionMap.find(V);
auto Duplicate = getDuplicateValue(V, I.getFunction());

// if the duplicate doesn't exist, we cannot perform a compare
if (Duplicate == DuplicatedInstructionMap.end()) {
if (Duplicate == nullptr) {
return;
}

Expand All @@ -1008,8 +1007,8 @@ void EDDI::createCompareOnOperand(std::vector<Value *> *CmpInstructions, Value *
// TODO: are there other cases to support?
}

Value *Original = Duplicate->first;
Value *Copy = Duplicate->second;
Value *Original = V;
Value *Copy = Duplicate;

// we compare the operands only if they are found in the TDA transparent types
if(deducedTypes.transparentTypes.find(V) == deducedTypes.transparentTypes.end()) {
Expand Down Expand Up @@ -1062,6 +1061,7 @@ void EDDI::compareValues(std::vector<Value *> *CmpInstructions, Value &V1, Value
} else if(V1Ty->isArrayTT()) {
int arraysize = V1Ty->getLLVMType()->getArrayNumElements();

// TODO: understand if is possible to remove the extracted values when no check is performed
for (int i = 0; i < arraysize; i++) {
Value *OriginalElem = B.CreateExtractValue(&V1, i);
Value *CopyElem = B.CreateExtractValue(&V2, i);
Expand Down Expand Up @@ -1093,19 +1093,11 @@ void EDDI::fixFuncValsPassedByReference(
Value *V = I.getOperand(i);
if (isa<Instruction>(V)) {
Instruction *Operand = cast<Instruction>(V);
Value *Duplicate = getDuplicateValue(Operand, &I);
Value *Duplicate = getDuplicateValue(Operand, I.getFunction());

if (Duplicate != nullptr) {
Value *Original = Operand;
Value *Copy = Duplicate;
if(Original->getType()->isPointerTy() && Copy->getType()->isPointerTy()) {
Type *OriginalType = Original->getType();
Instruction *TmpLoad = B.CreateLoad(OriginalType, Original);
Instruction *TmpStore = B.CreateStore(TmpLoad, Copy);
DuplicatedInstructionMap.insert(
std::pair<Instruction *, Instruction *>(TmpLoad, TmpLoad));
DuplicatedInstructionMap.insert(
std::pair<Instruction *, Instruction *>(TmpStore, TmpStore));
if(Operand->getType()->isPointerTy() && Duplicate->getType()->isPointerTy()) {
synchronizeFunctionArguments(*I.getModule(), Operand, B, &I, false);
}
}
}
Expand Down Expand Up @@ -1271,7 +1263,7 @@ int EDDI::transformCallBaseInst(CallBase *CInstr, IRBuilder<> &B, BasicBlock &Er
Value *Arg = CInstr->getArgOperand(i);

// see if Original has a copy
Value *Copy = getDuplicateValue(Arg, CInstr);
Value *Copy = getDuplicateValue(Arg, CInstr->getFunction());
if(Copy == nullptr) {
Copy = Arg;
}
Expand Down Expand Up @@ -1384,6 +1376,48 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) {
return 0;
}

if(I.isVolatile()) {
bool shouldDuplicateAnyway = false;
if(isa<LoadInst>(I)) {
if(FuncAnnotations.find(cast<LoadInst>(I).getPointerOperand()) != FuncAnnotations.end() &&
(FuncAnnotations.find(cast<LoadInst>(I).getPointerOperand())->second.starts_with("to_duplicate") || FuncAnnotations.find(cast<LoadInst>(I).getPointerOperand())->second.starts_with("to_harden"))) {
shouldDuplicateAnyway = true;
} else if(I.getType()->isIntegerTy()) {
IRBuilder<> B(&I);
auto Idup = B.CreateAdd(&I, llvm::ConstantInt::get(I.getType(), 0));
cast<Instruction>(Idup)->moveAfter(&I);
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(&I, Idup));
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(Idup, &I));
} else if(I.getType()->isFloatingPointTy()) {
IRBuilder<> B(&I);
auto Idup = B.CreateAdd(&I, llvm::ConstantFP::get(I.getType(), 0));
cast<Instruction>(Idup)->moveAfter(&I);
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(&I, Idup));
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(Idup, &I));
}
} else if(isa<StoreInst>(I)) {
if(getDuplicateValue(cast<StoreInst>(I).getPointerOperand(), I.getFunction()) != nullptr) {
shouldDuplicateAnyway = true;
} else {
#ifdef CHECK_AT_STORES
#if (SELECTIVE_CHECKING == 1)
if(I.getParent()->getTerminator() == NULL) {
errs() << "Malformed block!\n";
I.getParent()->print(errs());
errs() << "\n";
} else if (I.getParent()->getTerminator()->getNumSuccessors() > 1)
#endif
addConsistencyChecks(I, ErrBB);
#endif
}
}
if(!shouldDuplicateAnyway) {
return 0;
}
} else if (isa<CallBase>(I) && cast<CallBase>(I).isInlineAsm()) {
return 0;
}

Instruction *clonedInst = nullptr;
int res = 0;

Expand Down Expand Up @@ -1435,7 +1469,7 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) {
if (IClone->isIdenticalTo(&I)) {
IClone->eraseFromParent();

Value *Copy = getDuplicateValue(&I, &I);
Value *Copy = getDuplicateValue(&I, I.getFunction());
if(Copy != nullptr) {
DuplicatedInstructionMap.erase(Copy);
DuplicatedInstructionMap.erase(&I);
Expand Down Expand Up @@ -1471,13 +1505,26 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) {
Function *Callee = CInstr->getCalledFunction();
Callee = getFunctionFromDuplicate(Callee);

if(CInstr->getCalledFunction() != NULL && isToExcludeName(CInstr->getCalledFunction()->getName())) {
if((FuncAnnotations.find(Callee) != FuncAnnotations.end() && FuncAnnotations.find(Callee)->second.starts_with("exclude")) || (Callee != NULL && isToExclude(CInstr))) {
IRBuilder<> B(CInstr);
fixFuncValsPassedByReference(*CInstr, B);

#ifdef CHECK_AT_CALLS
#if (SELECTIVE_CHECKING == 1)
if(I.getParent()->getTerminator() == NULL) {
errs() << "Malformed block!\n";
I.getParent()->print(errs());
errs() << "\n";
} else if (I.getParent()->getTerminator()->getNumSuccessors() > 1)
#endif
addConsistencyChecks(I, ErrBB);
#endif
return 0;
}

// check if the function call has to be duplicated
if ((FuncAnnotations.find(Callee) != FuncAnnotations.end() && FuncAnnotations.find(Callee)->second.starts_with("to_duplicate")) ||
isToDuplicate(CInstr)) {
(Callee != NULL && isToDuplicate(CInstr))) {
// duplicate the instruction
clonedInst = cloneInstr(*CInstr);

Expand Down Expand Up @@ -1966,7 +2013,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) {
Value *Arg = CInstr->getArgOperand(i);

// If argument has already a duplicate, nothing to do
if(getDuplicateValue(Arg, CInstr) != nullptr || !isa<Instruction>(Arg)) {
if(getDuplicateValue(Arg, CInstr->getFunction()) != nullptr || !isa<Instruction>(Arg)) {
// If Argument already duplicated continue to next argument
continue;
}
Expand All @@ -1975,7 +2022,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) {
if(Arg->getType()->isPointerTy() && !CInstr->isByValArgument(i) && isa<Instruction>(Arg) && !isa<CallInst>(Arg))
{
// If cannot perform TAD, do not duplicate Arg
temporaryArgumentDuplication(Md, Arg, B);
synchronizeFunctionArguments(Md, Arg, B, CInstr, true);
} else {
// Otherwise pass two times the same arg
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(Arg, Arg)); // TODO: Check if needed
Expand Down Expand Up @@ -2048,7 +2095,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) {
return PreservedAnalyses::none();
}

bool EDDI::temporaryArgumentDuplication(Module &Md, llvm::Value *value, IRBuilder<> &B) {
bool EDDI::synchronizeFunctionArguments(Module &Md, llvm::Value *value, IRBuilder<> &B, Instruction *I, bool before) {
const llvm::DataLayout &DL = Md.getDataLayout();

auto TTIter = deducedTypes.transparentTypes.find(value);
Expand Down Expand Up @@ -2088,44 +2135,73 @@ bool EDDI::temporaryArgumentDuplication(Module &Md, llvm::Value *value, IRBuilde
}
}

// currentPtr is now the pointer to the final value

bool hasPerformedTAD = false;
Value *valueDup = getDuplicateValue(value, I->getFunction());
uint64_t SizeInBytes = 0;
AllocaInst *allocaPrev = nullptr;

if(isa<GetElementPtrInst>(currentPtr)) {
auto *gepInst = cast<GetElementPtrInst>(currentPtr);
SizeInBytes = DL.getTypeAllocSize(gepInst->getSourceElementType());
allocaPrev = B.CreateAlloca(VTy->getLLVMType(), ConstantInt::get(VTy->getLLVMType(), SizeInBytes));
} else {
SizeInBytes = DL.getTypeAllocSize(VTy->getLLVMType());
allocaPrev = B.CreateAlloca(VTy->getLLVMType());
}

deducedTypes.transparentTypes[allocaPrev].insert(VTy->clone());
if(valueDup == nullptr) {
hasPerformedTAD = true;
assert(hasPerformedTAD && before && "TAD shall be performed only for syncrhonization before the instruction");
// currentPtr is now the pointer to the final value

AllocaInst *allocaPrev = nullptr;

if(isa<GetElementPtrInst>(currentPtr)) {
allocaPrev = B.CreateAlloca(VTy->getLLVMType(), ConstantInt::get(B.getInt8Ty(), SizeInBytes));
} else {
allocaPrev = B.CreateAlloca(VTy->getLLVMType());
}
allocaPrev->moveAfter(allocaPrev->getParent()->getParent()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());

deducedTypes.transparentTypes[allocaPrev].insert(VTy->clone());
valueDup = allocaPrev;
} else {
hasPerformedTAD = false;
}

Value *Size = llvm::ConstantInt::get(B.getInt8Ty(), SizeInBytes);

llvm::CallInst *memcpy_call = B.CreateMemCpy(
allocaPrev, allocaPrev->getPointerAlignment(DL),
currentPtr, allocaPrev->getPointerAlignment(DL),
valueDup, valueDup->getPointerAlignment(DL),
currentPtr, valueDup->getPointerAlignment(DL),
Size);

if(!before) {
if(!I->isTerminator()) {
memcpy_call->moveAfter(I);
} else {
if(isa<InvokeInst>(I)) {
memcpy_call->moveBefore(cast<InvokeInst>(I)->getNormalDest()->getFirstNonPHIOrDbgOrAlloca());
} else {
errs() << "Error: not handled instruction for synchronize function arguments\n";
abort();
}
}
}

auto VTyPtr = VTy->clone();

// Now we need to create as many allocas as the number of pointer indirections
// in order to duplicate the whole pointer chain
for (int i = 0; i < indirections; ++i) {
VTyPtr = VTyPtr->getPointerToType();
auto *allocaCurr = B.CreateAlloca(VTyPtr->getLLVMType());
deducedTypes.transparentTypes[allocaCurr].insert(VTyPtr->getPointerToType()->clone());
B.CreateStore(allocaPrev, allocaCurr);
allocaPrev = allocaCurr;
if(hasPerformedTAD) {
for (int i = 0; i < indirections; ++i) {
VTyPtr = VTyPtr->getPointerToType();
auto *allocaCurr = B.CreateAlloca(VTyPtr->getLLVMType());
allocaCurr->moveAfter(allocaCurr->getParent()->getParent()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
deducedTypes.transparentTypes[allocaCurr].insert(VTyPtr->getPointerToType()->clone());
B.CreateStore(valueDup, allocaCurr);
valueDup = allocaCurr;
}

DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(valueDup, value));
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(value, valueDup));
}

DuplicatedInstructionMap.emplace(allocaPrev, value);
DuplicatedInstructionMap.emplace(value, allocaPrev);
DuplicatedInstructionMap.insert(std::pair<Value *, Value *>(memcpy_call, memcpy_call));

return true;
Expand Down
4 changes: 2 additions & 2 deletions passes/FuncRetToRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void FuncRetToRef::updateRetInstructions(Function &Fn) {
Value *ReturnPtr = Fn.getArg(Fn.arg_size()-1); // the last argument is the return ptr

// Store the returnvalue in the returnptr
B.CreateStore(ReturnValue, ReturnPtr, true);
B.CreateStore(ReturnValue, ReturnPtr);

// create a ret instruction
B.CreateRetVoid();
Expand Down Expand Up @@ -208,7 +208,7 @@ void FuncRetToRef::updateFunctionCalls(Function &Fn, Function &NewFn) {
abort();
}
// use the load on the return value instead of the previous function output
Instruction *TmpLoad = B.CreateLoad(CInstr->getType(), TmpAlloca, true);
Instruction *TmpLoad = B.CreateLoad(CInstr->getType(), TmpAlloca);
createdNewCall = true;
CInstr->replaceNonMetadataUsesWith(TmpLoad);
}
Expand Down
Loading
Loading