svf-tools 1.0.961 → 1.0.963

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.961",
3
+ "version": "1.0.963",
4
4
  "description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -739,9 +739,6 @@ void CHGBuilder::addFuncToFuncVector(CHNode::FuncVector &v, const Function *lf)
739
739
  {
740
740
  SVFFunction* pFunction =
741
741
  LLVMModuleSet::getLLVMModuleSet()->getSVFFunction(tf);
742
- cppUtil::DemangledName dname = cppUtil::demangle(pFunction->getName());
743
- string calleeName = dname.funcName;
744
- pFunction->setName(calleeName);
745
742
  v.push_back(pFunction);
746
743
  }
747
744
  }
@@ -749,9 +746,6 @@ void CHGBuilder::addFuncToFuncVector(CHNode::FuncVector &v, const Function *lf)
749
746
  {
750
747
  SVFFunction* pFunction =
751
748
  LLVMModuleSet::getLLVMModuleSet()->getSVFFunction(lf);
752
- cppUtil::DemangledName dname = cppUtil::demangle(pFunction->getName());
753
- string calleeName = dname.funcName;
754
- pFunction->setName(calleeName);
755
749
  v.push_back(pFunction);
756
750
  }
757
751
  }
@@ -161,271 +161,325 @@ const Type *ObjTypeInference::inferObjType(const Value *var)
161
161
  */
162
162
  const Type *ObjTypeInference::fwInferObjType(const Value *var)
