Пример #1
0
/// 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;
}