diff --git a/passes/ASPIS.h b/passes/ASPIS.h index 1d250c5..2cc4fca 100644 --- a/passes/ASPIS.h +++ b/passes/ASPIS.h @@ -76,8 +76,8 @@ class EDDI : public PassInfoMixin { 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 *CmpInstructions, Value *V, Instruction &I, IRBuilder<> &B); void compareValues(std::vector *CmpInstructions, Value &V1, Value &V2, IRBuilder<> &B); void fixGlobalCtors(Module &M); diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index c0e861a..cffda60 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -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(V) || isa(V)) { assert((DuplicatedInstructionMap.count(V) <= 1) && "Local variable has more than one duplicate"); @@ -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(duplicate) && cast(duplicate)->getParent()->getParent() == I->getParent()->getParent()) { + if (isa(duplicate) && cast(duplicate)->getParent()->getParent() == Fn) { return duplicate; } } @@ -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(Clone)) { IClone = cast(Clone); @@ -671,7 +671,7 @@ void EDDI::duplicateOperands( if (IClone != nullptr) { GEPOperator *GEPOperand = cast(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) { @@ -701,12 +701,12 @@ void EDDI::duplicateOperands( } } else if (isa(I) && isa(V) && cast(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 } @@ -780,17 +780,11 @@ void EDDI::comparePtrs(std::vector *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; } @@ -853,7 +847,7 @@ void EDDI::comparePtrs(std::vector *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 storeInsts; @@ -913,6 +907,11 @@ bool isLocalValueInitializedBefore(Instruction *AI, Instruction *At) { if(isa(I) && storeInsts.find(cast(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()); } @@ -944,7 +943,7 @@ void EDDI::addConsistencyChecks( // if the instruction is a call with indirect function, we try to get a compare if(isa(I) && cast(I).isIndirectCall()) { - Value *Duplicate = getDuplicateValue(cast(I).getCalledOperand(), &I); + Value *Duplicate = getDuplicateValue(cast(I).getCalledOperand(), I.getFunction()); if (Duplicate != nullptr) { Value *Original = cast(I).getCalledOperand(); Value *Copy = Duplicate; @@ -988,10 +987,10 @@ void EDDI::addConsistencyChecks( } void EDDI::createCompareOnOperand(std::vector *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; } @@ -1008,8 +1007,8 @@ void EDDI::createCompareOnOperand(std::vector *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()) { @@ -1062,6 +1061,7 @@ void EDDI::compareValues(std::vector *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); @@ -1093,19 +1093,11 @@ void EDDI::fixFuncValsPassedByReference( Value *V = I.getOperand(i); if (isa(V)) { Instruction *Operand = cast(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(TmpLoad, TmpLoad)); - DuplicatedInstructionMap.insert( - std::pair(TmpStore, TmpStore)); + if(Operand->getType()->isPointerTy() && Duplicate->getType()->isPointerTy()) { + synchronizeFunctionArguments(*I.getModule(), Operand, B, &I, false); } } } @@ -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; } @@ -1384,6 +1376,48 @@ int EDDI::duplicateInstruction(Instruction &I, BasicBlock &ErrBB) { return 0; } + if(I.isVolatile()) { + bool shouldDuplicateAnyway = false; + if(isa(I)) { + if(FuncAnnotations.find(cast(I).getPointerOperand()) != FuncAnnotations.end() && + (FuncAnnotations.find(cast(I).getPointerOperand())->second.starts_with("to_duplicate") || FuncAnnotations.find(cast(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(Idup)->moveAfter(&I); + DuplicatedInstructionMap.insert(std::pair(&I, Idup)); + DuplicatedInstructionMap.insert(std::pair(Idup, &I)); + } else if(I.getType()->isFloatingPointTy()) { + IRBuilder<> B(&I); + auto Idup = B.CreateAdd(&I, llvm::ConstantFP::get(I.getType(), 0)); + cast(Idup)->moveAfter(&I); + DuplicatedInstructionMap.insert(std::pair(&I, Idup)); + DuplicatedInstructionMap.insert(std::pair(Idup, &I)); + } + } else if(isa(I)) { + if(getDuplicateValue(cast(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(I) && cast(I).isInlineAsm()) { + return 0; + } + Instruction *clonedInst = nullptr; int res = 0; @@ -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); @@ -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); @@ -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(Arg)) { + if(getDuplicateValue(Arg, CInstr->getFunction()) != nullptr || !isa(Arg)) { // If Argument already duplicated continue to next argument continue; } @@ -1975,7 +2022,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { if(Arg->getType()->isPointerTy() && !CInstr->isByValArgument(i) && isa(Arg) && !isa(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(Arg, Arg)); // TODO: Check if needed @@ -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); @@ -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(currentPtr)) { auto *gepInst = cast(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(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(I)) { + memcpy_call->moveBefore(cast(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(valueDup, value)); + DuplicatedInstructionMap.insert(std::pair(value, valueDup)); } - DuplicatedInstructionMap.emplace(allocaPrev, value); - DuplicatedInstructionMap.emplace(value, allocaPrev); DuplicatedInstructionMap.insert(std::pair(memcpy_call, memcpy_call)); return true; diff --git a/passes/FuncRetToRef.cpp b/passes/FuncRetToRef.cpp index 3b46c9e..5f4c364 100644 --- a/passes/FuncRetToRef.cpp +++ b/passes/FuncRetToRef.cpp @@ -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(); @@ -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); } diff --git a/passes/Utils/Utils.cpp b/passes/Utils/Utils.cpp index 581b0bb..e96910e 100644 --- a/passes/Utils/Utils.cpp +++ b/passes/Utils/Utils.cpp @@ -218,12 +218,15 @@ StringRef getLinkageName(const LinkageMap &linkageMap, const std::string &functi } } -bool isToDuplicate(CallBase *CInstr) { - Intrinsic::ID intrinsicID = CInstr->getIntrinsicID(); - if (intrinsicID != Intrinsic::not_intrinsic) { - return true; - } else if(CInstr->getCalledFunction() != NULL && isToDuplicateName(CInstr->getCalledFunction()->getName())) { - return true; +bool isToDuplicate(Value *V) { + if(isa(V)) { + CallBase *CInstr = cast(V); + Intrinsic::ID intrinsicID = CInstr->getIntrinsicID(); + if (intrinsicID != Intrinsic::not_intrinsic) { + return true; + } else if(CInstr->getCalledFunction() != NULL && isToDuplicateName(CInstr->getCalledFunction()->getName())) { + return true; + } } return false; @@ -241,7 +244,8 @@ bool isToDuplicateName(StringRef FnMangledName) { if(FnName.find("std::ostream") != FnName.npos || FnName.find("std::basic_ostream") != FnName.npos || FnName.find("std::basic_ios") != FnName.npos || - FnName.find("std::thread") != FnName.npos) { + FnName.find("std::thread") != FnName.npos || + FnName.find("printf") != FnName.npos) { return false; } @@ -251,6 +255,24 @@ bool isToDuplicateName(StringRef FnMangledName) { return false; } +bool isToExclude(Value *V) { + if(isa(V)) { + Instruction *Inst = cast(V); + if (Inst->isVolatile()) { + return true; + } + } + + if(isa(V)) { + CallBase *CInstr = cast(V); + if(CInstr->getCalledFunction() != NULL && isToExcludeName(CInstr->getCalledFunction()->getName())) { + return true; + } + } + + return false; +} + bool isToExcludeName(StringRef FnMangledName) { if(FnMangledName.ends_with("_ret")) { FnMangledName = FnMangledName.substr(0, FnMangledName.size() - 4); @@ -258,7 +280,11 @@ bool isToExcludeName(StringRef FnMangledName) { auto FnName = demangle(FnMangledName.str()); - if(FnName.find("std::thread") != FnName.npos) { + if(FnName.find("std::ostream") != FnName.npos || + FnName.find("std::basic_ostream") != FnName.npos || + FnName.find("std::basic_ios") != FnName.npos || + FnName.find("std::thread") != FnName.npos || + FnName.find("printf") != FnName.npos) { return true; } diff --git a/passes/Utils/Utils.h b/passes/Utils/Utils.h index cdc7f0b..22313f8 100644 --- a/passes/Utils/Utils.h +++ b/passes/Utils/Utils.h @@ -45,8 +45,9 @@ LinkageMap mapFunctionLinkageNames(const Module &M); void printLinkageMap(const LinkageMap &linkageMap); StringRef getLinkageName(const LinkageMap &linkageMap, const std::string &functionName); bool isToDuplicateName(StringRef FnMangledName); -bool isToDuplicate(CallBase *CInstr); +bool isToDuplicate(Value *CInstr); bool isToExcludeName(StringRef FnMangledName); +bool isToExclude(Value *V); void createFtFuncs(Module &Md);