163
163
  {
164
- // consult cache
165
- auto tIt = _valueToType.find(var);
166
- if (tIt != _valueToType.end())
164
+ if (const AllocaInst *allocaInst = SVFUtil::dyn_cast<AllocaInst>(var))
167
165
  {
168
- return tIt->second ? tIt->second : defaultType(var);
166
+ // stack object
167
+ return infersiteToType(allocaInst);
169
168
  }
170
-
171
- // simulate the call stack, the second element indicates whether we should update valueTypes for current value
172
- FILOWorkList<ValueBoolPair> workList;
173
- Set<ValueBoolPair> visited;
174
- workList.push({var, false});
175
-
176
- while (!workList.empty())
169
+ else if (const GlobalValue *global = SVFUtil::dyn_cast<GlobalValue>(var))
177
170
  {
178
- auto curPair = workList.pop();
179
- if (visited.count(curPair)) continue;
180
- visited.insert(curPair);
181
- const Value *curValue = curPair.first;
182
- bool canUpdate = curPair.second;
183
- Set<const Value *> infersites;
171
+ // global object
172
+ return infersiteToType(global);
173
+ }
174
+ else
175
+ {
176
+ // for heap or static object, we forward infer its type
184
177
 
185
- auto insertInferSite = [&infersites, &canUpdate](const Value *infersite)
178
+ // consult cache
179
+ auto tIt = _valueToType.find(var);
180
+ if (tIt != _valueToType.end())
186
181
  {
187
- if (canUpdate) infersites.insert(infersite);
188
- };
189
- auto insertInferSitesOrPushWorklist = [this, &infersites, &workList, &canUpdate](const auto &pUser)
182
+ return tIt->second ? tIt->second : defaultType(var);
183
+ }
184
+
185
+ // simulate the call stack, the second element indicates whether we should update valueTypes for current value
186
+ FILOWorkList<ValueBoolPair> workList;
187
+ Set<ValueBoolPair> visited;
188
+ workList.push({var, false});
189
+
190
+ while (!workList.empty())
190
191
  {
191
- auto vIt = _valueToInferSites.find(pUser);
192
- if (canUpdate)
192
+ auto curPair = workList.pop();
193
+ if (visited.count(curPair))
194
+ continue;
195
+ visited.insert(curPair);
196
+ const Value* curValue = curPair.first;
197
+ bool canUpdate = curPair.second;
198
+ Set<const Value*> infersites;
199
+
200
+ auto insertInferSite = [&infersites,
201
+ &canUpdate](const Value* infersite)
193
202
  {
194
- if (vIt != _valueToInferSites.end())
203
+ if (canUpdate)
204
+ infersites.insert(infersite);
205
+ };
206
+ auto insertInferSitesOrPushWorklist =
207
+ [this, &infersites, &workList, &canUpdate](const auto& pUser)
208
+ {
209
+ auto vIt = _valueToInferSites.find(pUser);
210
+ if (canUpdate)
195
211
  {
196
- infersites.insert(vIt->second.begin(), vIt->second.end());
212
+ if (vIt != _valueToInferSites.end())
213
+ {
214
+ infersites.insert(vIt->second.begin(),
215
+ vIt->second.end());
216
+ }
197
217
  }
198
- }
199
- else
200
- {
201
- if (vIt == _valueToInferSites.end()) workList.push({pUser, false});
202
- }
203
- };
204
- if (!canUpdate && !_valueToInferSites.count(curValue))
205
- {
206
- workList.push({curValue, true});
207
- }
208
- if (const auto *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(curValue))
209
- insertInferSite(gepInst);
210
- for (const auto it: curValue->users())
211
- {
212
- if (const auto *loadInst = SVFUtil::dyn_cast<LoadInst>(it))
218
+ else
219
+ {
220
+ if (vIt == _valueToInferSites.end())
221
+ workList.push({pUser, false});
222
+ }
223
+ };
224
+ if (!canUpdate && !_valueToInferSites.count(curValue))
213
225
  {
214
- /*
215
- * infer based on load, e.g.,
216
- %call = call i8* malloc()
217
- %1 = bitcast i8* %call to %struct.MyStruct*
218
- %q = load %struct.MyStruct, %struct.MyStruct* %1
219
- */
220
- insertInferSite(loadInst);
226
+ workList.push({curValue, true});
221
227
  }
222
- else if (const auto *storeInst = SVFUtil::dyn_cast<StoreInst>(it))
228
+ if (const auto* gepInst =
229
+ SVFUtil::dyn_cast<GetElementPtrInst>(curValue))
230
+ insertInferSite(gepInst);
231
+ for (const auto it : curValue->users())
223
232
  {
224
- if (storeInst->getPointerOperand() == curValue)
233
+ if (const auto* loadInst = SVFUtil::dyn_cast<LoadInst>(it))
225
234
  {
226
235
  /*
227
- * infer based on store (pointer operand), e.g.,
236
+ * infer based on load, e.g.,
228
237
  %call = call i8* malloc()
229
238
  %1 = bitcast i8* %call to %struct.MyStruct*
230
- store %struct.MyStruct .., %struct.MyStruct* %1
239
+ %q = load %struct.MyStruct, %struct.MyStruct* %1
231
240
  */
232
- insertInferSite(storeInst);
241
+ insertInferSite(loadInst);
233
242
  }
234
- else
243
+ else if (const auto* storeInst =
244
+ SVFUtil::dyn_cast<StoreInst>(it))
235
245
  {
236
- for (const auto nit: storeInst->getPointerOperand()->users())
246
+ if (storeInst->getPointerOperand() == curValue)
237
247
  {
238
248
  /*
239
- * propagate across store (value operand) and load
249
+ * infer based on store (pointer operand), e.g.,
240
250
  %call = call i8* malloc()
241
- store i8* %call, i8** %p
242
- %q = load i8*, i8** %p
243
- ..infer based on %q..
244
- */
245
- if (SVFUtil::isa<LoadInst>(nit))
246
- insertInferSitesOrPushWorklist(nit);
251
+ %1 = bitcast i8* %call to %struct.MyStruct*
252
+ store %struct.MyStruct .., %struct.MyStruct* %1
253
+ */
254
+ insertInferSite(storeInst);
247
255
  }
248
- /*
249
- * infer based on store (value operand) <- gep (result element)
250
- */
251
- if (const auto *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(
252
- storeInst->getPointerOperand()))
256
+ else
253
257
  {
258
+ for (const auto nit :
259
+ storeInst->getPointerOperand()->users())
260
+ {
261
+ /*
262
+ * propagate across store (value operand) and load
263
+ %call = call i8* malloc()
264
+ store i8* %call, i8** %p
265
+ %q = load i8*, i8** %p
266
+ ..infer based on %q..
267
+ */
268
+ if (SVFUtil::isa<LoadInst>(nit))
269
+ insertInferSitesOrPushWorklist(nit);
270
+ }
254
271
  /*
255
- %call1 = call i8* @TYPE_MALLOC(i32 noundef 16, i32 noundef 2), !dbg !39
256
- %2 = bitcast i8* %call1 to %struct.MyStruct*, !dbg !41
257
- %3 = load %struct.MyStruct*, %struct.MyStruct** %p, align 8, !dbg !42
258
- %next = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %3, i32 0, i32 1, !dbg !43
259
- store %struct.MyStruct* %2, %struct.MyStruct** %next, align 8, !dbg !44
260
- %5 = load %struct.MyStruct*, %struct.MyStruct** %p, align 8, !dbg !48
261
- %next3 = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %5, i32 0, i32 1, !dbg !49
262
- %6 = load %struct.MyStruct*, %struct.MyStruct** %next3, align 8, !dbg !49
263
- infer site -> %f1 = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %6, i32 0, i32 0, !dbg !50
272
+ * infer based on store (value operand) <- gep (result element)
264
273
  */
265
- const Value *gepBase = gepInst->getPointerOperand();
266
- if(const auto *load = SVFUtil::dyn_cast<LoadInst>(gepBase))
274
+ if (const auto* gepInst =
275
+ SVFUtil::dyn_cast<GetElementPtrInst>(
276
+ storeInst->getPointerOperand()))
267
277
  {
268
- for (const auto loadUse: load->getPointerOperand()->users())
278
+ /*
279
+ %call1 = call i8* @TYPE_MALLOC(i32 noundef 16, i32
280
+ noundef 2), !dbg !39 %2 = bitcast i8* %call1 to
281
+ %struct.MyStruct*, !dbg !41 %3 = load
282
+ %struct.MyStruct*, %struct.MyStruct** %p, align 8,
283
+ !dbg !42 %next = getelementptr inbounds
284
+ %struct.MyStruct, %struct.MyStruct* %3, i32 0, i32
285
+ 1, !dbg !43 store %struct.MyStruct* %2,
286
+ %struct.MyStruct** %next, align 8, !dbg !44 %5 =
287
+ load %struct.MyStruct*, %struct.MyStruct** %p,
288
+ align 8, !dbg !48 %next3 = getelementptr inbounds
289
+ %struct.MyStruct, %struct.MyStruct* %5, i32 0, i32
290
+ 1, !dbg !49 %6 = load %struct.MyStruct*,
291
+ %struct.MyStruct** %next3, align 8, !dbg !49 infer
292
+ site -> %f1 = getelementptr inbounds
293
+ %struct.MyStruct, %struct.MyStruct* %6, i32 0, i32
294
+ 0, !dbg !50
295
+ */
296
+ const Value* gepBase = gepInst->getPointerOperand();
297
+ if (const auto* load =
298
+ SVFUtil::dyn_cast<LoadInst>(gepBase))
269
299
  {
270
- if (loadUse == load || !SVFUtil::isa<LoadInst>(loadUse))
271
- continue;
272
- for (const auto gepUse: loadUse->users())
300
+ for (const auto loadUse :
301
+ load->getPointerOperand()->users())
273
302
  {
274
- if (!SVFUtil::isa<GetElementPtrInst>(gepUse)) continue;
275
- for (const auto loadUse2: gepUse->users())
303
+ if (loadUse == load ||
304
+ !SVFUtil::isa<LoadInst>(loadUse))
305
+ continue;
306
+ for (const auto gepUse : loadUse->users())
276
307
  {
277
- if (SVFUtil::isa<LoadInst>(loadUse2))
308
+ if (!SVFUtil::isa<GetElementPtrInst>(
309
+ gepUse))
310
+ continue;
311
+ for (const auto loadUse2 :
312
+ gepUse->users())
278
313
  {
279
- insertInferSitesOrPushWorklist(loadUse2);
314
+ if (SVFUtil::isa<LoadInst>(
315
+ loadUse2))
316
+ {
317
+ insertInferSitesOrPushWorklist(
318
+ loadUse2);
319
+ }
280
320
  }
281
321
  }
282
322
  }
283
323
  }
284
- }
285
- else if (const auto *alloc = SVFUtil::dyn_cast<AllocaInst>(gepBase))
286
- {
287
- /*
288
- %2 = alloca %struct.ll, align 8
289
- store i32 0, ptr %1, align 4
290
- %3 = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #2
291
- %4 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1
292
- store ptr %3, ptr %4, align 8
293
- %5 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1
294
- %6 = load ptr, ptr %5, align 8
295
- %7 = getelementptr inbounds %struct.ll, ptr %6, i32 0, i32 0
296
- */
297
- for (const auto gepUse: alloc->users())
324
+ else if (const auto* alloc =
325
+ SVFUtil::dyn_cast<AllocaInst>(gepBase))
298
326
  {
299
- if (!SVFUtil::isa<GetElementPtrInst>(gepUse)) continue;
300
- for (const auto loadUse2: gepUse->users())
327
+ /*
328
+ %2 = alloca %struct.ll, align 8
329
+ store i32 0, ptr %1, align 4
330
+ %3 = call noalias noundef nonnull ptr
331
+ @_Znwm(i64 noundef 16) #2 %4 = getelementptr
332
+ inbounds %struct.ll, ptr %2, i32 0, i32 1
333
+ store ptr %3, ptr %4, align 8
334
+ %5 = getelementptr inbounds %struct.ll, ptr
335
+ %2, i32 0, i32 1 %6 = load ptr, ptr %5, align
336
+ 8 %7 = getelementptr inbounds %struct.ll, ptr
337
+ %6, i32 0, i32 0
338
+ */
339
+ for (const auto gepUse : alloc->users())
301
340
  {
302
- if (SVFUtil::isa<LoadInst>(loadUse2))
341
+ if (!SVFUtil::isa<GetElementPtrInst>(
342
+ gepUse))
343
+ continue;
344
+ for (const auto loadUse2 : gepUse->users())
303
345
  {
304
- insertInferSitesOrPushWorklist(loadUse2);
346
+ if (SVFUtil::isa<LoadInst>(loadUse2))
347
+ {
348
+ insertInferSitesOrPushWorklist(
349
+ loadUse2);
350
+ }
305
351
  }
306
352
  }
307
353
  }
308
354
  }
309
355
  }
310
356
  }
311
-
312
- }
313
- else if (const auto *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(it))
314
- {
315
- /*
316
- * infer based on gep (pointer operand)
317
- %call = call i8* malloc()
318
- %1 = bitcast i8* %call to %struct.MyStruct*
319
- %next = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %1, i32 0..
320
- */
321
- if (gepInst->getPointerOperand() == curValue)
322
- insertInferSite(gepInst);
323
- }
324
- else if (const auto *bitcast = SVFUtil::dyn_cast<BitCastInst>(it))
325
- {
326
- // continue on bitcast
327
- insertInferSitesOrPushWorklist(bitcast);
328
- }
329
- else if (const auto *phiNode = SVFUtil::dyn_cast<PHINode>(it))
330
- {
331
- // continue on bitcast
332
- insertInferSitesOrPushWorklist(phiNode);
333
- }
334
- else if (const auto *retInst = SVFUtil::dyn_cast<ReturnInst>(it))
335
- {
336
- /*
337
- * propagate from return to caller
338
- Function Attrs: noinline nounwind optnone uwtable
339
- define dso_local i8* @malloc_wrapper() #0 !dbg !22 {
340
- entry:
341
- %call = call i8* @malloc(i32 noundef 16), !dbg !25
342
- ret i8* %call, !dbg !26
343
- }
344
- %call = call i8* @malloc_wrapper()
345
- ..infer based on %call..
346
- */
347
- for (const auto callsite: retInst->getFunction()->users())
357
+ else if (const auto* gepInst =
358
+ SVFUtil::dyn_cast<GetElementPtrInst>(it))
348
359
  {
349
- if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(callsite))
360
+ /*
361
+ * infer based on gep (pointer operand)
362
+ %call = call i8* malloc()
363
+ %1 = bitcast i8* %call to %struct.MyStruct*
364
+ %next = getelementptr inbounds %struct.MyStruct,
365
+ %struct.MyStruct* %1, i32 0..
366
+ */
367
+ if (gepInst->getPointerOperand() == curValue)
368
+ insertInferSite(gepInst);
369
+ }
370
+ else if (const auto* bitcast =
371
+ SVFUtil::dyn_cast<BitCastInst>(it))
372
+ {
373
+ // continue on bitcast
374
+ insertInferSitesOrPushWorklist(bitcast);
375
+ }
376
+ else if (const auto* phiNode = SVFUtil::dyn_cast<PHINode>(it))
377
+ {
378
+ // continue on bitcast
379
+ insertInferSitesOrPushWorklist(phiNode);
380
+ }
381
+ else if (const auto* retInst =
382
+ SVFUtil::dyn_cast<ReturnInst>(it))
383
+ {
384
+ /*
385
+ * propagate from return to caller
386
+ Function Attrs: noinline nounwind optnone uwtable
387
+ define dso_local i8* @malloc_wrapper() #0 !dbg !22 {
388
+ entry:
389
+ %call = call i8* @malloc(i32 noundef 16), !dbg !25
390
+ ret i8* %call, !dbg !26
391
+ }
392
+ %call = call i8* @malloc_wrapper()
393
+ ..infer based on %call..
394
+ */
395
+ for (const auto callsite : retInst->getFunction()->users())
350
396
  {
351
- // skip function as parameter
352
- // e.g., call void @foo(%struct.ssl_ctx_st* %9, i32 (i8*, i32, i32, i8*)* @passwd_callback)
353
- if (callBase->getCalledFunction() != retInst->getFunction()) continue;
354
- insertInferSitesOrPushWorklist(callBase);
397
+ if (const auto* callBase =
398
+ SVFUtil::dyn_cast<CallBase>(callsite))
399
+ {
400
+ // skip function as parameter
401
+ // e.g., call void @foo(%struct.ssl_ctx_st* %9, i32 (i8*, i32, i32, i8*)* @passwd_callback)
402
+ if (callBase->getCalledFunction() !=
403
+ retInst->getFunction())
404
+ continue;
405
+ insertInferSitesOrPushWorklist(callBase);
406
+ }
355
407
  }
356
408
  }
357
- }
358
- else if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(it))
359
- {
360
- /*
361
- * propagate from callsite to callee
362
- %call = call i8* @malloc(i32 noundef 16)
363
- %0 = bitcast i8* %call to %struct.Node*, !dbg !43
364
- call void @foo(%struct.Node* noundef %0), !dbg !45
365
-
366
- define dso_local void @foo(%struct.Node* noundef %param) #0 !dbg !22 {...}
367
- ..infer based on the formal param %param..
368
- */
369
- // skip global function value -> callsite
370
- // e.g., def @foo() -> call @foo()
371
- // we don't skip function as parameter, e.g., def @foo() -> call @bar(..., @foo)
372
- if (SVFUtil::isa<Function>(curValue) && curValue == callBase->getCalledFunction()) continue;
373
- // skip indirect call
374
- // e.g., %0 = ... -> call %0(...)
375
- if (!callBase->hasArgument(curValue)) continue;
376
- if (Function *calleeFunc = callBase->getCalledFunction())
409
+ else if (const auto* callBase = SVFUtil::dyn_cast<CallBase>(it))
377
410
  {
378
- u32_t pos = getArgPosInCall(callBase, curValue);
379
- // for varargs function, we cannot directly get the value-flow between actual and formal args
380
- // e.g., consider the following vararg function @callee
381
- // 1: call void @callee(%arg)
382
- // 2: define dso_local i32 @callee(...) #0 !dbg !17 {
383
- // 3: .......
384
- // 4: %5 = load i32, ptr %vaarg.addr, align 4, !dbg !55
385
- // 5: .......
386
- // 6: }
387
- // it is challenging to precisely identify the forward value-flow of %arg (Line 2)
388
- // because the function definition of callee (Line 2) does not have any formal args related to the actual arg %arg
389
- // therefore we track all possible instructions like ``load i32, ptr %vaarg.addr''
390
- if (calleeFunc->isVarArg())
411
+ /*
412
+ * propagate from callsite to callee
413
+ %call = call i8* @malloc(i32 noundef 16)
414
+ %0 = bitcast i8* %call to %struct.Node*, !dbg !43
415
+ call void @foo(%struct.Node* noundef %0), !dbg !45
416
+
417
+ define dso_local void @foo(%struct.Node* noundef %param)
418
+ #0 !dbg !22 {...}
419
+ ..infer based on the formal param %param..
420
+ */
421
+ // skip global function value -> callsite
422
+ // e.g., def @foo() -> call @foo()
423
+ // we don't skip function as parameter, e.g., def @foo() -> call @bar(..., @foo)
424
+ if (SVFUtil::isa<Function>(curValue) &&
425
+ curValue == callBase->getCalledFunction())
426
+ continue;
427
+ // skip indirect call
428
+ // e.g., %0 = ... -> call %0(...)
429
+ if (!callBase->hasArgument(curValue))
430
+ continue;
431
+ if (Function* calleeFunc = callBase->getCalledFunction())
391
432
  {
392
- // conservatively track all var args
393
- for (auto &I: instructions(calleeFunc))
433
+ u32_t pos = getArgPosInCall(callBase, curValue);
434
+ // for varargs function, we cannot directly get the value-flow between actual and formal args e.g., consider the following vararg function @callee 1: call void @callee(%arg) 2: define dso_local i32 @callee(...) #0 !dbg !17 { 3: ....... 4: %5 = load i32, ptr %vaarg.addr, align 4, !dbg !55 5: .......
435
+ // 6: }
436
+ // it is challenging to precisely identify the forward value-flow of %arg (Line 2) because the function definition of callee (Line 2) does not have any formal args related to the actual arg %arg therefore we track all possible instructions like ``load i32, ptr %vaarg.addr''
437
+ if (calleeFunc->isVarArg())
394
438
  {
395
- if (auto *load = llvm::dyn_cast<llvm::LoadInst>(&I))
439
+ // conservatively track all var args
440
+ for (auto& I : instructions(calleeFunc))
396
441
  {
397
- llvm::Value* loadPointer = load->getPointerOperand();
398
- if (loadPointer->getName().compare("vaarg.addr") == 0)
442
+ if (auto* load =
443
+ llvm::dyn_cast<llvm::LoadInst>(&I))
399
444
  {
400
- insertInferSitesOrPushWorklist(load);
445
+ llvm::Value* loadPointer =
446
+ load->getPointerOperand();
447
+ if (loadPointer->getName().compare(
448
+ "vaarg.addr") == 0)
449
+ {
450
+ insertInferSitesOrPushWorklist(load);
451
+ }
401
452
  }
402
453
  }
403
454
  }
404
- }
405
- else if (!calleeFunc->isDeclaration())
406
- {
407
- insertInferSitesOrPushWorklist(calleeFunc->getArg(pos));
455
+ else if (!calleeFunc->isDeclaration())
456
+ {
457
+ insertInferSitesOrPushWorklist(
458
+ calleeFunc->getArg(pos));
459
+ }
408
460
  }
409
461
  }
410
462
  }
