// Get the arg nodes in CalleeGraph for the callee of DSCS. Like
// DSGraph::getFunctionArgumentsForCall, but for indirect calls gets the most
// non-null nodes from all functions callable from that callsite.
void CSDataRando::getArgNodesForCall(DSGraph *CalleeGraph, DSCallSite DSCS, std::vector<DSNodeHandle> &ArgNodes) {
  ArgNodes.clear();

  if (DSCS.isDirectCall()) {
    CalleeGraph->getFunctionArgumentsForCall(DSCS.getCalleeFunc(), ArgNodes);
    return;
  }

  // Handle indirect calls.
  const DSCallGraph &CG = DSA->getCallGraph();
  CallSite OriginalCS = DSCS.getCallSite();
  std::vector<DSNodeHandle> TempArgNodes;

  // Get as many non-null arg nodes as possible. We don't know what the actual
  // caller will be, and there can be some mismatch between which arguments have
  // nodes for the different functions which may be called from this callsite.
  // TODO: It should be possible to cache the result of this to use for all
  // calls within the function equivalence class.
  for (auto i = CG.callee_begin(OriginalCS), e = CG.callee_end(OriginalCS); i != e; i++) {
    TempArgNodes.clear();
    CalleeGraph->getFunctionArgumentsForCall(*i, TempArgNodes);
    for (unsigned int i = 0, e = TempArgNodes.size(); i < e; i++) {
      if (i < ArgNodes.size()) {
        if (ArgNodes[i].isNull() && (!TempArgNodes[i].isNull())) {
          ArgNodes[i] = TempArgNodes[i];
        }
      } else {
        ArgNodes.push_back(TempArgNodes[i]);
      }
    }
  }
}
Example #2
0
static void GetAnyCallees(const DSCallSite &CS,
                          std::vector<const Function*> &Callees) {
  if (CS.isDirectCall()) {
    if (!CS.getCalleeFunc()->isDeclaration())
      Callees.push_back(CS.getCalleeFunc());
  } else {
    // Get all callees.
    unsigned OldSize = Callees.size();
    CS.getCalleeNode()->addFullFunctionList(Callees);
    
    // If any of the callees are unresolvable, remove them
    for (unsigned i = OldSize; i != Callees.size(); )
      if (Callees[i]->isDeclaration()) {
        Callees.erase(Callees.begin()+i);
      } else 
        ++i;
  }
}
Example #3
0
/// ResolveFunctionCall - Resolve the actual arguments of a call to function F
/// with the specified call site descriptor.  This function links the arguments
/// and the return value for the call site context-insensitively.
///
void
SteensgaardDataStructures::ResolveFunctionCall(const Function *F, 
                                                const DSCallSite &Call,
                                                DSNodeHandle &RetVal) {

  assert(ResultGraph != 0 && "Result graph not allocated!");
  DSGraph::ScalarMapTy &ValMap = ResultGraph->getScalarMap();

  // Handle the return value of the function...
  if (Call.getRetVal().getNode() && RetVal.getNode())
    RetVal.mergeWith(Call.getRetVal());

  // Loop over all pointer arguments, resolving them to their provided pointers
  unsigned PtrArgIdx = 0;
  for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
       AI != AE && PtrArgIdx < Call.getNumPtrArgs(); ++AI) {
    DSGraph::ScalarMapTy::iterator I = ValMap.find(AI);
    if (I != ValMap.end())    // If its a pointer argument...
      I->second.mergeWith(Call.getPtrArg(PtrArgIdx++));
  }
}
Example #4
0
//
// Function: getAllCallees()
//
// Description:
//  Given a DSCallSite, add to the list the functions that can be called by
//  the call site *if* it is resolvable.  Uses 'applyCallsiteFilter' to
//  only add the functions that are valid targets of this callsite.
//
void BUDataStructures::
getAllCallees(const DSCallSite &CS, FuncSet &Callees) {
  //
  // FIXME: Should we check for the Unknown flag on indirect call sites?
  //
  // Direct calls to functions that have bodies are always resolvable.
  // Indirect function calls that are for a complete call site (the analysis
  // knows everything about the call site) and do not target external functions
  // are also resolvable.
  //
  if (CS.isDirectCall()) {
    if (!CS.getCalleeFunc()->isDeclaration())
      Callees.insert(CS.getCalleeFunc());
  } else if (CS.getCalleeNode()->isCompleteNode()) {
    // Get all callees.
    if (!CS.getCalleeNode()->isExternFuncNode()) {
      // Get all the callees for this callsite
      FuncSet TempCallees;
      CS.getCalleeNode()->addFullFunctionSet(TempCallees);
      // Filter out the ones that are invalid targets with respect
      // to this particular callsite.
      applyCallsiteFilter(CS, TempCallees);
      // Insert the remaining callees (legal ones, if we're filtering)
      // into the master 'Callees' list
      Callees.insert(TempCallees.begin(), TempCallees.end());
    }
  }
}
Example #5
0
//
// Function: applyCallsiteFilter
//
// Description:
//  Given a DSCallSite, and a list of functions, filter out the ones
//  that aren't callable from the given Callsite.
//
//  Does no filtering if 'filterCallees' is set to false.
//
void BUDataStructures::
applyCallsiteFilter(const DSCallSite &DCS, FuncSet &Callees) {

  if (!filterCallees) return;

  FuncSet::iterator I = Callees.begin();
  CallSite CS = DCS.getCallSite();
  while (I != Callees.end()) {
    if (functionIsCallable(CS, *I)) {
      ++I;
    } else {
      I = Callees.erase(I);
    }
  }
}
Example #6
0
static void GetAllCallees(const DSCallSite &CS,
                          std::vector<const Function*> &Callees) {
  if (CS.isDirectCall()) {
    if (!CS.getCalleeFunc()->isDeclaration())
      Callees.push_back(CS.getCalleeFunc());
  } else if (!CS.getCalleeNode()->NodeType.isIncompleteNode()) {
    // Get all callees.
    if (!CS.getCalleeNode()->NodeType.isExternFunctionNode())
      CS.getCalleeNode()->addFullFunctionList(Callees);
  }
}
bool CSDataRando::processCallSite(CallSite CS, FuncInfo &FI, PointerEquivalenceAnalysis &P, DSGraph *G) {
  bool IndirectCall = !isa<Function>(CS.getCalledValue()->stripPointerCasts());
  if (IndirectCall) { NumIndirectCalls++; }

  CallSite OriginalCS = originalCallSite(FI, CS);
  if (!DSA->canEncryptCall(OriginalCS)) {
    if (IndirectCall) { NumIndirectCantEncrypt++; }
    return false;
  }

  DSCallSite DSCS = G->getDSCallSiteForCallSite(OriginalCS);
  const Function *Callee = getEffectiveCallee(DSCS, FI, G);
  if (!Callee) {
    if (IndirectCall) { NumIndirectCantEncrypt++; }
    return false;
  }

  FuncInfo &CalleeInfo = FunctionInfo[Callee];
  Value *Clone = getCloneCalledValue(CS, CalleeInfo);
  if (!Clone || CalleeInfo.ArgNodes.empty()) {
    if (IndirectCall) { NumIndirectCantEncrypt++; }
    return false;
  }

  // We create a mapping of the formal argument nodes in the callee function and
  // actual argument nodes in the caller function's graph.
  DSGraph::NodeMapTy NodeMap;
  DSGraph *CalleeG = DSA->getDSGraph(*Callee);

  // getArgNodesForCall places the return node and the vanode in the
  // first two slots of the vector, followed by the nodes for the regular
  // pointer arguments.
  std::vector<DSNodeHandle> ArgNodes;
  getArgNodesForCall(CalleeG, DSCS, ArgNodes);

  // First the return value
  DSNodeHandle CalleeRetNode = ArgNodes[0];
  DSGraph::computeNodeMapping(CalleeRetNode, DSCS.getRetVal(), NodeMap);

  // Then VarArgs
  DSNodeHandle CalleeVarArgNode = ArgNodes[1];
  DSGraph::computeNodeMapping(CalleeVarArgNode, DSCS.getVAVal(), NodeMap);

  // And last the regular arguments.
  for (unsigned int i = 0; i < DSCS.getNumPtrArgs() && i + 2 < ArgNodes.size(); i++) {
    DSGraph::computeNodeMapping(ArgNodes[i + 2], DSCS.getPtrArg(i), NodeMap);
  }

  // Collect the arguments and masks to pass to call
  SmallVector<Value*, 8> Args;
  unsigned int i = 0;
  for (unsigned int e = CS.getFunctionType()->getNumParams(); i < e; i++) {
    Args.push_back(CS.getArgOperand(i));
  }

  for (const DSNode *N : CalleeInfo.ArgNodes) {
    Value *Mask = P.getMaskForNode(NodeMap[N]);
    Args.push_back(Mask);
  }

  // VarArgs go after masks
  for (unsigned int e = CS.arg_size(); i < e; i++) {
    Args.push_back(CS.getArgOperand(i));
  }

  // Do replacement
  Instruction *CI = CS.getInstruction();
  Value *Call;
  if (CS.isCall()) {
    Call = CallInst::Create(Clone, Args, "", CI);
  } else {
    InvokeInst *II = cast<InvokeInst>(CI);
    Call = InvokeInst::Create(Clone, II->getNormalDest(), II->getUnwindDest(), Args, "", II);
  }
  CallSite NewCS(Call);
  NewCS.setCallingConv(CS.getCallingConv());

  CI->replaceAllUsesWith(Call);
  P.replace(CI, Call);
  CI->eraseFromParent();

  return true;
}