Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
        }
      }
    }
  }
}
Ejemplo n.º 3
0
//
// 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;
}
Ejemplo n.º 4
0
//
// 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);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
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();

}


}
Ejemplo n.º 7
0
/// ProcessNodesReachableFromGlobals - If we inferred anything about nodes
/// reachable from globals, we have to make sure that we incorporate data for
/// all graphs that include those globals due to the nature of the globals
/// graph.
///
void StructureFieldVisitorBase::
ProcessNodesReachableFromGlobals(DSGraph &DSG,
                                 std::multimap<DSNode*,LatticeValue*> &NodeLVs){
  // Start by marking all nodes reachable from globals.
  DSScalarMap &SM = DSG.getScalarMap();
  if (SM.global_begin() == SM.global_end()) return;

  hash_set<const DSNode*> Reachable;
  for (DSScalarMap::global_iterator GI = SM.global_begin(),
         E = SM.global_end(); GI != E; ++GI)
    SM[*GI].getNode()->markReachableNodes(Reachable);
  if (Reachable.empty()) return;
  
  // If any of the nodes with dataflow facts are reachable from the globals
  // graph, we have to do the GG processing step.
  bool MustProcessThroughGlobalsGraph = false;
  for (std::multimap<DSNode*, LatticeValue*>::iterator I = NodeLVs.begin(),
         E = NodeLVs.end(); I != E; ++I)
    if (Reachable.count(I->first)) {
      MustProcessThroughGlobalsGraph = true;
      break;
    }
  
  if (!MustProcessThroughGlobalsGraph) return;
  Reachable.clear();

  // Compute the mapping from DSG to the globals graph.
  DSGraph::NodeMapTy DSGToGGMap;
  DSG.computeGToGGMapping(DSGToGGMap);

  // Most of the times when we find facts about things reachable from globals we
  // we are in the main graph.  This means that we have *all* of the globals
  // graph in this DSG.  To be efficient, we compute the minimum set of globals
  // that can reach any of the NodeLVs facts.
  //
  // I'm not aware of any wonderful way of computing the set of globals that
  // points to the set of nodes in NodeLVs that is not N^2 in either NodeLVs or
  // the number of globals, except to compute the inverse of DSG.  As such, we
  // compute the inverse graph of DSG, which basically has the edges going from
  // pointed to nodes to pointing nodes.  Because we only care about one
  // connectedness properties, we ignore field info.  In addition, we only
  // compute inverse of the portion of the graph reachable from the globals.
  std::set<std::pair<DSNode*,DSNode*> > InverseGraph;

  for (DSScalarMap::global_iterator GI = SM.global_begin(),
         E = SM.global_end(); GI != E; ++GI)
    ComputeInverseGraphFrom(SM[*GI].getNode(), InverseGraph);

  // Okay, now that we have our bastardized inverse graph, compute the set of
  // globals nodes reachable from our lattice nodes.
  for (std::multimap<DSNode*, LatticeValue*>::iterator I = NodeLVs.begin(),
         E = NodeLVs.end(); I != E; ++I)
    ComputeNodesReachableFrom(I->first, InverseGraph, Reachable);
 
  // Now that we know which nodes point to the data flow facts, figure out which
  // globals point to the data flow facts.
  std::set<GlobalValue*> Globals;
  for (hash_set<const DSNode*>::iterator I = Reachable.begin(),
         E = Reachable.end(); I != E; ++I)
    Globals.insert((*I)->globals_begin(), (*I)->globals_end());

  // Finally, loop over all of the DSGraphs for the program, computing
  // information for the graph if not done already, mapping the result into our
  // context.
  for (hash_map<const Function*, DSGraph*>::iterator GI = ECG.DSInfo.begin(),
         E = ECG.DSInfo.end(); GI != E; ++GI) {
    DSGraph &FG = *GI->second;
    // Graphs can contain multiple functions, only process the graph once.
    if (GI->first != FG.retnodes_begin()->first ||
        // Also, do not bother reprocessing DSG.
        &FG == &DSG)
      continue;

    bool GraphUsesGlobal = false;
    for (std::set<GlobalValue*>::iterator I = Globals.begin(),
           E = Globals.end(); I != E; ++I)
      if (FG.getScalarMap().count(*I)) {
        GraphUsesGlobal = true;
        break;
      }

    // If this graph does not contain the global at all, there is no reason to
    // even think about it.
    if (!GraphUsesGlobal) continue;

    // Otherwise, compute the full set of dataflow effects of the function.
    std::multimap<DSNode*, LatticeValue*> &FGF = getCalleeFacts(FG);
    //std::cerr << "Computed: " << FG.getFunctionNames() << "\n";

#if 0
    for (std::multimap<DSNode*, LatticeValue*>::iterator I = FGF.begin(),
           E = FGF.end(); I != E; ++I)
      I->second->dump();
#endif
    // Compute the mapping of nodes in the globals graph to the function's
    // graph.  Note that this function graph may not have nodes (or may have
    // fragments of full nodes) in the globals graph, and we don't want this to
    // pessimize the analysis.
    std::multimap<const DSNode*, std::pair<DSNode*,int> > GraphMap;
    DSGraph::NodeMapTy GraphToGGMap;
    FG.computeGToGGMapping(GraphToGGMap);

    // "Invert" the mapping.  We compute the mapping from the start of a global
    // graph node to a place in the graph's node.  Note that not all of the GG
    // node may be present in the graphs node, so there may be a negative offset
    // involved.
    while (!GraphToGGMap.empty()) {
      DSNode *GN = const_cast<DSNode*>(GraphToGGMap.begin()->first);
      DSNodeHandle &GGNH = GraphToGGMap.begin()->second;
      GraphMap.insert(std::make_pair(GGNH.getNode(),
                                     std::make_pair(GN, -GGNH.getOffset())));
      GraphToGGMap.erase(GraphToGGMap.begin());
    }

    // Loop over all of the dataflow facts that we have computed, mapping them
    // to the globals graph.
    for (std::multimap<DSNode*, LatticeValue*>::iterator I = NodeLVs.begin(),
           E = NodeLVs.end(); I != E; ) {
      bool FactHitBottom = false;

      //I->second->dump();

      assert(I->first->getParentGraph() == &DSG);
      assert(I->second->getNode()->getParentGraph() == &DSG);

      // Node is in the GG?
      DSGraph::NodeMapTy::iterator DSGToGGMapI = DSGToGGMap.find(I->first);
      if (DSGToGGMapI != DSGToGGMap.end()) {
        DSNodeHandle &GGNH = DSGToGGMapI->second;
        const DSNode *GGNode = GGNH.getNode();
        unsigned DSGToGGOffset = GGNH.getOffset();

        // See if there is a node in FG that corresponds to this one.  If not,
        // no information will be computed in this scope, as the memory is not
        // accessed.
        std::multimap<const DSNode*, std::pair<DSNode*,int> >::iterator GMI =
          GraphMap.find(GGNode);

        // LatticeValOffset - The offset from the start of the GG Node to the
        // start of the field we are interested in.
        unsigned LatticeValOffset = I->second->getFieldOffset()+DSGToGGOffset;

        // Loop over all of the nodes in FG that correspond to this single node
        // in the GG.
        for (; GMI != GraphMap.end() && GMI->first == GGNode; ++GMI) {
          // Compute the offset to the field in the user graph.
          unsigned FieldOffset = LatticeValOffset - GMI->second.second;

          // If the field is within the amount of memory accessed by this scope,
          // then there must be a corresponding lattice value.
          DSNode *FGNode = GMI->second.first;
          if (FieldOffset < FGNode->getSize()) {
            LatticeValue *CorrespondingLV = 0;

            std::multimap<DSNode*, LatticeValue*>::iterator FGFI =
              FGF.find(FGNode);
            for (; FGFI != FGF.end() && FGFI->first == FGNode; ++FGFI)
              if (FGFI->second->getFieldOffset() == FieldOffset) {
                CorrespondingLV = FGFI->second;
                break;
              }

            // Finally, if either there was no corresponding fact (because it
            // hit bottom in this scope), or if merging the two pieces of
            // information makes it hit bottom, remember this.
            if (CorrespondingLV == 0 ||
                I->second->mergeInValue(CorrespondingLV))
              FactHitBottom = true;
          }
        }
      }

      if (FactHitBottom) {
        delete I->second;
        NodeLVs.erase(I++);
        if (NodeLVs.empty()) return;
      } else {
        ++I;
      }
    }
  }
}
Ejemplo n.º 8
0
// Precondition: Enforce that the alloca nodes haven't been already converted
void ConvertUnsafeAllocas::TransformAllocasToMallocs(std::list<DSNode *> 
                                                     & unsafeAllocaNodes) {

  std::list<DSNode *>::const_iterator iCurrent = unsafeAllocaNodes.begin(), 
                                      iEnd     = unsafeAllocaNodes.end();

  for (; iCurrent != iEnd; ++iCurrent) {
    DSNode *DSN = *iCurrent;
    
    // Now change the alloca instruction corresponding to the node  
    // to malloc 
    DSGraph *DSG = DSN->getParentGraph();
    DSGraph::ScalarMapTy &SM = DSG->getScalarMap();

#ifndef LLVA_KERNEL    
    Instruction *MI = 0;
#else
    Value *MI = 0;
#endif
    for (DSGraph::ScalarMapTy::iterator SMI = SM.begin(), SME = SM.end();
         SMI != SME; ) {
      bool stackAllocate = true;
      // If this is already a heap node, then you cannot allocate this on the
      // stack
      if (DSN->isHeapNode()) {
        stackAllocate = false;
      }

      if (SMI->second.getNode() == DSN) {
        if (AllocaInst *AI = dyn_cast<AllocaInst>((Value *)(SMI->first))) {
          //
          // Create a new heap allocation instruction.
          //
          if (AI->getParent() != 0) {
            //
            // Create an LLVM value representing the size of the allocation.
            // If it's an array allocation, we'll need to insert a
            // multiplication instruction to get the size times the number of
            // elements.
            //
            unsigned long size = TD->getTypeAllocSize(AI->getAllocatedType());
            Value *AllocSize = ConstantInt::get(Int32Type, size);
            if (AI->isArrayAllocation())
              AllocSize = BinaryOperator::Create(Instruction::Mul, AllocSize,
                                                 AI->getOperand(0), "sizetmp",
                                                 AI);     
            std::vector<Value *> args(1, AllocSize);
            CallInst *CI = CallInst::Create (kmalloc, args.begin(), args.end(), "", AI);
            MI = castTo (CI, AI->getType(), "", AI);
            DSN->setHeapMarker();
            AI->replaceAllUsesWith(MI);
            SM.erase(SMI++);
            AI->getParent()->getInstList().erase(AI);
            ++ConvAllocas;
            InsertFreesAtEnd(MI);
#ifndef LLVA_KERNEL     
            if (stackAllocate) {
              ArrayMallocs.insert(MI);
            }
#endif        
          } else {
            ++SMI;
          } 
        } else {
          ++SMI;
        }
      } else {
        ++SMI;
      }
    }
  }  
}