/// IsEquivalentPHI - Check if PHI has the same incoming value as specified /// in ValueMapping for each predecessor block. static bool IsEquivalentPHI(PHINode *PHI, DenseMap<BasicBlock*, Value*> &ValueMapping) { unsigned PHINumValues = PHI->getNumIncomingValues(); if (PHINumValues != ValueMapping.size()) return false; // Scan the phi to see if it matches. for (unsigned i = 0, e = PHINumValues; i != e; ++i) if (ValueMapping[PHI->getIncomingBlock(i)] != PHI->getIncomingValue(i)) { return false; } return true; }
bool CSDataRando::runOnModule(Module &M) { DSA = &getAnalysis<BUMarkDoNotEncrypt>(); MaskTy = TypeBuilder<mask_t, false>::get(M.getContext()); FunctionWrappers &FW = getAnalysis<FunctionWrappers>(); { // Gather statistics on the globals DenseMap<const DSNode*, unsigned int> GlobalClassSizes; DSGraph *GG = DSA->getGlobalsGraph(); for (GlobalVariable &GV : M.getGlobalList()) { if (!(GV.isDeclaration() || PointerEquivalenceAnalysis::shouldIgnoreGlobal(GV))) { GlobalClassSizes[GG->getNodeForValue(&GV).getNode()] += 1; } } NumGlobalECs = GlobalClassSizes.size(); for (auto i : GlobalClassSizes) { if (i.second > MaxSizeGlobalEC) { MaxSizeGlobalEC = i.second; } } } findGlobalNodes(M); findArgNodes(M); // Find which functions may need cloning. If we have a DSGraph for the // function, consider it a candidate for cloning. std::vector<Function *> OriginalFunctions; for (Function &F : M) { if (!F.isDeclaration() && DSA->hasDSGraph(F)) { OriginalFunctions.push_back(&F); } } // Perform cloning of the original functions Function *Main = M.getFunction("main"); for (Function *Original : OriginalFunctions) { // Handle the main function if (Main && Original == Main) { // Never clone main OldToNewFuncMap[Original] = nullptr; // If main has no uses then we can encrypt the arguments to main. To allow // the arg nodes to be encrypted we clear ArgNodes. if (Original->uses().begin() == Original->uses().end()) { FunctionInfo[Original].ArgNodes.clear(); } continue; } // Maybe make a clone, if a clone was not made nullptr is returned. OldToNewFuncMap[Original] = makeFunctionClone(Original); } // File to potentially print diagnostic information std::unique_ptr<tool_output_file> Out(nullptr); // If we will be printing diagnostic information, open the file if (!PointerEquivalenceAnalysis::PrintEquivalenceClassesTo.empty()) { std::error_code error; Out.reset(new tool_output_file(PointerEquivalenceAnalysis::PrintEquivalenceClassesTo, error, sys::fs::F_None)); if (error) { Out.release(); } } // Perform randomization DataRandomizer DR(M); RandomNumberGenerator *RNG = M.createRNG(this); FuncInfo empty; ContextSensitivePEA GGPEA(*RNG, M.getContext(), empty, *DSA->getGlobalsGraph()); DR.encryptGlobalVariables(M, GGPEA); // All original functions with DSGraphs will be in OldToNewFuncMap. If a clone // was not made, then the entry will map to nullptr. for (auto i : OldToNewFuncMap) { Function *Original = i.first; Function *Clone = i.second; FuncInfo &FI = FunctionInfo[Original]; DSGraph *Graph = DSA->getDSGraph(*Original); if (Clone) { // Perform randomization of the cloned function CloneFunctionPEA CP(*RNG, M.getContext(), FI, *Graph, &GGPEA); DR.instrumentMemoryOperations(*Clone, CP, NULL); DR.wrapLibraryFunctions(*Clone, CP, FW); replaceWithClones(Clone, FI, CP, Graph); if (Out.get()) { // Add all Instructions before dumping to make the dump more complete. addAllInstructions(Clone, CP); Out->os() << "*** Equivalence classes for: " << Clone->getName() << " ***\n"; CP.printEquivalenceClasses(Out->os()); Out->os() << "*** End of equivalence classes for: " << Clone->getName() << " ***\n"; } } // Perform randomization of the original function FunctionPEA FP(*RNG, M.getContext(), FI, *Graph, &GGPEA, !Clone); DR.instrumentMemoryOperations(*Original, FP, NULL); DR.wrapLibraryFunctions(*Original, FP, FW); replaceWithClones(Original, FI, FP, Graph); // Encrypt main args using the main function's PEA if (Main && Original == Main) { DR.encryptMainArgs(M, FP, FW); } if (Out.get()) { // Add all Instructions before dumping to make the dump more complete. addAllInstructions(Original, FP); Out->os() << "*** Equivalence classes for: " << Original->getName() << " ***\n"; FP.printEquivalenceClasses(Out->os()); Out->os() << "*** End of equivalence classes for: " << Original->getName() << " ***\n"; } } // Replace remaining uses of original functions with clones. replaceOriginalsWithClones(); if (Out.get()) { Out->os() << "*** Equivalence classes for global variables ***\n"; GGPEA.printEquivalenceClasses(Out->os()); Out->os() << "*** End of equivalence classes for global variables ***\n"; Out->keep(); } return true; }