PSNodesSeq LLVMPointerSubgraphBuilder::createVarArg(const llvm::IntrinsicInst *Inst) { // just store all the pointers from vararg argument // to the memory given in vastart() on Offset::UNKNOWN. // It is the easiest thing we can do without any further // analysis // first we need to get the vararg argument phi const llvm::Function *F = Inst->getParent()->getParent(); Subgraph& subg = subgraphs_map[F]; PSNode *arg = subg.vararg; assert(F->isVarArg() && "vastart in a non-variadic function"); assert(arg && "Don't have variadic argument in a variadic function"); // vastart will be node that will keep the memory // with pointers, its argument is the alloca, that // alloca will keep pointer to vastart PSNode *vastart = PS.create(PSNodeType::ALLOC); // vastart has only one operand which is the struct // it uses for storing the va arguments. Strip it so that we'll // get the underlying alloca inst PSNode *op = getOperand(Inst->getOperand(0)->stripInBoundsOffsets()); // the argument is usually an alloca, but it may be a load // in the case the code was transformed by -reg2mem assert((op->getType() == PSNodeType::ALLOC || op->getType() == PSNodeType::LOAD) && "Argument of vastart is invalid"); // get node with the same pointer, but with Offset::UNKNOWN // FIXME: we're leaking it // make the memory in alloca point to our memory in vastart PSNode *ptr = PS.create(PSNodeType::GEP, op, Offset::UNKNOWN); PSNode *S1 = PS.create(PSNodeType::STORE, vastart, ptr); // and also make vastart point to the vararg args PSNode *S2 = PS.create(PSNodeType::STORE, arg, vastart); vastart->addSuccessor(ptr); ptr->addSuccessor(S1); S1->addSuccessor(S2); // set paired node to S2 for vararg, so that when adding structure, // we add the whole sequence (it adds from call-node to pair-node, // because of the old system where we did not store all sequences) // FIXME: fix this vastart->setPairedNode(S2); // FIXME: we're assuming that in a sequence in the nodes_map // is always the last node the 'real' node. In this case it is not true, // so add only the 'vastart', so that we have the mapping in nodes_map addNode(Inst, vastart); return PSNodesSeq(vastart, S2); }
PSNodesSeq LLVMPointerSubgraphBuilder::createRealloc(const llvm::CallInst *CInst) { using namespace llvm; // we create new allocation node and memcpy old pointers there PSNode *orig_mem = getOperand(CInst->getOperand(0)); PSNodeAlloc *reall = PSNodeAlloc::get(PS.create(PSNodeType::DYN_ALLOC)); // copy everything that is in orig_mem to reall PSNode *mcp = PS.create(PSNodeType::MEMCPY, orig_mem, reall, Offset::UNKNOWN); // we need the pointer in the last node that we return PSNode *ptr = PS.create(PSNodeType::CONSTANT, reall, 0); reall->setIsHeap(); reall->setSize(getConstantSizeValue(CInst->getOperand(1))); reall->addSuccessor(mcp); mcp->addSuccessor(ptr); reall->setUserData(const_cast<llvm::CallInst *>(CInst)); PSNodesSeq ret = PSNodesSeq(reall, ptr); addNode(CInst, ret); return ret; }
PSNodesSeq LLVMPointerSubgraphBuilder::createMemSet(const llvm::Instruction *Inst) { PSNode *val; if (memsetIsZeroInitialization(llvm::cast<llvm::IntrinsicInst>(Inst))) val = NULLPTR; else // if the memset is not 0-initialized, it does some // garbage into the pointer val = UNKNOWN_MEMORY; PSNode *op = getOperand(Inst->getOperand(0)->stripInBoundsOffsets()); // we need to make unknown offsets PSNode *G = PS.create(PSNodeType::GEP, op, Offset::UNKNOWN); PSNode *S = PS.create(PSNodeType::STORE, val, G); G->addSuccessor(S); PSNodesSeq ret = PSNodesSeq(G, S); addNode(Inst, ret); return ret; }