463
+ if (canUpdate)
464
+ {
465
+ Set<const Type*> types;
466
+ std::transform(infersites.begin(), infersites.end(),
467
+ std::inserter(types, types.begin()),
468
+ infersiteToType);
469
+ _valueToInferSites[curValue] = SVFUtil::move(infersites);
470
+ _valueToType[curValue] = selectLargestSizedType(types);
471
+ }
411
472
  }
412
- if (canUpdate)
473
+ const Type* type = _valueToType[var];
474
+ if (type == nullptr)
413
475
  {
414
- Set<const Type *> types;
415
- std::transform(infersites.begin(), infersites.end(), std::inserter(types, types.begin()),
416
- infersiteToType);
417
- _valueToInferSites[curValue] = SVFUtil::move(infersites);
418
- _valueToType[curValue] = selectLargestSizedType(types);
476
+ type = defaultType(var);
477
+ WARN_MSG("Using default type, trace ID is " +
478
+ std::to_string(traceId) + ":" + dumpValueAndDbgInfo(var));
419
479
  }
480
+ ABORT_IFNOT(type, "type cannot be a null ptr");
481
+ return type;
420
482
  }
421
- const Type *type = _valueToType[var];
422
- if (type == nullptr)
423
- {
424
- type = defaultType(var);
425
- WARN_MSG("Using default type, trace ID is " + std::to_string(traceId) + ":" + dumpValueAndDbgInfo(var));
426
- }
427
- ABORT_IFNOT(type, "type cannot be a null ptr");
428
- return type;
429
483
  }
430
484
 
431
485
  /*!