dsa算法(10)

1.3.3.4.1.1.10. 对整数ßà指针指令的处理

IntToPtrInst代表把一个整数转换到一个指针。由于Value是IntToPtrInst的基类之一,如果这个Value只有一个用户(llvm的User类),hasOneUse返回true。如果该用户是ICmpInst——整数/指针比较语句,那么566行的NumBoringIntToPtr用于统计这种事件。在其他情况,由于得到的指针所指向的内存对象未知,在571行进行标记。

 

562    void GraphBuilder::visitIntToPtrInst(IntToPtrInst&I) {

563      DSNode *N = createNode();

564      if(I.hasOneUse()) {

565        if(isa<ICmpInst>(*(I.use_begin()))) {

566          NumBoringIntToPtr++;

567          return;

568        }

569      } else {

570        N->setIntToPtrMarker();

571        N->setUnknownMarker();

572      }

573      setDestTo(I,N);

574    }

 

类似的,PtrToIntInst代表把一个指针转换到一个整数。586行的DenseSet是llvm定义的容器,其在588行的insert方法返回std::pair<iterator, bool>,在插入成功或对象已在容器中时,返回pair的第二个元素是true。那么587行while循环的作用就是沿着用户链,发掘类型为BranchInst的用户,进行统计。NumBoringIntToPtr统记了仅用在cmp的inttoptr的数目。

 

576    void GraphBuilder::visitPtrToIntInst(PtrToIntInst&I) {

577      DSNode* N = getValueDest(I.getOperand(0)).getNode();

578      if(I.hasOneUse()) {

579        if(isa<ICmpInst>(*(I.use_begin()))) {

580          NumBoringIntToPtr++;

581          return;

582        }

583      }

584      if(I.hasOneUse()) {

585        Value *V = dyn_cast<Value>(*(I.use_begin()));

586        DenseSet<Value *> Seen;

587        while(V&& V->hasOneUse() &&

588              Seen.insert(V).second) {

589          if(isa<LoadInst>(V))

590            break;

591          if(isa<StoreInst>(V))

592            break;

593          if(isa<CallInst>(V))

594            break;

595          V =dyn_cast<Value>(*(V->use_begin()));

596        }

597        if(isa<BranchInst>(V)){

598          NumBoringIntToPtr++;

599          return;

600        }

601      }

602      if(N)

603        N->setPtrToIntMarker();

604    }

1.3.3.4.1.1.11. 对bitcast指令的处理

BitCastInst代表一个空操作转换,因为这个转换没有比特位的改变。显然对于DSA,这个转换在涉及指针时才有价值。

 

607    void GraphBuilder::visitBitCastInst(BitCastInst&I) {

608      if (!isa<PointerType>(I.getType())) return; // Only pointers

609      DSNodeHandle Ptr = getValueDest(I.getOperand(0));

610      if (Ptr.isNull()) return;

611      setDestTo(I,Ptr);

612    }

1.3.3.4.1.1.12. 对insertvalue指令的处理

InsertValueInst向一个聚集类型(struct/class/union或数组)值的一个数据成员插入值,并返回更新后的聚集类型值。InsertValueInst带至少三个参数,第一个是聚集类型值,第二个是插入的值,第三个是指示插入位置的常量。

 

648    void GraphBuilder::visitInsertValueInst(InsertValueInst&I) {

649      setDestTo(I,createNode()->setAllocaMarker());

650   

651      Type *StoredTy =I.getInsertedValueOperand()->getType();

652      DSNodeHandle Dest = getValueDest(&I);

653      Dest.mergeWith(getValueDest(I.getAggregateOperand()));

654   

655      // Mark that thenode is written to...

656      Dest.getNode()->setModifiedMarker();

657      Type* STy =I.getAggregateOperand()->getType();

658   

659      unsigned Offset = getValueOffset(STy,I.getIndices(), TD);

660   

661      // Ensure atype-record exists...

662      Dest.getNode()->mergeTypeInfo(StoredTy, Offset);

663   

664      // Avoid addingedges from null, or processing non-"pointer" stores

665      if (isa<PointerType>(StoredTy))

666        Dest.addEdgeTo(getValueDest(I.getInsertedValueOperand()));

667    }

 

