InsInfo::InsInfo(const Instruction *i, const ptr::PointsToSets &PS, const mods::Modifies &MOD) : ins(i), sliced(true) { typedef ptr::PointsToSets::PointsToSet PTSet; if (const LoadInst *LI = dyn_cast<const LoadInst>(i)) { addDEF(Pointee(i, -1)); const Value *op = elimConstExpr(LI->getPointerOperand()); if (isa<ConstantPointerNull>(op)) { errs() << "ERROR in analysed code -- reading from address 0 at " << i->getParent()->getParent()->getName() << ":\n"; i->print(errs()); } else if (isa<ConstantInt>(op)) { } else { addREF(Pointee(op, -1)); if (hasExtraReference(op)) { addREF(Pointee(op, 0)); } else { const PTSet &S = getPointsToSet(op,PS); for (PTSet::const_iterator I = S.begin(), E = S.end(); I != E; ++I) addREF(*I); } } } else if (const StoreInst *SI = dyn_cast<const StoreInst>(i)) { const Value *l = elimConstExpr(SI->getPointerOperand()); if (isa<ConstantPointerNull>(l)) { errs() << "ERROR in analysed code -- writing to address 0 at " << i->getParent()->getParent()->getName() << ":\n"; i->print(errs()); } else if (isa<ConstantInt>(l)) { } else { if (hasExtraReference(l)) { addDEF(Pointee(l, 0)); } else { const PTSet &S = getPointsToSet(l, PS); for (PTSet::const_iterator I = S.begin(), E = S.end(); I != E; ++I) addDEF(*I); } if (!l->getType()->isIntegerTy()) addREF(Pointee(l, -1)); const Value *r = elimConstExpr(SI->getValueOperand()); if (!hasExtraReference(r) && !isConstantValue(r)) addREF(Pointee(r, -1)); } } else if (const GetElementPtrInst *gep = dyn_cast<const GetElementPtrInst>(i)) { addDEF(Pointee(i, -1)); addREF(Pointee(gep->getPointerOperand(), -1)); for (unsigned i = 1, e = gep->getNumOperands(); i != e; ++i) { Value *op = gep->getOperand(i); if (!isConstantValue(op)) addREF(Pointee(op, -1)); } } else if (CallInst const* const C = dyn_cast<const CallInst>(i)) { const Value *cv = C->getCalledValue(); if (isInlineAssembly(C)) { errs() << "ERROR: Inline assembler detected in " << i->getParent()->getParent()->getName() << ", ignoring\n"; } else if (isMemoryAllocation(cv)) { if (!isConstantValue(C->getArgOperand(0))) addREF(Pointee(C->getArgOperand(0), -1)); addDEF(Pointee(i, -1)); } else if (isMemoryDeallocation(cv)) { } else if (isMemoryCopy(cv) || isMemoryMove(cv) || isMemorySet(cv)) { const Value *len = elimConstExpr(C->getArgOperand(2)); uint64_t lenConst = getSizeOfMem(len); const Value *l = elimConstExpr(C->getOperand(0)); addDEFArray(PS, l, lenConst); addREF(Pointee(l, -1)); const Value *r = elimConstExpr(C->getOperand(1)); /* memset has a constant/variable there */ if (isMemoryCopy(cv) || isMemoryMove(cv)) addREFArray(PS, r, lenConst); addREF(Pointee(r, -1)); /* memcpy/memset wouldn't work with len being 'undef' */ if (!isConstantValue(len)) addREF(Pointee(len, -1)); } else { typedef std::vector<const llvm::Function *> CalledVec; /* did we miss something? */ assert(!memoryManStuff(cv)); if (const Function *F = dyn_cast<Function>(cv)) handleVariousFuns(PS, C, F); else addREF(Pointee(cv, -1)); CalledVec CV; getCalledFunctions(C, PS, std::back_inserter(CV)); for (CalledVec::const_iterator f = CV.begin(); f != CV.end(); ++f) { mods::Modifies::mapped_type const& M = getModSet(*f, MOD); for (mods::Modifies::mapped_type::const_iterator v = M.begin(); v != M.end(); ++v) addDEF(*v); } if (!callToVoidFunction(C)) addDEF(Pointee(C, -1)); } } else if (isa<const ReturnInst>(i)) { } else if (const BinaryOperator *BO = dyn_cast<const BinaryOperator>(i)) { addDEF(Pointee(i, -1)); if (!isConstantValue(BO->getOperand(0))) addREF(Pointee(BO->getOperand(0), -1)); if (!isConstantValue(BO->getOperand(1))) addREF(Pointee(BO->getOperand(1), -1)); } else if (const CastInst *CI = dyn_cast<const CastInst>(i)) { addDEF(Pointee(i, -1)); if (!hasExtraReference(CI->getOperand(0))) addREF(Pointee(CI->getOperand(0), -1)); } else if (const AllocaInst *AI = dyn_cast<const AllocaInst>(i)) { addDEF(Pointee(AI, -1)); if (!isConstantValue(AI->getArraySize())) addREF(Pointee(AI->getArraySize(), -1)); } else if (const CmpInst *CI = dyn_cast<const CmpInst>(i)) { addDEF(Pointee(i, -1)); if (!isConstantValue(CI->getOperand(0))) addREF(Pointee(CI->getOperand(0), -1)); if (!isConstantValue(CI->getOperand(1))) addREF(Pointee(CI->getOperand(1), -1)); } else if (const BranchInst *BI = dyn_cast<const BranchInst>(i)) { if (BI->isConditional() && !isConstantValue(BI->getCondition())) addREF(Pointee(BI->getCondition(), -1)); } else if (const PHINode *phi = dyn_cast<const PHINode>(i)) { addDEF(Pointee(i, -1)); for (unsigned k = 0; k < phi->getNumIncomingValues(); ++k) if (!isConstantValue(phi->getIncomingValue(k))) addREF(Pointee(phi->getIncomingValue(k), -1)); } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(i)) { if (!isConstantValue(SI->getCondition())) addREF(Pointee(SI->getCondition(), -1)); } else if (const SelectInst *SI = dyn_cast<const SelectInst>(i)) { // TODO: THE FOLLOWING CODE HAS NOT BEEN TESTED YET addDEF(Pointee(i, -1)); if (!isConstantValue(SI->getCondition())) addREF(Pointee(SI->getCondition(), -1)); if (!isConstantValue(SI->getTrueValue())) addREF(Pointee(SI->getTrueValue(), -1)); if (!isConstantValue(SI->getFalseValue())) addREF(Pointee(SI->getFalseValue(), -1)); } else if (isa<const UnreachableInst>(i)) { } else if (const ExtractValueInst *EV = dyn_cast<const ExtractValueInst>(i)) { addDEF(Pointee(i, -1)); addREF(Pointee(EV->getAggregateOperand(), -1)); } else if (const InsertValueInst *IV = dyn_cast<const InsertValueInst>(i)) { // TODO THE FOLLOWING CODE HAS NOT BEEN TESTED YET const Value *r = IV->getInsertedValueOperand(); addDEF(Pointee(IV->getAggregateOperand(), -1)); if (!isConstantValue(r)) addREF(Pointee(r, -1)); } else { errs() << "ERROR: Unsupported instruction reached\n"; i->print(errs()); } }
InsInfo::InsInfo(const Instruction *i, const ptr::PointsToSets &PS, const mods::Modifies &MOD) : ins(i), sliced(true) { typedef ptr::PointsToSets::PointsToSet PTSet; if (const LoadInst *LI = dyn_cast<const LoadInst>(i)) { addDEF(i); const Value *op = elimConstExpr(LI->getPointerOperand()); if (isa<ConstantPointerNull>(op)) { errs() << "ERROR in analysed code -- reading from address 0 at " << i->getParent()->getParent()->getName() << ":\n"; i->print(errs()); } else if (isa<ConstantInt>(op)) { } else { addREF(op); if (!hasExtraReference(op)) { const PTSet &S = getPointsToSet(op,PS); for (PTSet::const_iterator I = S.begin(), E = S.end(); I != E; ++I) addREF(*I); } } } else if (const StoreInst *SI = dyn_cast<const StoreInst>(i)) { const Value *l = elimConstExpr(SI->getPointerOperand()); if (isa<ConstantPointerNull>(l)) { errs() << "ERROR in analysed code -- writing to address 0 at " << i->getParent()->getParent()->getName() << ":\n"; i->print(errs()); } else if (isa<ConstantInt>(l)) { } else { if (hasExtraReference(l)) { addDEF(l); } else { const PTSet &S = getPointsToSet(l, PS); for (PTSet::const_iterator I = S.begin(), E = S.end(); I != E; ++I) addDEF(*I); } if (!l->getType()->isIntegerTy()) { #ifdef DEBUG_INSTINFO errs() << " store inst add LHS " << l->getName() << " to reference "; l->getType()->dump(); errs() << "\n"; #endif //TODO: make the reference set strict for now addREF(l); } const Value *r = elimConstExpr(SI->getValueOperand()); if (!hasExtraReference(r) && !isConstantValue(r)) { addREF(r); #ifdef DEBUG_INSTINFO errs() << " store inst add RHS " << r->getName() << " to reference\n"; #endif } } } else if (const GetElementPtrInst *gep = dyn_cast<const GetElementPtrInst>(i)) { addDEF(i); addREF(gep->getPointerOperand()); for (unsigned i = 1, e = gep->getNumOperands(); i != e; ++i) { Value *op = gep->getOperand(i); if (!isa<ConstantInt>(op)) addREF(op); } } else if (CallInst const* const C = dyn_cast<const CallInst>(i)) { if (isa<IntrinsicInst>(C)) // skip intrinsic instruction return; const Value *cv = C->getCalledValue(); if (isInlineAssembly(C)) { errs() << "ERROR: Inline assembler detected in " << i->getParent()->getParent()->getName() << ", ignoring\n"; } else if (isMemoryAllocation(cv)) { addDEF(i); } else if (isMemoryDeallocation(cv)) { } else if (isMemoryCopy(cv) || isMemoryMove(cv)) { const Value *l = elimConstExpr(C->getOperand(0)); if (isPointerValue(l)) { const PTSet &L = getPointsToSet(l, PS); for (PTSet::const_iterator p = L.begin(); p != L.end(); ++p) addDEF(*p); } const Value *r = elimConstExpr(C->getOperand(1)); const Value *len = elimConstExpr(C->getOperand(2)); addREF(l); addREF(r); /* memcpy/memset wouldn't work with len being 'undef' */ addREF(len); if (isPointerValue(r)) { const PTSet &R = getPointsToSet(r, PS); for (PTSet::const_iterator p = R.begin(); p != R.end(); ++p) addREF(*p); } } else if (!memoryManStuff(C)) { typedef std::vector<const llvm::Function *> CalledVec; CalledVec CV; getCalledFunctions(C, PS, std::back_inserter(CV)); const Value *callie = C->getCalledValue(); #ifdef DEBUG_INSTINFO errs() << "CallInst "; C->dump(); #endif if (!isa<Function>(callie)) { #ifdef DEBUG_INSTINFO errs() << "\tRef1: "; callie->dump(); #endif addREF(callie); } for (CalledVec::const_iterator f = CV.begin(); f != CV.end(); ++f) { mods::Modifies::mapped_type const& M = getModSet(*f, MOD); for (mods::Modifies::mapped_type::const_iterator v = M.begin(); v != M.end(); ++v) { #ifdef DEBUG_INSTINFO errs() << "\tDef1: "; (*v)->dump(); #endif addDEF(*v); } } unsigned argn = C->getNumArgOperands(); for (unsigned arg = 0; arg < argn; arg++) { Value * argument = C->getArgOperand(arg); #ifdef DEBUG_INSTINFO errs() << "\tRef2: "; argument->dump(); #endif if (isConstantValue(argument)) // skip constant arugment continue; addREF(argument); } if (!callToVoidFunction(C)) { #ifdef DEBUG_INSTINFO errs() << "\tDef2: "; C->dump(); #endif addDEF(C); } } } else if (isa<const ReturnInst>(i)) { } else if (const BinaryOperator *BO = dyn_cast<const BinaryOperator>(i)) { addDEF(i); if (!isConstantValue(BO->getOperand(0))) addREF(BO->getOperand(0)); if (!isConstantValue(BO->getOperand(1))) addREF(BO->getOperand(1)); } else if (const CastInst *CI = dyn_cast<const CastInst>(i)) { addDEF(i); if (!hasExtraReference(CI->getOperand(0))) addREF(CI->getOperand(0)); } else if (const AllocaInst *AI = dyn_cast<const AllocaInst>(i)) { addDEF(AI); } else if (const CmpInst *CI = dyn_cast<const CmpInst>(i)) { addDEF(i); if (!isConstantValue(CI->getOperand(0))) addREF(CI->getOperand(0)); if (!isConstantValue(CI->getOperand(1))) addREF(CI->getOperand(1)); } else if (const BranchInst *BI = dyn_cast<const BranchInst>(i)) { if (BI->isConditional() && !isConstantValue(BI->getCondition())) addREF(BI->getCondition()); } else if (const PHINode *phi = dyn_cast<const PHINode>(i)) { addDEF(i); for (unsigned k = 0; k < phi->getNumIncomingValues(); ++k) if (!isConstantValue(phi->getIncomingValue(k))) addREF(phi->getIncomingValue(k)); } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(i)) { if (!isConstantValue(SI->getCondition())) addREF(SI->getCondition()); } else if (const SelectInst *SI = dyn_cast<const SelectInst>(i)) { // TODO: THE FOLLOWING CODE HAS NOT BEEN TESTED YET addDEF(i); if (!isConstantValue(SI->getCondition())) addREF(SI->getCondition()); if (!isConstantValue(SI->getTrueValue())) addREF(SI->getTrueValue()); if (!isConstantValue(SI->getFalseValue())) addREF(SI->getFalseValue()); } else if (isa<const UnreachableInst>(i)) { } else if (const ExtractValueInst *EV = dyn_cast<const ExtractValueInst>(i)) { addDEF(i); addREF(EV->getAggregateOperand()); } else if (const InsertValueInst *IV = dyn_cast<const InsertValueInst>(i)) { // TODO THE FOLLOWING CODE HAS NOT BEEN TESTED YET const Value *r = IV->getInsertedValueOperand(); addDEF(IV->getAggregateOperand()); if (!isConstantValue(r)) addREF(r); } else { errs() << "ERROR: Unsupported instruction reached\n"; i->print(errs()); } }