// 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; }
// 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); } } }