Example #1
0
// Helper to find the set of values described by a TSpecifier
std::set<const Value*>
getValues(const ImmutableCallSite cs, TSpecifier TS) {
  std::set<const Value*> Values;
  switch (TS) {
    case Ret:
      assert(!cs.getInstruction()->getType()->isVoidTy());
      Values.insert(cs.getInstruction());
      break;
    case Arg0:
      assert(0 < cs.arg_size());
      Values.insert(cs.getArgument(0));
      break;
    case Arg1:
      assert(1 < cs.arg_size());
      Values.insert(cs.getArgument(1));
      break;
    case Arg2:
      assert(2 < cs.arg_size());
      Values.insert(cs.getArgument(2));
      break;
    case Arg3:
      assert(3 < cs.arg_size());
      Values.insert(cs.getArgument(3));
      break;
    case Arg4:
      assert(4 < cs.arg_size());
      Values.insert(cs.getArgument(4));
      break;
    case AllArgs:
      assert(!cs.arg_empty());
      for (unsigned i = 0; i < cs.arg_size(); ++i)
        Values.insert(cs.getArgument(i));
      break;
    case VarArgs: {
      const Value *Callee = cs.getCalledValue()->stripPointerCasts();
      FunctionType *CalleeType =
        dyn_cast<FunctionType>(
          dyn_cast<PointerType>(Callee->getType())->getElementType()
          );
      for (unsigned i = CalleeType->getNumParams(); i < cs.arg_size(); ++i)
        Values.insert(cs.getArgument(i));
      break;
    }
  }
  return Values;
}
Example #2
0
// There are two types of constraints to add for a function call:
// - ValueNode(callsite) = ReturnNode(call target)
// - ValueNode(formal arg) = ValueNode(actual arg)
void Andersen::addConstraintForCall(ImmutableCallSite cs) {
  if (const Function *f = cs.getCalledFunction()) // Direct call
  {
    if (f->isDeclaration() || f->isIntrinsic()) // External library call
    {
      // Handle libraries separately
      if (addConstraintForExternalLibrary(cs, f))
        return;
      else // Unresolved library call: ruin everything!
      {
        errs() << "Unresolved ext function: " << f->getName() << "\n";
        if (cs.getType()->isPointerTy()) {
          NodeIndex retIndex = nodeFactory.getValueNodeFor(cs.getInstruction());
          assert(retIndex != AndersNodeFactory::InvalidIndex &&
                 "Failed to find ret node!");
          constraints.emplace_back(AndersConstraint::COPY, retIndex,
                                   nodeFactory.getUniversalPtrNode());
        }
        for (ImmutableCallSite::arg_iterator itr = cs.arg_begin(),
                                             ite = cs.arg_end();
             itr != ite; ++itr) {
          Value *argVal = *itr;
          if (argVal->getType()->isPointerTy()) {
            NodeIndex argIndex = nodeFactory.getValueNodeFor(argVal);
            assert(argIndex != AndersNodeFactory::InvalidIndex &&
                   "Failed to find arg node!");
            constraints.emplace_back(AndersConstraint::COPY, argIndex,
                                     nodeFactory.getUniversalPtrNode());
          }
        }
      }
    } else // Non-external function call
    {
      if (cs.getType()->isPointerTy()) {
        NodeIndex retIndex = nodeFactory.getValueNodeFor(cs.getInstruction());
        assert(retIndex != AndersNodeFactory::InvalidIndex &&
               "Failed to find ret node!");
        // errs() << f->getName() << "\n";
        NodeIndex fRetIndex = nodeFactory.getReturnNodeFor(f);
        assert(fRetIndex != AndersNodeFactory::InvalidIndex &&
               "Failed to find function ret node!");
        constraints.emplace_back(AndersConstraint::COPY, retIndex, fRetIndex);
      }
      // The argument constraints
      addArgumentConstraintForCall(cs, f);
    }
  } else // Indirect call
  {
    // We do the simplest thing here: just assume the returned value can be
    // anything :)
    if (cs.getType()->isPointerTy()) {
      NodeIndex retIndex = nodeFactory.getValueNodeFor(cs.getInstruction());
      assert(retIndex != AndersNodeFactory::InvalidIndex &&
             "Failed to find ret node!");
      constraints.emplace_back(AndersConstraint::COPY, retIndex,
                               nodeFactory.getUniversalPtrNode());
    }

    // For argument constraints, first search through all addr-taken functions:
    // any function that takes can take as many variables is a potential
    // candidate
    const Module *M =
        cs.getInstruction()->getParent()->getParent()->getParent();
    for (auto const &f : *M) {
      NodeIndex funPtrIndex = nodeFactory.getValueNodeFor(&f);
      if (funPtrIndex == AndersNodeFactory::InvalidIndex)
        // Not an addr-taken function
        continue;

      if (!f.getFunctionType()->isVarArg() && f.arg_size() != cs.arg_size())
        // #arg mismatch
        continue;

      if (f.isDeclaration() || f.isIntrinsic()) // External library call
      {
        if (addConstraintForExternalLibrary(cs, &f))
          continue;
        else {
          // Pollute everything
          for (ImmutableCallSite::arg_iterator itr = cs.arg_begin(),
                                               ite = cs.arg_end();
               itr != ite; ++itr) {
            Value *argVal = *itr;

            if (argVal->getType()->isPointerTy()) {
              NodeIndex argIndex = nodeFactory.getValueNodeFor(argVal);
              assert(argIndex != AndersNodeFactory::InvalidIndex &&
                     "Failed to find arg node!");
              constraints.emplace_back(AndersConstraint::COPY, argIndex,
                                       nodeFactory.getUniversalPtrNode());
            }
          }
        }
      } else
        addArgumentConstraintForCall(cs, &f);
    }
  }
}