Example #1
0
//
// Method: getUnsafeAllocsFromABC()
//
// Description:
//  Find all memory objects that are both allocated on the stack and are not
//  proven to be indexed in a type-safe manner according to the static array
//  bounds checking pass.
//
// Notes:
//  This method saves its results be remembering the set of DSNodes which are
//  both on the stack and potentially indexed in a type-unsafe manner.
//
// FIXME:
//  This method only considers unsafe GEP instructions; it does not consider
//  unsafe call instructions or other instructions deemed unsafe by the array
//  bounds checking pass.
//
void
ConvertUnsafeAllocas::getUnsafeAllocsFromABC(Module & M) {
  UnsafeAllocaNodeListBuilder Builder(budsPass, unsafeAllocaNodes);
  Builder.visit(M);
#if 0
  // Haohui: Disable it right now since nobody using the code

  std::map<BasicBlock *,std::set<Instruction*>*> UnsafeGEPMap= abcPass->UnsafeGetElemPtrs;
  std::map<BasicBlock *,std::set<Instruction*>*>::const_iterator bCurrent = UnsafeGEPMap.begin(), bEnd = UnsafeGEPMap.end();
  for (; bCurrent != bEnd; ++bCurrent) {
    std::set<Instruction *> * UnsafeGetElemPtrs = bCurrent->second;
    std::set<Instruction *>::const_iterator iCurrent = UnsafeGetElemPtrs->begin(), iEnd = UnsafeGetElemPtrs->end();
    for (; iCurrent != iEnd; ++iCurrent) {
      if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(*iCurrent)) {
        Value *pointerOperand = GEP->getPointerOperand();
        DSGraph * TDG = budsPass->getDSGraph(*(GEP->getParent()->getParent()));
        DSNode *DSN = TDG->getNodeForValue(pointerOperand).getNode();
        //FIXME DO we really need this ?      markReachableAllocas(DSN);
        if (DSN && DSN->isAllocaNode() && !DSN->isNodeCompletelyFolded()) {
          unsafeAllocaNodes.push_back(DSN);
        }
      } else {
        
        //call instruction add the corresponding    *iCurrent->dump();
        //FIXME     abort();
      }
    }
  }
#endif
}
Example #2
0
void ListaDescritor::imprime()
{
    //DSGRAPH
    DSGraph ds;
    ds.showCPP(this->descritor);
    //DSGRAPH
}
Example #3
0
void Fila::imprime()
{
    //DSGRAPH
    DSGraph ds;
    ds.showCPP(this->inicio, 2, this->inicio, this->fim);
    //DSGRAPH
}
//
// Method: findGlobalPoolNodes()
//
// Description:
//  This method finds DSNodes that are reachable from globals and that need a
//  pool.  The Automatic Pool Allocation transform will use the returned
//  information to build global pools for the DSNodes in question.
//
//  Note that this method does not assign DSNodes to pools; it merely decides
//  which DSNodes are reachable from globals and will need a pool of global
//  scope.
//
// Outputs:
//  Nodes - The DSNodes that are both reachable from globals and which should
//          have global pools will be *added* to this container.
//
void
AllHeapNodesHeuristic::findGlobalPoolNodes (DSNodeSet_t & Nodes) {
  // Get the globals graph for the program.
  DSGraph* GG = Graphs->getGlobalsGraph();

  // Get all of the nodes reachable from globals.
  DenseSet<const DSNode*> GlobalHeapNodes;
  GetNodesReachableFromGlobals (GG, GlobalHeapNodes);
  //
  // Create a global pool for each global DSNode.
  //
  for (DenseSet<const DSNode *>::iterator NI = GlobalHeapNodes.begin();
              NI != GlobalHeapNodes.end();++NI) {
    const DSNode * N = *NI;
    PoolMap[N] = OnePool(N);
  }

  //
  // Now find all DSNodes belonging to function-local DSGraphs which are
  // mirrored in the globals graph.  These DSNodes require a global pool, too.
  //
  for (Module::iterator F = M->begin(); F != M->end(); ++F) {
    if (Graphs->hasDSGraph(*F)) {
      DSGraph* G = Graphs->getDSGraph(*F);
      DSGraph::NodeMapTy NodeMap;
      G->computeGToGGMapping (NodeMap);
      //
      // Scan through all DSNodes in the local graph.  If a local DSNode has a
      // corresponding DSNode in the globals graph that is reachable from a 
      // global, then add the local DSNode to the set of DSNodes reachable from
      // a global.
      //
      DSGraph::node_iterator ni = G->node_begin();
      for (; ni != G->node_end(); ++ni) {
        DSNode * N = ni;
        DSNode * GGN = NodeMap[N].getNode();
        
        //assert (!GGN || GlobalHeapNodes.count (GGN));
        if (GGN && GlobalHeapNodes.count (GGN))
          PoolMap[GGN].NodesInPool.push_back (N);
      }
    }
  }

  //
  // Copy the values into the output container.  Note that DenseSet has no
  // iterator traits (or whatever allows us to treat DenseSet has a generic
  // container), so we have to use a loop to copy values from the DenseSet into
  // the output container.
  //
  for (DenseSet<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
         E = GlobalHeapNodes.end(); I != E; ++I) {
    Nodes.insert (*I);
  }

  return;
}
Example #5
0
 void visitGetElementPtrInst(GetElementPtrInst &GEP) {
   Value *pointerOperand = GEP.getPointerOperand();
   DSGraph * TDG = budsPass->getDSGraph(*(GEP.getParent()->getParent()));
   DSNode *DSN = TDG->getNodeForValue(pointerOperand).getNode();
   //FIXME DO we really need this ?      markReachableAllocas(DSN);
   if (DSN && DSN->isAllocaNode() && !DSN->isNodeCompletelyFolded()) {
     unsafeAllocaNodes.push_back(DSN);
   }
 }
Example #6
0
/**
 * Imprime os elementos da lista com o auxilio da biblioteca DSGraph.
 */