在649行,为InsertValueInst创建了DSNodeHandle,并指向同一行构建的标记为alloca的DSNode(代表其在栈上构建的返回值)。这个DSNodeHandle在652行通过getValueDesc给出。接着在653行,它与第一个参数的节点发生了简并(因为它们的指针域都要指向相同的地方)。因为llvm IR要求操作数的类型必须严格匹配,因此662行确保要保存的值的类型存在于结构体指定的位置上(至于这个位置所代表的多个类型是否相容就是另一个问题了)。最后,如果插入的值是个指针,在666行让Dest有指向该指针指向对象的一条边。

1.3.3.4.1.1.13. 对extractvalue指令的处理

ExtractValueInst则是InsertValueInst的相反操作——从一个聚集类型值的指定域提取值。它也类似地带至少三个参数,第一个是聚集类型值,第二个是提取的值,第三个是指示提取位置的常量。

 

669    void GraphBuilder::visitExtractValueInst(ExtractValueInst&I) {

670      DSNodeHandle Ptr = getValueDest(I.getAggregateOperand());

671   

672      // Make that thenode is read from...

673      Ptr.getNode()->setReadMarker();

674      Type* STy =I.getAggregateOperand()->getType();

675   

676      unsigned Offset = getValueOffset(STy,I.getIndices(), TD);

677   

678      // Ensure atyperecord exists...

679      Ptr.getNode()->mergeTypeInfo(I.getType(), Offset);

680   

681      if (isa<PointerType>(I.getType()))

682        setDestTo(I,getLink(Ptr));

683    }

 

这里的处理与InsertValueInst类似,且更简单。

1.3.3.4.1.1.14. 对GetElementPtr指令的处理

参考1.3.3.2.2.2. 对GetElementPtr指令的处理一节。

1.3.3.4.1.1.15. 对调用指令的处理

在llvm IR中,CallInst来自call指令,InvokeInst来自invoke指令。两者都是对函数的调用,主要的区别在于,invoke指令会创建与一个标记的关联,该关联被运行时用于回滚栈。不过,对于DSA这两者没有区别。

 

904    void GraphBuilder::visitCallInst(CallInst&CI) {

904      visitCallSite(&CI);

904    }

 

904    void GraphBuilder::visitInvokeInst(InvokeInst&II) {

904      visitCallSite(&II);

904    }

 

要以相同的方式处理CallInst及InvokeInst,就要用到CallSite。它是llvm专门提供的一个便利的封装类。Intrinsic函数由1143行的visitIntrinsic处理。而对于内联汇编函数,采用保守的处理,把所有的指针视为互为别名,进行简并,并缩合返回值节点,如果它是指针。

 

1135  void GraphBuilder::visitCallSite(CallSite CS){

1136    //

1137    // Get the calledvalue.  Strip off any casts which arelossless.

1138    //

1139    Value *Callee =CS.getCalledValue()->stripPointerCasts();

1140 

1141    // Special case handlingof certain libc allocation functions here.

1142    if (Function *F =dyn_cast<Function>(Callee))

1143      if (F->isIntrinsic() && visitIntrinsic(CS, F))

1144        return;

1145 

1146    //Can't do muchabout inline asm (yet!)

1147    if (isa<InlineAsm> (Callee)) {

1148      ++NumAsmCall;

1149      DSNodeHandle RetVal;

1150      Instruction *I = CS.getInstruction();

1151      if (isa<PointerType >(I->getType()))

1152        RetVal = getValueDest(I);

1153 

1154      // Calculatethe arguments vector...

1155      for(CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)

1156        if (isa<PointerType >((*I)->getType()))

1157          RetVal.mergeWith(getValueDest(*I));

1158      if (!RetVal.isNull())

1159        RetVal.getNode()->foldNodeCompletely();

1160      return;

1161    }

1162 

1163    // Set up thereturn value...

1164    DSNodeHandle RetVal;

1165    Instruction *I = CS.getInstruction();

1166    if (isa<PointerType>(I->getType()))

1167      RetVal = getValueDest(I);

1168 

1169    DSNode *CalleeNode = 0;

1170    if (!isa<Function>(Callee)) {

1171      CalleeNode = getValueDest(Callee).getNode();

1172      if (CalleeNode == 0) {

1173        DEBUG(errs() << "WARNING:Program is calling through a null pointer?\n" << *I);

1174        return// Calling a nullpointer?

1175      }

1176    }

1177 

1178    // NOTE: Thiscode is identical to 'DSGraph::getDSCallSiteForCallSite',

1179    // the reasonit's duplicated is because this calls getValueDest instead

1180    // ofgetNodeForValue to get the DSNodes for the arguments.  Since we're in

1181    // local it'spossible that we need to create a DSNode for the argument, as

1182    // opposed togetNodeForValue which simply retrieves the existing node.

1183 

1184 

1185    //Get theFunctionType for the called function

1186    constFunctionType *CalleeFuncType = DSCallSite::FunctionTypeOfCallSite(CS);

1187    int NumFixedArgs =CalleeFuncType->getNumParams();

1188 

1189    // Sanitycheck--this really, really shouldn't happen

1190    if (!CalleeFuncType->isVarArg())

1191      assert(CS.arg_size()== static_cast<unsigned>(NumFixedArgs)&&

1192             "Too many arguments/incorrectfunction signature!");

1193 

1194    std::vector<DSNodeHandle> Args;

1195    Args.reserve(CS.arg_size());

1196    DSNodeHandle VarArgNH;

1197 

1198    // Calculate thearguments vector...

1199    // Add all fixedpointer arguments, then merge the rest together

1200    for(CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();

1201         I != E; ++I)

1202      if(isa<PointerType>((*I)->getType())) {

1203        DSNodeHandle ArgNode = getValueDest(*I);

1204        if (I - CS.arg_begin() < NumFixedArgs){

1205          Args.push_back(ArgNode);

1206        } else {

1207          VarArgNH.mergeWith(ArgNode);

1208        }

1209      }

1210 

1211    // Add a newfunction call entry...

1212    if (CalleeNode) {

1213      ++NumIndirectCall;

1214     G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, VarArgNH,CalleeNode,

1215                                               Args));

