bool CallLowering::lowerCall( MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, unsigned ResReg, ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const { auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout(); // First step is to marshall all the function's parameters into the correct // physregs and memory locations. Gather the sequence of argument types that // we'll pass to the assigner function. SmallVector<ArgInfo, 8> OrigArgs; unsigned i = 0; unsigned NumFixedArgs = CS.getFunctionType()->getNumParams(); for (auto &Arg : CS.args()) { ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}, i < NumFixedArgs}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS); // We don't currently support swifterror or swiftself args. if (OrigArg.Flags.isSwiftError() || OrigArg.Flags.isSwiftSelf()) return false; OrigArgs.push_back(OrigArg); ++i; } MachineOperand Callee = MachineOperand::CreateImm(0); if (const Function *F = CS.getCalledFunction()) Callee = MachineOperand::CreateGA(F, 0); else Callee = MachineOperand::CreateReg(GetCalleeReg(), false); ArgInfo OrigRet{ResReg, CS.getType(), ISD::ArgFlagsTy{}}; if (!OrigRet.Ty->isVoidTy()) setArgFlags(OrigRet, AttributeList::ReturnIndex, DL, CS); return lowerCall(MIRBuilder, CS.getCallingConv(), Callee, OrigRet, OrigArgs); }
std::vector<FlowRecord> TaintReachable::process(const ContextID ctxt, const ImmutableCallSite cs) const { DEBUG(errs() << "Using taint reachable signature for: " << *cs.getInstruction() << "\n"); FlowRecord exp(false,ctxt,ctxt); FlowRecord imp(true,ctxt,ctxt); // implicit from the pc of the call site and the function pointer imp.addSourceValue(*cs->getParent()); imp.addSourceValue(*cs.getCalledValue()); // Sources and sinks of the args for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end(); arg != end; ++arg) { // every argument's value is a source exp.addSourceValue(**arg); // if the argument is a pointer, everything it reaches is a source // and everything it reaches is a sink if ((*arg)->getType()->isPointerTy()) { exp.addSourceReachablePtr(**arg); imp.addSourceValue(**arg); exp.addSinkReachablePtr(**arg); imp.addSinkReachablePtr(**arg); } } // if the function has a return value it is a sink if (!cs->getType()->isVoidTy()) { imp.addSinkValue(*cs.getInstruction()); exp.addSinkValue(*cs.getInstruction()); } std::vector<FlowRecord> flows; flows.push_back(imp); flows.push_back(exp); return flows; }
std::vector<FlowRecord> OverflowChecks::process(const ContextID ctxt, const ImmutableCallSite cs) const { DEBUG(errs() << "Using OverflowChecks signature...\n"); FlowRecord exp(false,ctxt,ctxt); FlowRecord imp(true,ctxt,ctxt); imp.addSourceValue(*cs->getParent()); // Add all argument values as sources for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end(); arg != end; ++arg) exp.addSourceValue(**arg); assert(!cs->getType()->isVoidTy() && "Found 'void' overflow check?"); // And the return value as a sink exp.addSinkValue(*cs.getInstruction()); imp.addSinkValue(*cs.getInstruction()); std::vector<FlowRecord> flows; flows.push_back(imp); flows.push_back(exp); return flows; }