void ListaEncadeada::imprime()
{
   No *p = this->prim;

    //DSGRAPH
    DSGraph ds;
    ds.showCPP(p);
    //DSGRAPH

}
void
PoolRegisterElimination::removeTypeSafeRegistrations (const char * name) {
  //
  // Scan through all uses of the registration function and see if it can be
  // safely removed.  If so, schedule it for removal.
  //
  std::vector<CallInst*> toBeRemoved;
  Function * F = intrinsic->getIntrinsic(name).F;

  //
  // Look for and record all registrations that can be deleted.
  //
  for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
       UI != UE;
       ++UI) {
    //
    // Get the pointer to the registered object.
    //
    CallInst * CI = cast<CallInst>(*UI);
    Value * Ptr = intrinsic->getValuePointer(CI);
    // Lookup the DSNode for the value in the function's DSGraph.
    //
    DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent()));
    DSNodeHandle DSH = TDG->getNodeForValue(Ptr);
    assert ((!(DSH.isNull())) && "No DSNode for Value!\n");

    //
    // If the DSNode is type-safe and is never used as an array, then there
    // will never be a need to look it up in a splay tree, so remove its
    // registration.
    //
    DSNode * N = DSH.getNode();
    if(!N->isArrayNode() && 
       TS->isTypeSafe(Ptr, F)){
      toBeRemoved.push_back(CI);
    }
  }

  //
  // Update the statistics.
  //
  if (toBeRemoved.size()) {
    RemovedRegistration += toBeRemoved.size();
    TypeSafeRegistrations += toBeRemoved.size();
  }

  //
  // Remove the unnecesary registrations.
  //
  std::vector<CallInst*>::iterator it, end;
  for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
    (*it)->eraseFromParent();
  }
}
//
// Method: insertHardDanglingPointers()
//
// Description:
//  Insert dangling pointer dereferences into the code.  This is done by
//  finding instructions that store pointers to memory and free'ing those
//  pointers before the store.  Subsequent loads and uses of the pointer will
//  cause a dangling pointer dereference.
//
// Return value:
//  true  - The module was modified.
//  false - The module was left unmodified.
//
// Notes:
//  This code utilizes DSA to ensure that the pointer can point to heap
//  memory (although the pointer is allowed to alias global and stack memory).
//
bool
FaultInjector::insertHardDanglingPointers (Function & F) {
  //
  // Ensure that we can get analysis information for this function.
  //
  if (!(TDPass->hasDSGraph(F)))
    return false;

  //
  // Scan through each instruction of the function looking for store
  // instructions that store a pointer to memory.  Free the pointer right
  // before the store instruction.
  //
  DSGraph * DSG = TDPass->getDSGraph(F);
  for (Function::iterator fI = F.begin(), fE = F.end(); fI != fE; ++fI) {
    BasicBlock & BB = *fI;
    for (BasicBlock::iterator bI = BB.begin(), bE = BB.end(); bI != bE; ++bI) {
      Instruction * I = bI;

      //
      // Look to see if there is an instruction that stores a pointer to
      // memory.  If so, then free the pointer before the store.
      //
      if (StoreInst * SI = dyn_cast<StoreInst>(I)) {
        if (isa<PointerType>(SI->getOperand(0)->getType())) {
          Value * Pointer = SI->getOperand(0);

          //
          // Check to ensure that the pointer aliases with the heap.  If so, go
          // ahead and add the free.  Note that we may introduce an invalid
          // free, but we're injecting errors, so I think that's okay.
          //
          DSNode * Node = DSG->getNodeForValue(Pointer).getNode();
          if (Node && (Node->isHeapNode())) {
            // Skip if we should not insert a fault.
            if (!doFault()) continue;

            //
            // Print information about where the fault is being inserted.
            //
            printSourceInfo ("Hard dangling pointer", I);

            CallInst::Create (Free, Pointer, "", I);
            ++DPFaults;
          }
        }
      }
    }
  }

  return (DPFaults > 0);
}
// Find the number of arguments we need to add to the functions.
void CSDataRando::findFunctionArgNodes(const std::vector<const Function *> &Functions) {
  std::vector<DSNodeHandle> RootNodes;
  for (const Function *F : Functions) {
    DSGraph *G = DSA->getDSGraph(*F);
    G->getFunctionArgumentsForCall(F, RootNodes);
  }

  // No additional args to pass.
  if (RootNodes.size() == 0) {
    return;
  }

  DenseSet<const DSNode*> MarkedNodes;
  for (DSNodeHandle &NH : RootNodes) {
    if (DSNode *N = NH.getNode()) {
      N->markReachableNodes(MarkedNodes);
    }
  }

  // Remove global nodes from the arg nodes. If we are using the bottom-up
  // analysis then if a node is a global node all contexts will use the global map.
  for (auto i : GlobalNodes) {
    MarkedNodes.erase(i);
  }

  // Remove any nodes that are marked do not encrypt.
  SmallVector<const DSNode*, 8> MarkedNodeWorkList;
  for (auto i : MarkedNodes) {
    if (i->isDoNotEncryptNode()) {
      MarkedNodeWorkList.push_back(i);
    }
  }
  for (auto i : MarkedNodeWorkList) {
    MarkedNodes.erase(i);
  }

  if (MarkedNodes.empty()) {
    return;
  }

  // Create a FuncInfo entry for each of the functions with the arg nodes that
  // need to be passed
  for (const Function *F : Functions) {
    FuncInfo &FI = FunctionInfo[F];
    FI.ArgNodes.insert(FI.ArgNodes.end(), MarkedNodes.begin(), MarkedNodes.end());
  }
}
Example #10
0
/// OptimizeGlobals - This method uses information taken from DSA to optimize
/// global variables.
///
bool DSOpt::OptimizeGlobals(Module &M) {
  DSGraph* GG = TD->getGlobalsGraph();
  const DSGraph::ScalarMapTy &SM = GG->getScalarMap();
  bool Changed = false;

  for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
    if (!I->isDeclaration()) { // Loop over all of the non-external globals...
      // Look up the node corresponding to this global, if it exists.
      DSNode *GNode = 0;
      DSGraph::ScalarMapTy::const_iterator SMI = SM.find(I);
      if (SMI != SM.end()) GNode = SMI->second.getNode();

      if (GNode == 0 && I->hasInternalLinkage()) {
        // If there is no entry in the scalar map for this global, it was never
        // referenced in the program.  If it has internal linkage, that means we
        // can delete it.  We don't ACTUALLY want to delete the global, just
        // remove anything that references the global: later passes will take
        // care of nuking it.
        if (!I->use_empty()) {
          I->replaceAllUsesWith(ConstantPointerNull::get(I->getType()));
          ++NumGlobalsIsolated;
        }
      } else if (GNode && GNode->NodeType.isCompleteNode()) {

        // If the node has not been read or written, and it is not externally
        // visible, kill any references to it so it can be DCE'd.
        if (!GNode->NodeType.isModifiedNode() && !GNode->NodeType.isReadNode() &&I->hasInternalLinkage()){
          if (!I->use_empty()) {
            I->replaceAllUsesWith(ConstantPointerNull::get(I->getType()));
            ++NumGlobalsIsolated;
          }
        }

        // We expect that there will almost always be a node for this global.
        // If there is, and the node doesn't have the M bit set, we can set the
        // 'constant' bit on the global.
        if (!GNode->NodeType.isModifiedNode() && !I->isConstant()) {
          I->setConstant(true);
          ++NumGlobalsConstanted;
          Changed = true;
        }
      }
    }
  return Changed;
}
Example #11
0
void TDDataStructures::ComputePostOrder(const Function* F,
                                        hash_set<DSGraph*> &Visited,
                                        std::vector<DSGraph*> &PostOrder) {
  if (F->isDeclaration()) return;
  DSGraph* G = getOrFetchDSGraph(F);
  if (Visited.count(G)) return;
  Visited.insert(G);

  // Recursively traverse all of the callee graphs.
  for (DSGraph::fc_iterator CI = G->fc_begin(), CE = G->fc_end(); CI != CE; ++CI){
    Instruction *CallI = CI->getCallSite().getInstruction();
    for (calleeTy::iterator I = callee.begin(CallI),
           E = callee.end(CallI); I != E; ++I)
      ComputePostOrder(*I, Visited, PostOrder);
  }

  PostOrder.push_back(G);
}
Example #12
0
//
// Function: GetNodesReachableFromGlobals()
//
// Description:
//  This function finds all DSNodes which are reachable from globals.  It finds
//  DSNodes both within the local DSGraph as well as in the Globals graph that
//  are reachable from globals.
//
// Inputs:
//  G - The Globals Graph.
//
// Outputs:
//  NodesFromGlobals - A reference to a container object in which to record
//                     DSNodes reachable from globals.  DSNodes are *added* to
//                     this container; it is not cleared by this function.
//                     DSNodes from both the local and globals graph are added.
static void
GetNodesReachableFromGlobals (DSGraph* G,
                              DenseSet<const DSNode*> &NodesFromGlobals) {
    //
    // Ensure that G is the globals graph.
    //
    assert (G->getGlobalsGraph() == 0);
    DSGraph * GlobalsGraph = G;

    //
    // Find all DSNodes which are reachable in the globals graph.
    //
    for (DSGraph::node_iterator NI = GlobalsGraph->node_begin();
            NI != GlobalsGraph->node_end();
            ++NI) {
        NI->markReachableNodes(NodesFromGlobals);
    }
}
Example #13
0
/**
* Realiza a busca de um valor na lista e retorna
* o nó com este valor.
* @param valor
*/
void ListaDescritor::busca(int valor)
{
    No *noBusca = NULL;
    if(this->vazia())
    {
        cout<<"Lista se encontra vazia."<<endl;
        exit(1);
    }
    else if(this->descritor->getAnt()->getInfo() == valor)
    {
        noBusca = this->descritor->getAnt(); //primeiro nó da lista
    }
    else if(this->descritor->getProx()->getInfo() == valor)
    {
        noBusca = this->descritor->getProx(); //ultimo nó da lista
    }
    else
    {
        No *l = this->descritor->getAnt(); // primeiro nó da lista
        while(l!= NULL && l->getInfo()!= valor)
        {
            l = l->getProx();
        }
        noBusca = l;
    }

    //DSGRAPH
    DSGraph ds;
    //DSGRAPH
    if(noBusca != NULL)
    {
        //DSGRAPH
        showComment("Valor %d encontrado...", valor);
        ds.showCPP(this->descritor, 1, noBusca);
        //DSGRAPH
    }
    else
    {
        //DSGRAPH
        showComment("Valor %d nao encontrado...", valor);
        ds.showCPP(this->descritor);
        //DSGRAPH
    }
}
// Get all nodes in all function DSGraphs and the global DSGraph that contain
// global values.
void CSDataRando::findGlobalNodes(Module &M) {
  DSGraph *GG = DSA->getGlobalsGraph();
  for (auto i = GG->node_begin(), e = GG->node_end(); i != e; i++) {
    GlobalNodes.insert(&*i);
  }

  for (Function &F : M) {
    if ((!F.isDeclaration()) && DSA->hasDSGraph(F)) {
      DSGraph *G = DSA->getDSGraph(F);
      FuncInfo &FI = FunctionInfo[&F];
      DSGraph::NodeMapTy NodeMap;
      G->computeGToGGMapping(NodeMap);
      for (auto i : NodeMap) {
        GlobalNodes.insert(i.first);
        FI.ToGlobalNodeMap[i.first] = i.second.getNode();
      }
    }
  }
}
Example #15
0
//
// Method: TransformCollapsedAllocas()
//
// Description:
//  Transform all stack allocated objects that are type-unknown
//  (i.e., are completely folded) to heap allocations.
//
void
ConvertUnsafeAllocas::TransformCollapsedAllocas(Module &M) {
  //
  // Need to check if the following is incomplete because we are only looking
  // at scalars.
  //
  // It may be complete because every instruction actually is a scalar in
  // LLVM?!
  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
    if (!MI->isDeclaration()) {
      DSGraph *G = budsPass->getDSGraph(*MI);
      DSGraph::ScalarMapTy &SM = G->getScalarMap();
      for (DSGraph::ScalarMapTy::iterator SMI = SM.begin(), SME = SM.end();
           SMI != SME; ) {
        if (AllocaInst *AI = dyn_cast<AllocaInst>((Value *)(SMI->first))) {
          if (SMI->second.getNode()->isNodeCompletelyFolded()) {
            Value *AllocSize =
            ConstantInt::get(Int32Type,
                              TD->getTypeAllocSize(AI->getAllocatedType()));
            if (AI->isArrayAllocation())
              AllocSize = BinaryOperator::Create(Instruction::Mul, AllocSize,
                                                 AI->getOperand(0), "sizetmp",
                                                 AI);     

            CallInst *CI = CallInst::Create (kmalloc, AllocSize, "", AI);
            Value * MI = castTo (CI, AI->getType(), "", AI);
            InsertFreesAtEnd(CI);
            AI->replaceAllUsesWith(MI);
            SMI->second.getNode()->setHeapMarker();
            SM.erase(SMI++);
            AI->getParent()->getInstList().erase(AI);   
            ++ConvAllocas;
          } else {
            ++SMI;
          }
        } else {
          ++SMI;
        }
      }
    }
  }
}
Example #16
0
//
// Function: processRuntimeCheck()
//
// Description:
//  Modify a run-time check so that its return value has the same DSNode as the
//  checked pointer.
//
// Inputs:
//  M    - The module in which calls to the function live.
//  name - The name of the function for which direct calls should be processed.
//  arg  - The argument index that contains the pointer which the run-time
//         check returns.
//
void
StdLibDataStructures::processRuntimeCheck (Module & M,
                                           std::string name,
                                           unsigned arg) {
  //
  // Get a pointer to the function.
  //
  Function* F = M.getFunction (name);

  //
  // If the function doesn't exist, then there is no work to do.
  //
  if (!F) return;

  //
  // Scan through all direct calls to the function (there should only be direct
  // calls) and process each one.
  //
  for (Value::use_iterator ii = F->use_begin(), ee = F->use_end();
       ii != ee; ++ii) {
    if (CallInst* CI = dyn_cast<CallInst>(*ii)) {
      if (CI->getCalledValue() == F) {
        DSGraph* Graph = getDSGraph(*CI->getParent()->getParent());
        DSNodeHandle & RetNode = Graph->getNodeForValue(CI);
        DSNodeHandle & ArgNode = Graph->getNodeForValue(CI->getArgOperand(arg));
        RetNode.mergeWith(ArgNode);
      }
    }
  }

  //
  // Erase the DSCallSites for this function.  This should prevent other DSA
  // passes from making the DSNodes passed to/returned from the function
  // from becoming Incomplete or External.
  //
  eraseCallsTo (F);
  return;
}
Example #17
0
//
// Function: FoldNodesInDSGraph()
//
// Description:
//  This function will take the specified DSGraph and fold all DSNodes within
//  it that are marked with the heap flag.
//
static void
FoldNodesInDSGraph (DSGraph & Graph) {
  // Worklist of heap nodes to process
  std::vector<DSNodeHandle> HeapNodes;

  //
  // Go find all of the heap nodes.
  //
  DSGraph::node_iterator i;
  DSGraph::node_iterator e = Graph.node_end();
  for (i = Graph.node_begin(); i != e; ++i) {
    DSNode * Node = i;
    if (Node->isHeapNode())
      HeapNodes.push_back (DSNodeHandle(Node));
  }

  //
  // Fold all of the heap nodes; this makes them type-unknown.
  //
  for (unsigned i = 0; i < HeapNodes.size(); ++i)
    HeapNodes[i].getNode()->foldNodeCompletely();
  return;
}
//
// Method: getFunctionTargets()
//
// Description:
//  This method finds all of the potential targets of the specified indirect
//  function call.
//
void
CompleteChecks::getFunctionTargets (CallSite CS,
                                    std::vector<const Function *> & Targets) {
  EQTDDataStructures & dsaPass = getAnalysis<EQTDDataStructures>();
  const DSCallGraph & callgraph = dsaPass.getCallGraph();
  DSGraph* G = dsaPass.getGlobalsGraph();
  DSGraph::ScalarMapTy& SM = G->getScalarMap();

  DSCallGraph::callee_iterator csi = callgraph.callee_begin(CS);
  DSCallGraph::callee_iterator cse = callgraph.callee_end(CS);
  for (; csi != cse; ++csi) {
    const Function *F = *csi;
    DSCallGraph::scc_iterator sccii = callgraph.scc_begin(F),
      sccee = callgraph.scc_end(F);
    for (;sccii != sccee; ++sccii) {
      DSGraph::ScalarMapTy::const_iterator I = 
        SM.find(SM.getLeaderForGlobal(*sccii));
      if (I != SM.end() && !((*sccii)->isDeclaration())) {
        Targets.push_back (*sccii);
      }
    }
  }

  const Function *F1 = CS.getInstruction()->getParent()->getParent();
  F1 = callgraph.sccLeader(&*F1);
  DSCallGraph::scc_iterator sccii = callgraph.scc_begin(F1),
                 sccee = callgraph.scc_end(F1);
  for(;sccii != sccee; ++sccii) {
    DSGraph::ScalarMapTy::const_iterator I = 
      SM.find(SM.getLeaderForGlobal(*sccii));
    if (I != SM.end() && !((*sccii)->isDeclaration())) {
      Targets.push_back (*sccii);
    }
  }

  return;
}
Example #19
0
void TDDataStructures::ComputePostOrder(const Function &F,
                                        DenseSet<DSGraph*> &Visited,
                                        std::vector<DSGraph*> &PostOrder) {
  if (F.isDeclaration()) return;
  DSGraph* G = getOrCreateGraph(&F);
  if (!Visited.insert(G).second) return;

  // Recursively traverse all of the callee graphs.
  svset<const Function*> Callees;

  // Go through all of the callsites in this graph and find all callees
  // Here we're trying to capture all possible callees so that we can ensure
  // each function has all possible callers inlined into it.
  for (DSGraph::fc_iterator CI = G->fc_begin(), E = G->fc_end();
       CI != E; ++CI) {
    // Direct calls are easy, no reason to look at DSCallGraph
    // or anything to do with SCC's
    if (CI->isDirectCall()) {
      ComputePostOrder(*CI->getCalleeFunc(), Visited, PostOrder);
    }
    else {
      // Otherwise, ask the DSCallGraph for the full set of possible
      // callees for this callsite.
      // This includes all members of the SCC's of those callees,
      // and well as others in F's SCC, since we must assume
      // any indirect call might be intra-SCC.
      callgraph.addFullFunctionSet(CI->getCallSite(), Callees);
    }
  }

  for (svset<const Function*>::iterator I = Callees.begin(),
       E = Callees.end(); I != E; ++I)
    ComputePostOrder(**I, Visited, PostOrder);

  PostOrder.push_back(G);
}
//
// Method: getDSNodeHandle()
//
// Description:
//  This method looks up the DSNodeHandle for a given LLVM value.  The context
//  of the value is the specified function, although if it is a global value,
//  the DSNodeHandle may exist within the global DSGraph.
//
// Return value:
//  A DSNodeHandle for the value is returned.  This DSNodeHandle could either
//  be in the function's DSGraph or from the GlobalsGraph.  Note that the
//  DSNodeHandle may represent a NULL DSNode.
//
DSNodeHandle
CompleteChecks::getDSNodeHandle (const Value * V, const Function * F) {
  //
  // Get access to the points-to results.
  //
  EQTDDataStructures & dsaPass = getAnalysis<EQTDDataStructures>();

  //
  // Ensure that the function has a DSGraph
  //
  assert (dsaPass.hasDSGraph(*F) && "No DSGraph for function!\n");

  //
  // Lookup the DSNode for the value in the function's DSGraph.
  //
  DSGraph * TDG = dsaPass.getDSGraph(*F);
  DSNodeHandle DSH = TDG->getNodeForValue(V);

  //
  // If the value wasn't found in the function's DSGraph, then maybe we can
  // find the value in the globals graph.
  //
  if ((DSH.isNull()) && (isa<GlobalValue>(V))) {
    //
    // Try looking up this DSNode value in the globals graph.  Note that
    // globals are put into equivalence classes; we may need to first find the
    // equivalence class to which our global belongs, find the global that
    // represents all globals in that equivalence class, and then look up the
    // DSNode Handle for *that* global.
    //
    DSGraph * GlobalsGraph = TDG->getGlobalsGraph ();
    DSH = GlobalsGraph->getNodeForValue(V);
    if (DSH.isNull()) {
      //
      // DSA does not currently handle global aliases.
      //
      if (!isa<GlobalAlias>(V)) {
        //
        // We have to dig into the globalEC of the DSGraph to find the DSNode.
        //
        const GlobalValue * GV = dyn_cast<GlobalValue>(V);
        const GlobalValue * Leader;
        Leader = GlobalsGraph->getGlobalECs().getLeaderValue(GV);
        DSH = GlobalsGraph->getNodeForValue(Leader);
      }
    }
  }

  return DSH;
}
Example #21
0
//
// Method: getLocalPoolNodes()
//
// Description:
//  For a given function, determine which DSNodes for that function should have
//  local pools created for them.
//
void
Heuristic::getLocalPoolNodes (const Function & F, DSNodeList_t & Nodes) {
  //
  // Get the DSGraph of the specified function.  If the DSGraph has no nodes,
  // then there is nothing we need to do.
  //
  DSGraph* G = Graphs->getDSGraph(F);
  if (G->node_begin() == G->node_end()) return;

  //
  // Calculate which DSNodes are reachable from globals.  If a node is reachable
  // from a global, we will create a global pool for it, so no argument passage
  // is required.
  Graphs->getGlobalsGraph();

  // Map all node reachable from this global to the corresponding nodes in
  // the globals graph.
  DSGraph::NodeMapTy GlobalsGraphNodeMapping;
  G->computeGToGGMapping(GlobalsGraphNodeMapping);

  //
  // Loop over all of the nodes which are non-escaping, adding pool-allocatable
  // ones to the NodesToPA vector.  In other words, scan over the DSGraph and
  // find nodes for which a new pool must be created within this function.
  //
  for (DSGraph::node_iterator I = G->node_begin(), E = G->node_end();
       I != E;
       ++I){
    // Get the DSNode and, if applicable, its mirror in the globals graph
    DSNode * N   = I;
    DSNode * GGN = GlobalsGraphNodeMapping[N].getNode();

    //
    // Only the following nodes are pool allocated:
    //  1) Local Heap nodes
    //  2) Nodes which are mirrored in the globals graph and, in the globals
    //     graph, are heap nodes.
    //
    if ((N->isHeapNode()) || (GGN && GGN->isHeapNode())) {
      if (!(GlobalPoolNodes.count (N) || GlobalPoolNodes.count (GGN))) {
        // Otherwise, if it was not passed in from outside the function, it must
        // be a local pool!
        assert((!N->isGlobalNode() || N->isPtrToIntNode()) && "Should be in global mapping!");
        if(!N->isPtrToIntNode()) {
          Nodes.push_back (N);
        }
      }
    }
  }

  return;
}
Example #22
0
void BUDataStructures::CloneAuxIntoGlobal(DSGraph* G) {
  DSGraph* GG = G->getGlobalsGraph();
  ReachabilityCloner RC(GG, G, 0);

  for(DSGraph::afc_iterator ii = G->afc_begin(), ee = G->afc_end();
      ii != ee; ++ii) {
    //cerr << "Pushing " << ii->getCallSite().getInstruction()->getOperand(0) << "\n";
    //If we can, merge with an existing call site for this instruction
    if (GG->hasNodeForValue(ii->getCallSite().getInstruction()->getOperand(0))) {
      DSGraph::afc_iterator GGii;
      for(GGii = GG->afc_begin(); GGii != GG->afc_end(); ++GGii)
        if (GGii->getCallSite().getInstruction()->getOperand(0) ==
            ii->getCallSite().getInstruction()->getOperand(0))
          break;
      if (GGii != GG->afc_end())
        RC.cloneCallSite(*ii).mergeWith(*GGii);
      else
        GG->addAuxFunctionCall(RC.cloneCallSite(*ii));
    } else {
      GG->addAuxFunctionCall(RC.cloneCallSite(*ii));
    }
  }
}
Example #23
0
 void initialize(const Module *M, const DataStructures *DS) {
   parseValue(M);
   assert(V && "Failed to parse value?");
   if (isa<GlobalValue>(V)) {
     DSGraph *G = DS->getGlobalsGraph();
     assert(G->hasNodeForValue(V) && "Node not in specified graph!");
     NH = G->getNodeForValue(V);
   } else {
     assert(F && "No function?");
     DSGraph *G = DS->getDSGraph(*F);
     assert(G->hasNodeForValue(V) && "Node not in specified graph!");
     NH = G->getNodeForValue(V);
   }
   // Handle offsets, if any
   // For each offset in the offsets vector, follow the link at that offset
   for (OffsetVectorTy::const_iterator I = offsets.begin(), E = offsets.end();
       I != E; ++I ) {
     assert(!NH.isNull() && "Null NodeHandle?");
     assert(NH.hasLink(*I) && "Handle doesn't have link?");
     // Follow the offset
     NH = NH.getLink(*I);
   }
 }