1216    } else {

1217      ++NumDirectCall;

1218      G.getFunctionCalls().push_back(DSCallSite(CS,RetVal, VarArgNH,

1219                                               cast<Function>(Callee),

1220                                               Args));

1221    }

1222 

1223 

1224  }

 

在DSGraph值专门有一个域FunctionCalls记录有关函数调用的DSA节点。这个域的类型是std::list<DSCallSite>,而类型DSCallSite有如下成员:

 

160      typedefstd::set<CallSite> MappedSites_t;

161    private:

162      CallSite        Site;               //Actual call site

163      constFunction *CalleeF;            // The functioncalled (direct call)

164      DSNodeHandle    CalleeN;            // Thefunction node called (indirect call)

165      DSNodeHandle    RetVal;             //Returned value

166      DSNodeHandle    VarArgVal;          // Mergedvar-arg val

167      std::vector<DSNodeHandle> CallArgs; // The pointer arguments

168      MappedSites_t MappedSites;          // Themerged callsites

 

这些成员的含义,注释已经说得很清楚。1214及1218行调用了下面这两个构造函数:

 

199      DSCallSite(CallSite CS, const DSNodeHandle &rv, constDSNodeHandle &va,

200                 DSNode *Callee,std::vector<DSNodeHandle> &Args)

201        : Site(CS), CalleeF(0), CalleeN(Callee),RetVal(rv), VarArgVal(va) {

202        assert(Callee&& "Null callee node specified for call site!");

203        Args.swap(CallArgs);

204      }

205      DSCallSite(CallSite CS, const DSNodeHandle &rv, constDSNodeHandle &va,

206                 constFunction *Callee, std::vector<DSNodeHandle> &Args)

207        : Site(CS), CalleeF(Callee), RetVal(rv),VarArgVal(va) {

208        assert(Callee&& "Null callee function specified for call site!");

209        Args.swap(CallArgs);

210      }

 

在1214行CalleeNode被设置到CalleeN,而在1218行,Callee被设置到CalleeF。

1.3.3.4.1.1.16. 对其他指令的处理

根据基类InstVisitor的安排,所有没有重载的visit*函数,都最终会进入visitInstruction函数。对于DSA,只关心Inst的类型。如果它是指针类型,意味着其返回值与其指针类型的操作数可能互为别名,于是将它们简并起来。

 

1229  void GraphBuilder::visitInstruction(Instruction&Inst) {

1230    DSNodeHandle CurNode;

1231    if (isa<PointerType>(Inst.getType()))

1232      CurNode = getValueDest(&Inst);

1233    for(User::op_iterator I = Inst.op_begin(), E = Inst.op_end(); I != E; ++I)

1234      if(isa<PointerType>((*I)->getType()))

1235        CurNode.mergeWith(getValueDest(*I));

1236 

1237    if (DSNode *N = CurNode.getNode())

1238      N->setUnknownMarker();

1239  }

 

如果CurNode不是指向null,把这个DSNode标记为unknown,而不是Incomplete。这是Chris在论文中强调过的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值