Example #24
0
// run - Calculate the top down data structure graphs for each function in the
// program.
//
bool TDDataStructures::runOnModule(Module &M) {

  init(useEQBU ? &getAnalysis<EquivBUDataStructures>()
       : &getAnalysis<BUDataStructures>(),
       true, true, true, false);
  // Figure out which functions must not mark their arguments complete because
  // they are accessible outside this compilation unit.  Currently, these
  // arguments are functions which are reachable by incomplete or external
  // nodes in the globals graph.
  const DSScalarMap &GGSM = GlobalsGraph->getScalarMap();
  DenseSet<DSNode*> Visited;
  for (DSScalarMap::global_iterator I=GGSM.global_begin(), E=GGSM.global_end();
       I != E; ++I) {
    DSNode *N = GGSM.find(*I)->second.getNode();
    if (N->isIncompleteNode() || N->isExternalNode())
      markReachableFunctionsExternallyAccessible(N, Visited);
  }

  // Loop over unresolved call nodes.  Any functions passed into (but not
  // returned!) from unresolvable call nodes may be invoked outside of the
  // current module.
  for (DSGraph::afc_iterator I = GlobalsGraph->afc_begin(),
         E = GlobalsGraph->afc_end(); I != E; ++I)
    for (unsigned arg = 0, e = I->getNumPtrArgs(); arg != e; ++arg)
      markReachableFunctionsExternallyAccessible(I->getPtrArg(arg).getNode(),
                                                 Visited);
  Visited.clear();

  // Clear Aux of Globals Graph to be refilled in later by post-TD unresolved
  // functions
  GlobalsGraph->getAuxFunctionCalls().clear();

  // Functions without internal linkage are definitely externally callable!
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() && !I->hasInternalLinkage() && !I->hasPrivateLinkage())
      ExternallyCallable.insert(I);

  // Debug code to print the functions that are externally callable
#if 0
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (ExternallyCallable.count(I)) {
      errs() << "ExternallyCallable: " << I->getNameStr() << "\n";
    }
#endif

  // We want to traverse the call graph in reverse post-order.  To do this, we
  // calculate a post-order traversal, then reverse it.
  DenseSet<DSGraph*> VisitedGraph;
  std::vector<DSGraph*> PostOrder;

{TIME_REGION(XXX, "td:Compute postorder");

  // Calculate top-down from main...
  if (Function *F = M.getFunction("main"))
    ComputePostOrder(*F, VisitedGraph, PostOrder);

  // Next calculate the graphs for each unreachable function...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration())
      ComputePostOrder(*I, VisitedGraph, PostOrder);

  VisitedGraph.clear();   // Release memory!
}

{TIME_REGION(XXX, "td:Inline stuff");

  // Visit each of the graphs in reverse post-order now!
  while (!PostOrder.empty()) {
    InlineCallersIntoGraph(PostOrder.back());
    PostOrder.pop_back();
  }
}

  // Free the IndCallMap.
  while (!IndCallMap.empty()) {
    delete IndCallMap.begin()->second;
    IndCallMap.erase(IndCallMap.begin());
  }

  formGlobalECs();

  ExternallyCallable.clear();
  GlobalsGraph->removeTriviallyDeadNodes();
  GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
  GlobalsGraph->computeIntPtrFlags();

  // Make sure each graph has updated external information about globals
  // in the globals graph.
  VisitedGraph.clear();
  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
    if (!(F->isDeclaration())){
      DSGraph *Graph  = getOrCreateGraph(F);
      if (!VisitedGraph.insert(Graph).second) continue;

      cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes |
                        DSGraph::DontCloneAuxCallNodes);

      Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
      Graph->computeIntPtrFlags();
      // Clean up uninteresting nodes
      Graph->removeDeadNodes(0);

    }
  }

  // CBU contains the correct call graph.
  // Restore it, so that subsequent passes and clients can get it.
  restoreCorrectCallGraph();

  /// Added by Zhiyuan: print out the DSGraph.
  if (llvm::DebugFlag) {
    print(errs(), &M);
  }
  return false;
}
Example #25
0
/// InlineCallersIntoGraph - Inline all of the callers of the specified DS graph
/// into it, then recompute completeness of nodes in the resultant graph.
void TDDataStructures::InlineCallersIntoGraph(DSGraph* DSG) {
  // Inline caller graphs into this graph.  First step, get the list of call
  // sites that call into this graph.
  std::vector<CallerCallEdge> EdgesFromCaller;
  std::map<DSGraph*, std::vector<CallerCallEdge> >::iterator
    CEI = CallerEdges.find(DSG);
  if (CEI != CallerEdges.end()) {
    std::swap(CEI->second, EdgesFromCaller);
    CallerEdges.erase(CEI);
  }

  // Sort the caller sites to provide a by-caller-graph ordering.
  std::sort(EdgesFromCaller.begin(), EdgesFromCaller.end());


  // Merge information from the globals graph into this graph.  FIXME: This is
  // stupid.  Instead of us cloning information from the GG into this graph,
  // then having RemoveDeadNodes clone it back, we should do all of this as a
  // post-pass over all of the graphs.  We need to take cloning out of
  // removeDeadNodes and gut removeDeadNodes at the same time first though. :(
  cloneGlobalsInto(DSG, DSGraph::DontCloneCallNodes |
                        DSGraph::DontCloneAuxCallNodes);

  DEBUG(errs() << "[TD] Inlining callers into '"
        << DSG->getFunctionNames() << "'\n");

  DSG->maskIncompleteMarkers();
  // Iteratively inline caller graphs into this graph.
  while (!EdgesFromCaller.empty()) {
    DSGraph* CallerGraph = EdgesFromCaller.back().CallerGraph;

    // Iterate through all of the call sites of this graph, cloning and merging
    // any nodes required by the call.
    ReachabilityCloner RC(DSG, CallerGraph,
                          DSGraph::DontCloneCallNodes |
                          DSGraph::DontCloneAuxCallNodes);

    // Inline all call sites from this caller graph.
    do {
      const DSCallSite &CS = *EdgesFromCaller.back().CS;
      const Function &CF = *EdgesFromCaller.back().CalledFunction;
      DEBUG(errs() << "   [TD] Inlining graph into Fn '"
            << CF.getName().str() << "' from ");
      if (CallerGraph->getReturnNodes().empty()) {
        DEBUG(errs() << "SYNTHESIZED INDIRECT GRAPH");
      } else {
        DEBUG(errs() << "Fn '" << CS.getCallSite().getInstruction()->
              getParent()->getParent()->getName().str() << "'");
      }
      DEBUG(errs() << ": " << CF.getFunctionType()->getNumParams()
            << " args\n");

      // Get the formal argument and return nodes for the called function and
      // merge them with the cloned subgraph.
      DSCallSite T1 = DSG->getCallSiteForArguments(CF);
      RC.mergeCallSite(T1, CS);
      ++NumTDInlines;

      EdgesFromCaller.pop_back();
    } while (!EdgesFromCaller.empty() &&
             EdgesFromCaller.back().CallerGraph == CallerGraph);
  }



  // Next, now that this graph is finalized, we need to recompute the
  // incompleteness markers for this graph and remove unreachable nodes.

  // If any of the functions is externally callable, treat everything in its
  // SCC as externally callable.
  bool isExternallyCallable = false;
  for (DSGraph::retnodes_iterator I = DSG->retnodes_begin(),
         E = DSG->retnodes_end(); I != E; ++I)
    if (ExternallyCallable.count(I->first)) {
      isExternallyCallable = true;
      break;
    }

  // Recompute the Incomplete markers.  Depends on whether args are complete
  unsigned IncFlags = DSGraph::IgnoreFormalArgs;
  IncFlags |= DSGraph::IgnoreGlobals | DSGraph::MarkVAStart;
  DSG->markIncompleteNodes(IncFlags);

  // If this graph contains functions that are externally callable, now is the time to mark
  // their arguments and return values as external.  At this point TD is inlining all caller information,
  // and that means External callers too.
  unsigned ExtFlags
    = isExternallyCallable ? DSGraph::MarkFormalsExternal : DSGraph::DontMarkFormalsExternal;
  DSG->computeExternalFlags(ExtFlags);
  DSG->computeIntPtrFlags();

  cloneIntoGlobals(DSG, DSGraph::DontCloneCallNodes |
                        DSGraph::DontCloneAuxCallNodes);
  //
  // Delete dead nodes.  Treat globals that are unreachable as dead also.
  //
  // FIXME:
  //  Do not delete unreachable globals as the comment describes.  For its
  //  alignment checks on the results of load instructions, SAFECode must be
  //  able to find the DSNode of both the result of the load as well as the
  //  pointer dereferenced by the load.  If we remove unreachable globals, then
  //  if the dereferenced pointer is a global, its DSNode will not reachable
  //  from the local graph's scalar map, and chaos ensues.
  //
  //  So, for now, just remove dead nodes but leave the globals alone.
  //
  DSG->removeDeadNodes(0);

  // We are done with computing the current TD Graph!  Finally, before we can
  // finish processing this function, we figure out which functions it calls and
  // records these call graph edges, so that we have them when we process the
  // callee graphs.
  if (DSG->fc_begin() == DSG->fc_end()) return;

  // Loop over all the call sites and all the callees at each call site, and add
  // edges to the CallerEdges structure for each callee.
  for (DSGraph::fc_iterator CI = DSG->fc_begin(), E = DSG->fc_end();
       CI != E; ++CI) {

    // Handle direct calls efficiently.
    if (CI->isDirectCall()) {
      if (!CI->getCalleeFunc()->isDeclaration() &&
          !DSG->getReturnNodes().count(CI->getCalleeFunc()))
        CallerEdges[getOrCreateGraph(CI->getCalleeFunc())]
          .push_back(CallerCallEdge(DSG, &*CI, CI->getCalleeFunc()));
      continue;
    }

    svset<const Function*> AllCallees;
    std::vector<const Function*> Callees;

    // Get the list of callees
    callgraph.addFullFunctionSet(CI->getCallSite(), AllCallees);

    // Filter all non-declarations, and calls within this DSGraph
    for (svset<const Function*>::iterator I = AllCallees.begin(),
        E = AllCallees.end(); I != E; ++I) {
      const Function *F = *I;
      if (!F->isDeclaration() && getDSGraph(**I) != DSG)
        Callees.push_back(F);
    }
    AllCallees.clear();

    // If there is exactly one callee from this call site, remember the edge in
    // CallerEdges.
    if (Callees.size() == 1) {
      const Function * Callee = Callees[0];
      CallerEdges[getOrCreateGraph(Callee)]
          .push_back(CallerCallEdge(DSG, &*CI, Callee));
    }
    if (Callees.size() <= 1) continue;

    // Otherwise, there are multiple callees from this call site, so it must be
    // an indirect call.  Chances are that there will be other call sites with
    // this set of targets.  If so, we don't want to do M*N inlining operations,
    // so we build up a new, private, graph that represents the calls of all
    // calls to this set of functions.

    std::map<std::vector<const Function*>, DSGraph*>::iterator IndCallRecI =
      IndCallMap.lower_bound(Callees);

    // If we already have this graph, recycle it.
    if (IndCallRecI != IndCallMap.end() && IndCallRecI->first == Callees) {
      DEBUG(errs() << "  [TD] *** Reuse of indcall graph for " << Callees.size()
            << " callees!\n");
      DSGraph * IndCallGraph = IndCallRecI->second;
      assert(IndCallGraph->getFunctionCalls().size() == 1);

      // Merge the call into the CS already in the IndCallGraph
      ReachabilityCloner RC(IndCallGraph, DSG, 0);
      RC.mergeCallSite(IndCallGraph->getFunctionCalls().front(), *CI);
    } else {
      // Otherwise, create a new DSGraph to represent this.
      DSGraph* IndCallGraph = new DSGraph(DSG->getGlobalECs(),
                                          DSG->getDataLayout(), *TypeSS);

      // Clone over the call into the new DSGraph
      ReachabilityCloner RC(IndCallGraph, DSG, 0);
      DSCallSite ClonedCS = RC.cloneCallSite(*CI);

      // Add the cloned CS to the graph, as if it were an original call.
      IndCallGraph->getFunctionCalls().push_back(ClonedCS);

      // Save this graph for use later, should we need it.
      IndCallRecI = IndCallMap.insert(IndCallRecI,
                                      std::make_pair(Callees, IndCallGraph));

      // Additionally, make sure that each of the callees inlines this graph
      // exactly once.
      DSCallSite *NCS = &IndCallGraph->getFunctionCalls().front();
      for (unsigned i = 0, e = Callees.size(); i != e; ++i) {
        DSGraph* CalleeGraph = getDSGraph(*Callees[i]);
        if (CalleeGraph != DSG)
          CallerEdges[CalleeGraph].push_back(CallerCallEdge(IndCallGraph, NCS,
                                                            Callees[i]));
      }
    }
  }
}
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;
}
Example #27
0
AliasAnalysis::AliasResult DSAAA::alias(const AliasAnalysis::Location& l1, const AliasAnalysis::Location& l2)
{
    DSAAA_TOTAL_ANSWER++;
	if (l1.Size == 0 || l2.Size == 0)
		return NoAlias;
    /// ? Zhiyuan: weired, l1 & l2's locations are both instructions, in my opinion, they should be operands
	const Value* v1 = (l1.Ptr)->stripPointerCasts();
	const Value* v2 = (l2.Ptr)->stripPointerCasts();


	if (!v1->getType()->isPointerTy() || !v2->getType()->isPointerTy())
		return NoAlias;

	if (v1 == v2) return MustAlias;

    DSGraph *G1 = getGraphForValue(v1);
    DSGraph *G2 = getGraphForValue(v2);
    assert((!G1 || !G2 || G1 == G2) && "Alias query for 2 different functions?");

    const Function *func = nullptr;
    /// Zhiyuan: Debug
    if (const Instruction *I = dyn_cast<Instruction>(v1)) {
        func = I->getParent()->getParent();
    }  else if (const Argument *A = dyn_cast<Argument>(v1)) {
        func = A->getParent();
    }  else if (const BasicBlock *BB = dyn_cast<BasicBlock>(v1)) {
        func = BB->getParent();
    }
    if (func != nullptr) {
        //errs() << "[DSAAA Debug] We are in function [" << func->getName() << "].\n";
        DEBUG_QueryFunctionSet.insert(func->getName().str());
    }
    DSAAA_TOTAL_QUERY_FUNCTIONS = DEBUG_QueryFunctionSet.size();
    // Get the graph to use...
    DSGraph* G = G1 ? G1 : (G2 ? G2 : TD->getGlobalsGraph());

    const DSGraph::ScalarMapTy &GSM = G->getScalarMap();
    DSGraph::ScalarMapTy::const_iterator I = GSM.find((Value*)v1);
    if (I == GSM.end()) return NoAlias;
    DSGraph::ScalarMapTy::const_iterator J = GSM.find((Value*)v2);
    if (J == GSM.end()) return NoAlias;

    DSNode  *N1 = I->second.getNode(),  *N2 = J->second.getNode();
    unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();
    if (N1 == nullptr || N2 == nullptr) {
        // Can't tell whether anything aliases null.
        errs() << "[DSAAA DEBUG] nullptr for this value. \n";
        return AliasAnalysis::alias(l1, l2);
    }

    if (!N1->isCompleteNode() && !N2->isCompleteNode()) {
//        if (llvm::DebugFlag) {
//            errs() << "We calculate MayAlias here.\n";
//            errs() << "v1 = " << *(l1.Ptr) << "; v2 = " << *(l2.Ptr) << "\n";
//            errs() << "N1 = " << N1 << "; N2 = " << N2 << "\n";
//            errs() << "N1 complete? " << N1->isCompleteNode() << "; N2 complete? " << N2->isCompleteNode() << "\n";
//        }
        if (N1 == N2) {
            DSAAA_INCOMPLETE_SAME_NODE++;
        }
        DSAAA_INCOMPLETE_NODE++;
        DEBUG_IncompleteNodeSet.insert(N1);
        DSAAA_INCOMPLETE_NODE_COUNT = DEBUG_IncompleteNodeSet.size();
        if ( llvm::DebugFlag && func != nullptr && func->getName().str() == "BZ2_decompress") {
            errs() << "[DSAAA DEBUG] # of referrers: " << N1->getNumReferrers() << "\n";
//            errs() << "[DSAAA DEBUG] # of links: " << N1->getLinkCount() << "\n";
            N1->print(errs(), G);
            const DSScalarMap &SM = G->getScalarMap();
            int refCount = 1;
            for (DSScalarMap::const_iterator i = SM.begin(); i != SM.end(); i++) {
                if (i->second.getNode() == N1 && refCount < 240) {
                    errs() << refCount++ <<": " << *(i->first) << "\n";
                }
            }
            //exit(0);
        }
        return AliasAnalysis::alias(l1, l2);
    }

    // We can only make a judgment if one of the nodes is complete.
    if (N1->isCompleteNode() || N2->isCompleteNode()) {
        if (N1 != N2) return NoAlias;   // Completely different nodes.

        // See if they point to different offsets...  if so, we may be able to
        // determine that they do not alias...
        if (O1 != O2) {
            uint64_t V1Size = l1.Size;
            uint64_t V2Size = l2.Size;
            if (O2 < O1) {    // Ensure that O1 <= O2
                std::swap(v1, v2);
                std::swap(O1, O2);
                std::swap(V1Size, V2Size);
            }

            if (O1+V1Size <= O2) return NoAlias;
        }
    }

  /**
   * Below added by Zhiyuan
   */
//    if (N1 == N2 && N1->isCompleteNode() && N2->isCompleteNode()) return MustAlias;

//    if (llvm::DebugFlag) {
//        errs() << "We need to consult other alias analysis for better results.\n";
//        errs() << "v1 = " << *(l1.Ptr) << "; v2 = " << *(l2.Ptr) << "\n";
//        errs() << "N1 = " << N1 << "; N2 = " << N2 << "\n";
//        errs() << "N1 complete? " << N1->isCompleteNode() << "; N2 complete? " << N2->isCompleteNode() << "\n";
//    }
  /**
   * Above added by Zhiyuan
   */
   DSAAA_CANNOT_ANSWER++;

  // FIXME: we could improve on this by checking the globals graph for aliased
  // global queries...
    return AliasAnalysis::alias(l1, l2);
}
void
PoolRegisterElimination::removeSingletonRegistrations (const char * name) {
  //
  // Scan through all uses of the registration function and see if it can be
  // safely removed.  If so, schedule it for removal.
  //
  std::vector<CallInst*> toBeRemoved;
  Function * F = intrinsic->getIntrinsic(name).F;

  //
  // Look for and record all registrations that can be deleted.
  //
  for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
       UI != UE;
       ++UI) {
    //
    // Get the pointer to the registered object.
    //
    CallInst * CI = cast<CallInst>(*UI);
    Value * Ptr = intrinsic->getValuePointer(CI);

    //
    // Lookup the DSNode for the value in the function's DSGraph.
    //
    DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent()));
    DSNodeHandle DSH = TDG->getNodeForValue(Ptr);
    assert ((!(DSH.isNull())) && "No DSNode for Value!\n");

    //
    // If the object being registered is the same size as that found in the
    // DSNode, then we know it's a singleton object.  The run-time doesn't need
    // such objects registered in the splay trees, so we can remove the
    // registration function.
    //
    DSNode * N = DSH.getNode();
    Value * Size = intrinsic->getObjectSize (Ptr->stripPointerCasts());
    if (Size) {
      if (ConstantInt * C = dyn_cast<ConstantInt>(Size)) {
        unsigned long size = C->getZExtValue();
        if (size == N->getSize()) {
          toBeRemoved.push_back(CI);
          continue;
        }
      }
    }
  }

  //
  // Update the statistics.
  //
  if (toBeRemoved.size()) {
    RemovedRegistration += toBeRemoved.size();
    SingletonRegistrations += toBeRemoved.size();
  }

  //
  // Remove the unnecesary registrations.
  //
  std::vector<CallInst*>::iterator it, end;
  for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
    (*it)->eraseFromParent();
  }
}
//
// Method: visitCallSite()
//
// Description:
//  This method transforms a call site.  A call site may either be a call
//  instruction or an invoke instruction.
//
// Inputs:
//  CS - The call site representing the instruction that should be transformed.
//
void FuncTransform::visitCallSite(CallSite& CS) {
  const Function *CF = CS.getCalledFunction();
  Instruction *TheCall = CS.getInstruction();
  bool thread_creation_point = false;

  //
  // Get the value that is called at this call site.  Strip away any pointer
  // casts that do not change the representation of the data (i.e., are
  // lossless casts).
  //
  Value * CalledValue = CS.getCalledValue()->stripPointerCasts();

  //
  // The CallSite::getCalledFunction() method is not guaranteed to strip off
  // pointer casts.  If no called function was found, manually strip pointer
  // casts off of the called value and see if we get a function.  If so, this
  // is a direct call, and we want to update CF accordingly.
  //
  if (!CF) CF = dyn_cast<Function>(CalledValue);

  //
  // Do not change any inline assembly code.
  //
  if (isa<InlineAsm>(TheCall->getOperand(0))) {
    errs() << "INLINE ASM: ignoring.  Hoping that's safe.\n";
    return;
  }

  //
  // Ignore calls to NULL pointers or undefined values.
  //
  if ((isa<ConstantPointerNull>(CalledValue)) ||
      (isa<UndefValue>(CalledValue))) {
    errs() << "WARNING: Ignoring call using NULL/Undef function pointer.\n";
    return;
  }

  // If this function is one of the memory manipulating functions built into
  // libc, emulate it with pool calls as appropriate.
  if (CF && CF->isDeclaration()) {
    std::string Name = CF->getName();

    if (Name == "free" || Name == "cfree") {
      visitFreeCall(CS);
      return;
    } else if (Name == "malloc") {
      visitMallocCall(CS);
      return;
    } else if (Name == "calloc") {
      visitCallocCall(CS);
      return;
    } else if (Name == "realloc") {
      visitReallocCall(CS);
      return;
    } else if (Name == "memalign" || Name == "posix_memalign") {
      visitMemAlignCall(CS);
      return;
    } else if (Name == "strdup") {
      visitStrdupCall(CS);
      return;
    } else if (Name == "valloc") {
      errs() << "VALLOC USED BUT NOT HANDLED!\n";
      abort();
    } else if (unsigned PoolArgc = PAInfo.getNumInitialPoolArguments(Name)) {
      visitRuntimeCheck(CS, PoolArgc);
      return;
    } else if (Name == "pthread_create") {
      thread_creation_point = true;

      //
      // Get DSNode representing the DSNode of the function pointer Value of
      // the pthread_create call
      //
      DSNode* thread_callee_node = G->getNodeForValue(CS.getArgument(2)).getNode();
      if (!thread_callee_node) {
    	  assert(0 && "apparently you need this code");
    	  FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
    	  thread_callee_node = G->getNodeForValue(CFI->MapValueToOriginal(CS.getArgument(2))).getNode();
      }

      // Fill in CF with the name of one of the functions in thread_callee_node
      CF = const_cast<Function*>(dyn_cast<Function>(*thread_callee_node->globals_begin()));
    }
  }

  //
  // We need to figure out which local pool descriptors correspond to the pool
  // descriptor arguments passed into the function call.  Calculate a mapping
  // from callee DSNodes to caller DSNodes.  We construct a partial isomophism
  // between the graphs to figure out which pool descriptors need to be passed
  // in.  The roots of this mapping is found from arguments and return values.
  //
  DataStructures& Graphs = PAInfo.getGraphs();
  DSGraph::NodeMapTy NodeMapping;
  Instruction *NewCall;
  Value *NewCallee;
  std::vector<const DSNode*> ArgNodes;
  DSGraph *CalleeGraph;  // The callee graph

  // For indirect callees, find any callee since all DS graphs have been
  // merged.
  if (CF) {   // Direct calls are nice and simple.
    DEBUG(errs() << "  Handling direct call: " << *TheCall << "\n");

    //
    // Do not try to add pool handles to the function if it:
    //  a) Already calls a cloned function; or
    //  b) Calls a function which was never cloned.
    //
    // For such a call, just replace any arguments that take original functions
    // with their cloned function poiner values.
    //
    FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
    if (CFI == 0 || CFI->Clone == 0) {   // Nothing to transform...
      visitInstruction(*TheCall);
      return;
    }

    //
    // Oh, dear.  We must add pool descriptors to this direct call.
    //
    NewCallee = CFI->Clone;
    ArgNodes = CFI->ArgNodes;
    
    assert ((Graphs.hasDSGraph (*CF)) && "Function has no ECGraph!\n");
    CalleeGraph = Graphs.getDSGraph(*CF);
  } else {
    DEBUG(errs() << "  Handling indirect call: " << *TheCall << "\n");
    DSGraph *G =  Graphs.getGlobalsGraph();
    DSGraph::ScalarMapTy& SM = G->getScalarMap();

    // Here we fill in CF with one of the possible called functions.  Because we
    // merged together all of the arguments to all of the functions in the
    // equivalence set, it doesn't really matter which one we pick.
    // (If the function was cloned, we have to map the cloned call instruction
    // in CS back to the original call instruction.)
    Instruction *OrigInst =
      cast<Instruction>(getOldValueIfAvailable(CS.getInstruction()));

    //
    // Attempt to get one of the function targets of this indirect call site by
    // looking at the call graph constructed by the points-to analysis.  Be
    // sure to use the original call site from the original function; the
    // points-to analysis has no information on the clones we've created.
    //
    // Also, look for the target that has the greatest number of arguments that
    // have associated DSNodes.  This ensures that we pass the maximum number
    // of pools possible and prevents us from eliding a pool because we're
    // examining a target that doesn't need it.
    //
    const DSCallGraph & callGraph = Graphs.getCallGraph();

    DSCallGraph::callee_iterator I = callGraph.callee_begin(OrigInst);
    for (; I != callGraph.callee_end(OrigInst); ++I) {
      for(DSCallGraph::scc_iterator sccii = callGraph.scc_begin(*I),
                           sccee = callGraph.scc_end(*I); sccii != sccee; ++sccii){
        if(SM.find(SM.getLeaderForGlobal(*sccii)) == SM.end())
          continue;
        //
        // Get the information for this function.  Since this is coming from
        // DSA, it should be an original function.
        //
        // This call site calls a function, that is not defined in this module
        if (!(Graphs.hasDSGraph(**sccii))) return;

        // For all other cases Func Info must exist.
        PAInfo.getFuncInfo(**sccii);

        //
        // If this target takes more DSNodes than the last one we found, then
        // make *this* target our canonical target.
        //
        CF = *sccii;
        break;
      }
    }
    if(!CF){
    const Function *F1 = OrigInst->getParent()->getParent();
    F1 = callGraph.sccLeader(&*F1);

    for(DSCallGraph::scc_iterator sccii = callGraph.scc_begin(F1),
                           sccee = callGraph.scc_end(F1); sccii != sccee; ++sccii){
        if(SM.find(SM.getLeaderForGlobal(*sccii)) == SM.end())
          continue;
        //
        // Get the information for this function.  Since this is coming from DSA,
        // it should be an original function.
        //
        // This call site calls a function, that is not defined in this module
        if (!(Graphs.hasDSGraph(**sccii))) return;
        // For all other cases Func Info must exist.
        PAInfo.getFuncInfo(**sccii);

        //
        // If this target takes more DSNodes than the last one we found, then
        // make *this* target our canonical target.
        //
        CF = *sccii;
      }
    }
    
    // Assuming the call graph is always correct. And if the call graph reports,
    // no callees, we can assume that it is right.
    //
    // If we didn't find the callee in the constructed call graph, try
    // checking in the DSNode itself.
    // This isn't ideal as it means that this call site didn't have inlining
    // happen.
    //

    //
    // If we still haven't been able to find a target function of the call site
    // to transform, do nothing.
    //
    // One may be tempted to think that we should always have at least one
    // target, but this is not true.  There are perfectly acceptable (but
    // strange) programs for which no function targets exist.  Function
    // pointers loaded from undef values, for example, will have no targets.
    //
    if (!CF) return;

    //
    // It's possible that this program has indirect call targets that are
    // not defined in this module.  Do not transformation for such functions.
    //
    if (!(Graphs.hasDSGraph(*CF))) return;

    //
    // Get the common graph for the set of functions this call may invoke.
    //
    assert ((Graphs.hasDSGraph(*CF)) && "Function has no DSGraph!\n");
    CalleeGraph = Graphs.getDSGraph(*CF);

#ifndef NDEBUG
    // Verify that all potential callees at call site have the same DS graph.
    DSCallGraph::callee_iterator E = Graphs.getCallGraph().callee_end(OrigInst);
    for (; I != E; ++I) {
      const Function * F = *I;
      assert (F);
      if (!(F)->isDeclaration())
        assert(CalleeGraph == Graphs.getDSGraph(**I) &&
               "Callees at call site do not have a common graph!");
    }
#endif    

    // Find the DS nodes for the arguments that need to be added, if any.
    FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
    assert(CFI && "No function info for callee at indirect call?");
    ArgNodes = CFI->ArgNodes;

    if (ArgNodes.empty())
      return;           // No arguments to add?  Transformation is a noop!

    // Cast the function pointer to an appropriate type!
    std::vector<Type*> ArgTys(ArgNodes.size(),
                                    PoolAllocate::PoolDescPtrTy);
    for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
         I != E; ++I)
      ArgTys.push_back((*I)->getType());
    
    FunctionType *FTy = FunctionType::get(TheCall->getType(), ArgTys, false);
    PointerType *PFTy = PointerType::getUnqual(FTy);
    
    // If there are any pool arguments cast the func ptr to the right type.
    NewCallee = CastInst::CreatePointerCast(CS.getCalledValue(), PFTy, "tmp", TheCall);
  }

  //
  // FIXME: Why do we disable strict checking when calling the
  //        DSGraph::computeNodeMapping() method?
  //
  Function::const_arg_iterator FAI = CF->arg_begin(), E = CF->arg_end();
  CallSite::arg_iterator AI = CS.arg_begin() + (thread_creation_point ? 3 : 0);
  CallSite::arg_iterator AE = CS.arg_end();
  for ( ; FAI != E && AI != AE; ++FAI, ++AI)
    if (!isa<Constant>(*AI)) {
      DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(FAI),
                                  getDSNodeHFor(*AI), NodeMapping, false);
    }

  //assert(AI == AE && "Varargs calls not handled yet!");

  // Map the return value as well...
  if (isa<PointerType>(TheCall->getType()))
    DSGraph::computeNodeMapping(CalleeGraph->getReturnNodeFor(*CF),
                                getDSNodeHFor(TheCall), NodeMapping, false);

  // This code seems redundant (and crashes occasionally)
  // There is no reason to map globals here, since they are not passed as
  // arguments

//   // Map the nodes that are pointed to by globals.
//    DSScalarMap &CalleeSM = CalleeGraph->getScalarMap();
//    for (DSScalarMap::global_iterator GI = G.getScalarMap().global_begin(), 
//           E = G.getScalarMap().global_end(); GI != E; ++GI)
//      if (CalleeSM.count(*GI))
//        DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(*GI),
//                                    getDSNodeHFor(*GI),
//                                    NodeMapping, false);

  //
  // Okay, now that we have established our mapping, we can figure out which
  // pool descriptors to pass in...
  //
  // Note:
  // There used to be code here that would create a new pool before the
  // function call and destroy it after the function call.  This could would
  // get triggered if bounds checking was disbled or the DSNode for the
  // argument was an array value.
  //
  // I believe that code was incorrect; an argument may have a NULL pool handle
  // (i.e., no pool handle) because the pool allocation heuristic used simply
  // decided not to assign that value a pool.  The argument may alias data
  // that should not be freed after the function call is complete, so calling
  // pooldestroy() after the call would free data, causing dangling pointer
  // dereference errors.
  //
  std::vector<Value*> Args;
  for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i) {
    Value *ArgVal = Constant::getNullValue(PoolAllocate::PoolDescPtrTy);
    if (NodeMapping.count(ArgNodes[i])) {
      if (DSNode *LocalNode = NodeMapping[ArgNodes[i]].getNode())
        if (FI.PoolDescriptors.count(LocalNode))
          ArgVal = FI.PoolDescriptors.find(LocalNode)->second;
    }
    Args.push_back(ArgVal);
  }

  // Add the rest of the arguments unless we're a thread creation point, in which case we only need the pools
  if(!thread_creation_point)
	  Args.insert(Args.end(), CS.arg_begin(), CS.arg_end());
    
  //
  // There are circumstances where a function is casted to another type and
  // then called (que horible).  We need to perform a similar cast if the
  // type doesn't match the number of arguments.
  //
  if (Function * NewFunction = dyn_cast<Function>(NewCallee)) {
    FunctionType * NewCalleeType = NewFunction->getFunctionType();
    if (NewCalleeType->getNumParams() != Args.size()) {
      std::vector<Type *> Types;
      Type * FuncTy = FunctionType::get (NewCalleeType->getReturnType(),
                                         Types,
                                         true);
      FuncTy = PointerType::getUnqual (FuncTy);
      NewCallee = new BitCastInst (NewCallee, FuncTy, "", TheCall);
    }
  }

  std::string Name = TheCall->getName();    TheCall->setName("");

  if(thread_creation_point) {
	Module *M = CS.getInstruction()->getParent()->getParent()->getParent();
	Value* pthread_replacement = M->getFunction("poolalloc_pthread_create");
	std::vector<Value*> thread_args;

	//Push back original thread arguments through the callee
	thread_args.push_back(CS.getArgument(0));
	thread_args.push_back(CS.getArgument(1));
	thread_args.push_back(CS.getArgument(2));

	//Push back the integer argument saying how many uses there are
	thread_args.push_back(Constant::getIntegerValue(llvm::Type::getInt32Ty(M->getContext()),APInt(32,Args.size())));
	thread_args.insert(thread_args.end(),Args.begin(),Args.end());
	thread_args.push_back(CS.getArgument(3));

	//Make the thread creation call
	NewCall = CallInst::Create(pthread_replacement,
							   thread_args,
							   Name,TheCall);
  }
  else if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    NewCall = InvokeInst::Create (NewCallee, II->getNormalDest(),
                                  II->getUnwindDest(),
                                  Args, Name, TheCall);
  } else {
    NewCall = CallInst::Create (NewCallee, Args, Name,
                                TheCall);
  }

  // Add all of the uses of the pool descriptor
  for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
    AddPoolUse(*NewCall, Args[i], PoolUses);

  TheCall->replaceAllUsesWith(NewCall);
  DEBUG(errs() << "  Result Call: " << *NewCall << "\n");

  if (!TheCall->getType()->isVoidTy()) {
    // If we are modifying the original function, update the DSGraph... 
    DSGraph::ScalarMapTy &SM = G->getScalarMap();
    DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall);
    if (CII != SM.end()) {
      SM[NewCall] = CII->second;
      SM.erase(CII);                     // Destroy the CallInst
    } else if (!FI.NewToOldValueMap.empty()) {
      // Otherwise, if this is a clone, update the NewToOldValueMap with the new
      // CI return value.
      UpdateNewToOldValueMap(TheCall, NewCall);
    }
  } else if (!FI.NewToOldValueMap.empty()) {
    UpdateNewToOldValueMap(TheCall, NewCall);
  }

  //
  // Copy over the calling convention and attributes of the original call
  // instruction to the new call instruction.
  //
  CallSite(NewCall).setCallingConv(CallSite(TheCall).getCallingConv());

  TheCall->eraseFromParent();
  visitInstruction(*NewCall);
}
Example #30
0
void CallTargetFinder<dsa>::findIndTargets(Module &M)
{
  dsa* T = &getAnalysis<dsa>();
  const DSCallGraph & callgraph = T->getCallGraph();
  DSGraph* G = T->getGlobalsGraph();
  DSGraph::ScalarMapTy& SM = G->getScalarMap();
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration())
      for (Function::iterator F = I->begin(), FE = I->end(); F != FE; ++F)
        for (BasicBlock::iterator B = F->begin(), BE = F->end(); B != BE; ++B)
          if (isa<CallInst>(B) || isa<InvokeInst>(B)) {
            CallSite cs(B);
            AllSites.push_back(cs);
            Function* CF = cs.getCalledFunction();

            if (isa<UndefValue>(cs.getCalledValue())) continue;
            if (isa<InlineAsm>(cs.getCalledValue())) continue;

            //
            // If the called function is casted from one function type to
            // another, peer into the cast instruction and pull out the actual
            // function being called.
            //
            if (!CF)
              CF = dyn_cast<Function>(cs.getCalledValue()->stripPointerCasts());

            if (!CF) {
              Value * calledValue = cs.getCalledValue()->stripPointerCasts();
              if (isa<ConstantPointerNull>(calledValue)) {
                ++DirCall;
                CompleteSites.insert(cs);
              } else {
                IndCall++;

                DSCallGraph::callee_iterator csi = callgraph.callee_begin(cs),
                                   cse = callgraph.callee_end(cs);
                while(csi != cse) {
                  const Function *F = *csi;
                  DSCallGraph::scc_iterator sccii = callgraph.scc_begin(F),
                    sccee = callgraph.scc_end(F);
                  for(;sccii != sccee; ++sccii) {
                    DSGraph::ScalarMapTy::const_iterator I = SM.find(SM.getLeaderForGlobal(*sccii));
                    if (I != SM.end()) {
                      IndMap[cs].push_back (*sccii);
                    }
                  }
                  ++csi;
                }
                const Function *F1 = (cs).getInstruction()->getParent()->getParent();
                F1 = callgraph.sccLeader(&*F1);
                
                DSCallGraph::scc_iterator sccii = callgraph.scc_begin(F1),
                  sccee = callgraph.scc_end(F1);
                for(;sccii != sccee; ++sccii) {
                  DSGraph::ScalarMapTy::const_iterator I = SM.find(SM.getLeaderForGlobal(*sccii));
                  if (I != SM.end()) {
                    IndMap[cs].push_back (*sccii);
                  }
                }

                DSNode* N = T->getDSGraph(*cs.getCaller())
                  ->getNodeForValue(cs.getCalledValue()).getNode();
                assert (N && "CallTarget: findIndTargets: No DSNode!");

                if (!N->isIncompleteNode() && !N->isExternalNode() && IndMap[cs].size()) {
                  CompleteSites.insert(cs);
                  ++CompleteInd;
                } 
                if (!N->isIncompleteNode() && !N->isExternalNode() && !IndMap[cs].size()) {
                  ++CompleteEmpty;
                  DEBUG(errs() << "Call site empty: '"
                                << cs.getInstruction()->getName()
                                << "' In '"
                                << cs.getInstruction()->getParent()->getParent()->getName()
                                << "'\n");
                }
              }
            } else {
              ++DirCall;
              IndMap[cs].push_back(CF);
              CompleteSites.insert(cs);
            }
          }

  //Print the indirect call Map:

for(std::map<CallSite, std::vector<const Function*> >::iterator indMapIt = IndMap.begin(); indMapIt != IndMap.end(); ++indMapIt )
{

   CallSite CS =  indMapIt->first;
   Instruction* Inst = CS.getInstruction();
   Inst->dump();

}


}