svf-tools 1.0.730 → 1.0.731

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.
@@ -348,44 +348,116 @@ cJSON* ExtAPI::get_FunJson(const std::string& funName)
348
348
  return cJSON_GetObjectItemCaseSensitive(root, funName.c_str());
349
349
  }
350
350
 
351
+ ExtAPI::Operand ExtAPI::getBasicOperation(cJSON* obj)
352
+ {
353
+ Operand basicOp;
354
+ if (strstr(obj->string, "AddrStmt") != NULL)
355
+ basicOp.setType(ExtAPI::OperationType::Addr);
356
+ else if (strstr(obj->string, "CopyStmt") != NULL)
357
+ basicOp.setType(ExtAPI::OperationType::Copy);
358
+ else if (strstr(obj->string, "LoadStmt") != NULL)
359
+ basicOp.setType(ExtAPI::OperationType::Load);
360
+ else if (strstr(obj->string, "StoreStmt") != NULL)
361
+ basicOp.setType(ExtAPI::OperationType::Store);
362
+ else if (strstr(obj->string, "GepStmt") != NULL)
363
+ basicOp.setType(ExtAPI::OperationType::Gep);
364
+ else if (strstr(obj->string, "ReturnStmt") != NULL)
365
+ basicOp.setType(ExtAPI::OperationType::Return);
366
+ else if (strstr(obj->string, "Rb_tree_ops") != NULL)
367
+ basicOp.setType(ExtAPI::OperationType::Rb_tree_ops);
368
+ else if (strstr(obj->string, "memcpy_like") != NULL)
369
+ basicOp.setType(ExtAPI::OperationType::Memcpy_like);
370
+ else if (strstr(obj->string, "memset_like") != NULL)
371
+ basicOp.setType(ExtAPI::OperationType::Memset_like);
372
+ else
373
+ assert(false && "Unknown operation type");
374
+
375
+ cJSON* value = obj->child;
376
+ while (value)
377
+ {
378
+ if (strcmp(value->string, "src") == 0)
379
+ basicOp.setSrcValue(value->valuestring);
380
+ else if (strcmp(value->string, "dst") == 0)
381
+ basicOp.setDstValue(value->valuestring);
382
+ else if (strcmp(value->string, "offset") == 0 || strcmp(value->string, "size") == 0)
383
+ basicOp.setOffsetOrSizeStr(value->valuestring);
384
+ else
385
+ assert(false && "Unknown operation value");
386
+ value = value->next;
387
+ }
388
+ return basicOp;
389
+ }
390
+
351
391
  // Get all operations of an extern function
352
- std::vector<ExtAPI::Operation> ExtAPI::getAllOperations(std::string funName)
392
+ ExtAPI::ExtFunctionOps ExtAPI::getExtFunctionOps(std::string funName)
353
393
  {
354
- std::vector<ExtAPI::Operation> allOperations;
394
+ auto it = extFunToOps.find(funName);
395
+ if (it != extFunToOps.end())
396
+ return it->second;
397
+
398
+ ExtAPI::ExtFunctionOps extFunctionOps;
399
+ extFunctionOps.setExtFunName(funName);
355
400
  cJSON* item = get_FunJson(funName);
356
401
  if (item != nullptr)
357
402
  {
358
403
  cJSON* obj = item->child;
359
404
  // Get the first operation of the function
360
405
  obj = obj->next->next->next->next;
361
- std::vector<ExtAPI::Operation*> operations;
362
406
  while (obj)
363
407
  {
364
- std::string op;
365
- std::vector<std::string> operandsStr;
366
- std::map<std::string, NodeID> opMap;
408
+ ExtOperation operation;
367
409
  if (obj->type == cJSON_Object || obj->type == cJSON_Array)
368
410
  {
369
- op = get_opName(obj->string);
370
- cJSON* value = obj->child;
371
- std::vector<std::string> args;
372
- while (value)
411
+ if (strstr(obj->string, "CallStmt") != NULL)
373
412
  {
374
- if (value->type == cJSON_String)
413
+ extFunctionOps.setCallStmtNum(extFunctionOps.getCallStmtNum() + 1);
414
+ operation.setCallOp(true);
415
+ cJSON* value = obj->child;
416
+ while (value)
375
417
  {
376
- operandsStr.push_back(value->valuestring);
418
+ if (strcmp(value->string, "callee_name") == 0)
419
+ operation.setCalleeName(value->valuestring);
420
+ else if (strcmp(value->string, "callee_return") == 0)
421
+ operation.setCalleeReturn(value->valuestring);
422
+ else if (strcmp(value->string, "callee_arguments") == 0)
423
+ operation.setCalleeArguments(value->valuestring);
424
+ else
425
+ operation.getCalleeOperands().push_back(getBasicOperation(value));
426
+ value = value->next;
377
427
  }
378
- value = value->next;
379
428
  }
429
+ else if (strstr(obj->string, "CondStmt") != NULL)
430
+ {
431
+ operation.setConOp(true);
432
+ obj = obj->child;
433
+ assert(strcmp(obj->string, "Condition") == 0 && "Unknown operation type");
434
+ operation.setConOp(obj->valuestring);
435
+ obj = obj->next;
436
+ assert(strcmp(obj->string, "TrueBranch") == 0 && "Unknown operation type");
437
+ cJSON* value = obj->child;
438
+ while (value)
439
+ {
440
+ operation.getTrueBranchOperands().push_back(getBasicOperation(value));
441
+ value = value->next;
442
+ }
443
+ obj = obj->next;
444
+ assert(strcmp(obj->string, "FalseBranch") == 0&& "Unknown operation type");
445
+ value = obj->child;
446
+ while (value)
447
+ {
448
+ operation.getFalseBranchOperands().push_back(getBasicOperation(value));
449
+ value = value->next;
450
+ }
451
+ }
452
+ else
453
+ operation.setBasicOp(getBasicOperation(obj));
380
454
  }
381
- ExtAPI::Operation operation(op, operandsStr);
382
- allOperations.push_back(operation);
383
- operations.clear();
384
-
385
455
  obj = obj->next;
456
+ extFunctionOps.getOperations().push_back(operation);
386
457
  }
387
458
  }
388
- return allOperations;
459
+ extFunToOps[funName] = extFunctionOps;
460
+ return extFunctionOps;
389
461
  }
390
462
 
391
463
  // Get arguments of the operation, e.g. ["A1R", "A0", "A2"]
@@ -42,6 +42,7 @@ class SymbolTableInfo;
42
42
 
43
43
  class LLVMModuleSet
44
44
  {
45
+ friend class SVFIRBuilder;
45
46
 
46
47
  public:
47
48
 
@@ -224,9 +224,6 @@ protected:
224
224
  /// Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst, i8* src, int size))
225
225
  const Value* getBaseValueForExtArg(const Value* V);
226
226
 
227
- /// Get the base type and max offset
228
- const Type* getBaseTypeAndFlattenedFields(const Value* V, std::vector<LocationSet> &fields, const Value* sz);
229
-
230
227
  /// Handle direct call
231
228
  void handleDirectCall(CallBase* cs, const Function *F);
232
229
 
@@ -235,9 +232,17 @@ protected:
235
232
 
236
233
  /// Handle external call
237
234
  //@{
238
- virtual void parseOperations(std::vector<ExtAPI::Operation> &operations, const SVFCallInst* svfcall);
235
+ virtual SVFCallInst* addSVFExtCallInst(const SVFCallInst* svfInst, SVFBasicBlock* svfBB, const SVFFunction* svfCaller, const SVFFunction* svfCallee);
236
+ virtual void addSVFExtRetInst(SVFCallInst* svfCall, SVFBasicBlock* svfBB, SVFFunction* svfCaller);
237
+ virtual SVFInstruction* addSVFExtInst(const std::string& instName, const SVFCallInst* svfInst, SVFBasicBlock* svfBB, SVF::ExtAPI::OperationType opType, const SVFType* svfType);
238
+ virtual void extFuncAtomaticOperation(ExtAPI::Operand& atomicOp, const SVFCallInst* svfInst);
239
+ virtual SVFBasicBlock* extFuncInitialization(const SVFCallInst* svfInst, SVFFunction* svfCaller);
240
+ virtual void handleExtCallStat(ExtAPI::ExtFunctionOps &extFunctionOps, const SVFCallInst* svfInst);
241
+ virtual NodeID getExtID(ExtAPI::OperationType operationType, const std::string &s, const SVFCallInst* svfCall);
242
+ virtual void parseAtomaticOp(SVF::ExtAPI::Operand &atomaticOp, const SVFCallInst* svfCall, std::map<std::string, NodeID> &nodeIDMap);
243
+ virtual void parseExtFunctionOps(ExtAPI::ExtFunctionOps &extFunctionOps, const SVFCallInst* svfCall);
239
244
  virtual void preProcessExtCall(CallBase* cs);
240
- virtual void handleExtCall(SVFInstruction* svfinst, const SVFFunction* svfcallee);
245
+ virtual void handleExtCall(const SVFInstruction* svfInst, const SVFFunction* svfCallee);
241
246
  void addComplexConsForExt(const SVFValue* D, const SVFValue* S, const SVFValue* sz);
242
247
  //@}
243
248
 
@@ -1049,22 +1049,32 @@ std::string dumpLLVMValue(const SVFValue* svfValue)
1049
1049
  {
1050
1050
  std::string str;
1051
1051
  llvm::raw_string_ostream rawstr(str);
1052
- if (const SVF::SVFFunction* fun = SVFUtil::dyn_cast<SVFFunction>(svfValue))
1052
+ if (LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(svfValue) == nullptr)
1053
1053
  {
1054
- rawstr << "Function: " << fun->getName() << " ";
1055
- }
1056
- else if (const SVFBasicBlock* bb = SVFUtil::dyn_cast<SVFBasicBlock>(svfValue))
1057
- {
1058
- rawstr << "BasicBlock: " << bb->getName() << " ";
1054
+ assert((SVFUtil::isa<SVFInstruction>(svfValue) ||
1055
+ SVFUtil::isa<SVFBasicBlock>(svfValue)) && "Manually created SVF call inst, actual parameter and BasicBlock by ExtAPI do not have LLVM value!");
1056
+ rawstr << svfValue->getName();
1057
+ return rawstr.str();
1059
1058
  }
1060
1059
  else
1061
1060
  {
1062
- const Value* val =
1063
- LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(svfValue);
1064
- rawstr << " " << *val << " ";
1061
+ if (const SVF::SVFFunction* fun = SVFUtil::dyn_cast<SVFFunction>(svfValue))
1062
+ {
1063
+ rawstr << "Function: " << fun->getName() << " ";
1064
+ }
1065
+ else if (const SVFBasicBlock* bb = SVFUtil::dyn_cast<SVFBasicBlock>(svfValue))
1066
+ {
1067
+ rawstr << "BasicBlock: " << bb->getName() << " ";
1068
+ }
1069
+ else
1070
+ {
1071
+ const Value* val =
1072
+ LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(svfValue);
1073
+ rawstr << " " << *val << " ";
1074
+ }
1075
+ rawstr << svfValue->getSourceLoc();
1076
+ return rawstr.str();
1065
1077
  }
1066
- rawstr << svfValue->getSourceLoc();
1067
- return rawstr.str();
1068
1078
  }
1069
1079
 
1070
1080
  std::string dumpLLVMType(const SVFType* svfType)
@@ -848,8 +848,7 @@ void SVFIRBuilder::visitCallSite(CallBase* cs)
848
848
  {
849
849
  // There is no extpag for the function, use the old method.
850
850
  preProcessExtCall(cs);
851
- SVFInstruction* svfinst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(cs);
852
- handleExtCall(svfinst, svfcallee);
851
+ handleExtCall(svfcall, svfcallee);
853
852
  }
854
853
  else
855
854
  {
@@ -1115,184 +1114,6 @@ const Value* SVFIRBuilder::getBaseValueForExtArg(const Value* V)
1115
1114
  return value;
1116
1115
  }
1117
1116
 
1118
- /*!
1119
- * Find the base type and the max possible offset of an object pointed to by (V).
1120
- */
1121
- const Type* SVFIRBuilder::getBaseTypeAndFlattenedFields(const Value* V, std::vector<LocationSet> &fields, const Value* szValue)
1122
- {
1123
- assert(V);
1124
- const Value* value = getBaseValueForExtArg(V);
1125
- const Type* T = value->getType();
1126
- while (const PointerType *ptype = SVFUtil::dyn_cast<PointerType>(T))
1127
- T = getPtrElementType(ptype);
1128
-
1129
- u32_t numOfElems = pag->getSymbolInfo()->getNumOfFlattenElements(LLVMModuleSet::getLLVMModuleSet()->getSVFType(T));
1130
- /// use user-specified size for this copy operation if the size is a constaint int
1131
- if(szValue && SVFUtil::isa<ConstantInt>(szValue))
1132
- {
1133
- numOfElems = (numOfElems > SVFUtil::cast<ConstantInt>(szValue)->getSExtValue()) ? SVFUtil::cast<ConstantInt>(szValue)->getSExtValue() : numOfElems;
1134
- }
1135
-
1136
- LLVMContext& context = LLVMModuleSet::getLLVMModuleSet()->getContext();
1137
- for(u32_t ei = 0; ei < numOfElems; ei++)
1138
- {
1139
- LocationSet ls(ei);
1140
- // make a ConstantInt and create char for the content type due to byte-wise copy
1141
- const ConstantInt* offset = ConstantInt::get(context, llvm::APInt(32, ei));
1142
- const SVFValue* svfOffset = LLVMModuleSet::getLLVMModuleSet()->getSVFValue(offset);
1143
- if (!pag->getSymbolInfo()->hasValSym(svfOffset))
1144
- {
1145
- SymbolTableBuilder builder(pag->getSymbolInfo());
1146
- builder.collectSym(offset);
1147
- pag->addValNode(svfOffset, pag->getSymbolInfo()->getValSym(svfOffset));
1148
- }
1149
- ls.addOffsetVarAndGepTypePair(getPAG()->getGNode(getPAG()->getValueNode(svfOffset)), nullptr);
1150
- fields.push_back(ls);
1151
- }
1152
- return T;
1153
- }
1154
-
1155
- /*!
1156
- * Add the load/store constraints and temp. nodes for the complex constraint
1157
- * *D = *S (where D/S may point to structs).
1158
- */
1159
- void SVFIRBuilder::addComplexConsForExt(const SVFValue* D, const SVFValue* S, const SVFValue* szValue)
1160
- {
1161
- assert(D && S);
1162
- NodeID vnD= pag->getValueNode(D), vnS= pag->getValueNode(S);
1163
- if(!vnD || !vnS)
1164
- return;
1165
-
1166
- std::vector<LocationSet> fields;
1167
-
1168
- //Get the max possible size of the copy, unless it was provided.
1169
- const SVFType* stype = pag->getTypeLocSetsMap(vnS).first;
1170
- const SVFType* dtype = pag->getTypeLocSetsMap(vnD).first;
1171
- std::vector<LocationSet> srcFields = pag->getTypeLocSetsMap(vnS).second;
1172
- std::vector<LocationSet> dstFields = pag->getTypeLocSetsMap(vnD).second;
1173
-
1174
- if(srcFields.size() > dstFields.size())
1175
- fields = dstFields;
1176
- else
1177
- fields = srcFields;
1178
-
1179
- /// If sz is 0, we will add edges for all fields.
1180
- u32_t sz = fields.size();
1181
- if (szValue && SVFUtil::dyn_cast<SVFConstantInt>(szValue))
1182
- {
1183
- const SVFConstantInt* arg2 = SVFUtil::dyn_cast<SVFConstantInt>(szValue);
1184
- sz = (fields.size() > static_cast<u32_t>(arg2->getSExtValue())) ? arg2->getSExtValue() : fields.size();
1185
- }
1186
-
1187
- if (fields.size() == 1 && (SVFUtil::isa<SVFConstantData>(D) || SVFUtil::isa<SVFConstantData>(S)))
1188
- {
1189
- NodeID dummy = pag->addDummyValNode();
1190
- addLoadEdge(vnD,dummy);
1191
- addStoreEdge(dummy,vnS);
1192
- return;
1193
- }
1194
-
1195
- //For each field (i), add (Ti = *S + i) and (*D + i = Ti).
1196
- for (u32_t index = 0; index < sz; index++)
1197
- {
1198
- const SVFType* dElementType = pag->getSymbolInfo()->getFlatternedElemType(dtype,
1199
- fields[index].getConstantFieldIdx());
1200
- const SVFType* sElementType = pag->getSymbolInfo()->getFlatternedElemType(stype,
1201
- fields[index].getConstantFieldIdx());
1202
- NodeID dField = getGepValVar(D,fields[index],dElementType);
1203
- NodeID sField = getGepValVar(S,fields[index],sElementType);
1204
- NodeID dummy = pag->addDummyValNode();
1205
- addLoadEdge(sField,dummy);
1206
- addStoreEdge(dummy,dField);
1207
- }
1208
- }
1209
-
1210
- void SVFIRBuilder::parseOperations(std::vector<ExtAPI::Operation> &operations, const SVFCallInst* svfcall)
1211
- {
1212
- // Record all dummy nodes
1213
- std::map<std::string, NodeID> nodeIDMap;
1214
- for (ExtAPI::Operation& operation : operations)
1215
- {
1216
- std::vector<NodeID>& operands = operation.getOperands();
1217
- if (operation.getOperator() == "funptr_ops" || operation.getOperator() == "Rb_tree_ops")
1218
- continue;
1219
- for (const std::string& s : operation.getOperandStr())
1220
- {
1221
- // There is already a NodeID in nodeIDMap
1222
- if (nodeIDMap.find(s) != nodeIDMap.end())
1223
- operands.push_back(nodeIDMap[s]);
1224
- else
1225
- {
1226
- s32_t nodeIDType = ExtAPI::getExtAPI()->getNodeIDType(s);
1227
- // return value >= 0 is an argument node
1228
- if (nodeIDType >= 0)
1229
- {
1230
- if( svfcall->arg_size() <= (u32_t) nodeIDType)
1231
- assert(false && "Argument out of bounds!");
1232
- else if (operation.getOperator() == "memcpy_like" || operation.getOperator() == "memset_like")
1233
- {
1234
- operands.push_back(nodeIDType);
1235
- nodeIDMap[s] = nodeIDType;
1236
- }
1237
- else
1238
- {
1239
- operands.push_back(pag->getValueNode(svfcall->getArgOperand(nodeIDType)));
1240
- nodeIDMap[s] = pag->getValueNode(svfcall->getArgOperand(nodeIDType));
1241
- }
1242
- }
1243
- // return value = -1 is an inst node
1244
- else if (nodeIDType == -1)
1245
- {
1246
- operands.push_back(pag->getValueNode(svfcall));
1247
- nodeIDMap[s] = pag->getValueNode(svfcall);
1248
- }
1249
- // return value = -2 is a Dummy node
1250
- else if (nodeIDType == -2)
1251
- {
1252
- operands.push_back(pag->addDummyValNode());
1253
- nodeIDMap[s] = operands[operands.size() - 1];
1254
- }
1255
- // return value = -3 is an object node
1256
- else if (nodeIDType == -3)
1257
- {
1258
- if (svfcall->getType()->isPointerTy())
1259
- {
1260
- NodeID objId;
1261
- // Indirect call
1262
- if (getCallee(svfcall) == nullptr)
1263
- objId = pag->addDummyObjNode(svfcall->getType());
1264
- else // Direct call
1265
- objId = pag->getObjectNode(svfcall);
1266
-
1267
- operands.push_back(objId);
1268
- nodeIDMap[s] = objId;
1269
- }
1270
- }
1271
- // return value = -4 is a nullptr node
1272
- else if (nodeIDType == -4)
1273
- {
1274
- operands.push_back(pag->getNullPtr());
1275
- nodeIDMap[s] = operands[operands.size() - 1];
1276
- }
1277
- // return value = -5 is an offset
1278
- else if (nodeIDType == -5)
1279
- {
1280
- for (char const &c : s)
1281
- {
1282
- if (std::isdigit(c) == 0)
1283
- assert(false && "Invalid offset!");
1284
- }
1285
- operands.push_back(atoi(s.c_str()));
1286
- nodeIDMap[s] = atoi(s.c_str());
1287
- }
1288
- // return value = -6 is an illegal operand format
1289
- else
1290
- assert(false && "The operand format of function operation is illegal!");
1291
- }
1292
- }
1293
- }
1294
- }
1295
-
1296
1117
  void SVFIRBuilder::preProcessExtCall(CallBase* cs)
1297
1118
  {
1298
1119
  const SVFInstruction* svfinst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(cs);
@@ -1360,249 +1181,6 @@ void SVFIRBuilder::preProcessExtCall(CallBase* cs)
1360
1181
  }
1361
1182
  }
1362
1183
 
1363
- /*!
1364
- * Handle external calls
1365
- */
1366
- void SVFIRBuilder::handleExtCall(SVFInstruction* svfinst, const SVFFunction* svfcallee)
1367
- {
1368
- const SVFCallInst* svfcall = SVFUtil::cast<SVFCallInst>(svfinst);
1369
-
1370
- if (isHeapAllocOrStaticExtCall(svfinst))
1371
- {
1372
- // case 1: ret = new obj
1373
- if (isHeapAllocExtCallViaRet(svfinst) || isStaticExtCall(svfinst))
1374
- {
1375
- NodeID val = pag->getValueNode(svfinst);
1376
- NodeID obj = pag->getObjectNode(svfinst);
1377
- addAddrEdge(obj, val);
1378
- }
1379
- // case 2: *arg = new obj
1380
- else
1381
- {
1382
- assert(isHeapAllocExtCallViaArg(svfinst) && "Must be heap alloc call via arg.");
1383
- u32_t arg_pos = getHeapAllocHoldingArgPosition(svfcallee);
1384
- const SVFValue* arg = svfcall->getArgOperand(arg_pos);
1385
- if (arg->getType()->isPointerTy())
1386
- {
1387
- NodeID vnArg = pag->getValueNode(arg);
1388
- NodeID dummy = pag->addDummyValNode();
1389
- NodeID obj = pag->addDummyObjNode(arg->getType());
1390
- if (vnArg && dummy && obj)
1391
- {
1392
- addAddrEdge(obj, dummy);
1393
- addStoreEdge(dummy, vnArg);
1394
- }
1395
- }
1396
- else
1397
- {
1398
- writeWrnMsg("Arg receiving new object must be pointer type");
1399
- }
1400
- }
1401
- }
1402
- else
1403
- {
1404
- if (isExtCall(svfcallee))
1405
- {
1406
- std::string funName = ExtAPI::getExtAPI()->get_name(svfcallee);
1407
- std::vector<ExtAPI::Operation> allOperations = ExtAPI::getExtAPI()->getAllOperations(funName);
1408
- if (allOperations.size() == 0)
1409
- {
1410
- std::string str;
1411
- std::stringstream rawstr(str);
1412
- rawstr << "function " << funName << " not in the external function summary ExtAPI.json file";
1413
- writeWrnMsg(rawstr.str());
1414
- }
1415
- else
1416
- {
1417
- parseOperations(allOperations, svfcall);
1418
- for (ExtAPI::Operation op : allOperations)
1419
- {
1420
- if (op.getOperator() == "AddrStmt")
1421
- {
1422
- if (op.getOperands().size() == 2)
1423
- addAddrEdge(op.getOperands()[0], op.getOperands()[1]);
1424
- else
1425
- writeWrnMsg("We need two valid NodeIDs to add an Addr edge");
1426
- }
1427
- else if (op.getOperator() == "CopyStmt")
1428
- {
1429
- if (op.getOperands().size() == 2)
1430
- addCopyEdge(op.getOperands()[0], op.getOperands()[1]);
1431
- else
1432
- writeWrnMsg("We need two valid NodeIDs to add a Copy edge");
1433
- }
1434
- else if (op.getOperator() == "LoadStmt")
1435
- {
1436
- if (op.getOperands().size() == 2)
1437
- addLoadEdge(op.getOperands()[0], op.getOperands()[1]);
1438
- else
1439
- writeWrnMsg("We need two valid NodeIDs to add a Load edge");
1440
- }
1441
- else if (op.getOperator() == "StoreStmt")
1442
- {
1443
- if (op.getOperands().size() == 2)
1444
- addStoreEdge(op.getOperands()[0], op.getOperands()[1]);
1445
- else
1446
- writeWrnMsg("We need two valid NodeIDs to add a Store edge");
1447
- }
1448
- else if (op.getOperator() == "GepStmt")
1449
- {
1450
- if (op.getOperands().size() == 3)
1451
- {
1452
- LocationSet ls(op.getOperands()[2]);
1453
- addNormalGepEdge(op.getOperands()[0], op.getOperands()[1], ls);
1454
- }
1455
- else
1456
- writeWrnMsg("We need two valid NodeIDs and an offset to add a Gep edge");
1457
- }
1458
- else if (op.getOperator() == "BinaryOPStmt")
1459
- {
1460
- if (op.getOperands().size() == 4)
1461
- addBinaryOPEdge(op.getOperands()[0], op.getOperands()[1], op.getOperands()[2], op.getOperands()[3]);
1462
- else
1463
- writeWrnMsg("We need four valid NodeIDs to add a BinaryOP edge");
1464
- }
1465
- else if (op.getOperator() == "UnaryOPStmt")
1466
- {
1467
- if (op.getOperands().size() == 3)
1468
- addUnaryOPEdge(op.getOperands()[0], op.getOperands()[1], op.getOperands()[2]);
1469
- else
1470
- writeWrnMsg("We need three valid NodeIDs to add a UnaryOP edge");
1471
- }
1472
- else if (op.getOperator() == "CmpStmt")
1473
- {
1474
- if (op.getOperands().size() == 4)
1475
- addCmpEdge(op.getOperands()[0], op.getOperands()[1], op.getOperands()[2], op.getOperands()[3]);
1476
- else
1477
- writeWrnMsg("We need four valid NodeIDs to add a CmpStmt edge");
1478
- }
1479
- else if (op.getOperator() == "memset_like")
1480
- {
1481
- // this is for memset(void *str, int c, size_t n)
1482
- // which copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str
1483
- // const SVFConstantInt* arg2 = SVFUtil::dyn_cast<SVFConstantInt>(svfcall->getArgOperand(op.getOperands()[2]));
1484
- NodeID argId = pag->getValueNode(svfcall->getArgOperand(op.getOperands()[0]));
1485
- std::vector<LocationSet> dstFields = pag->getTypeLocSetsMap(argId).second;
1486
- u32_t sz = dstFields.size();
1487
- if (const SVFConstantInt* arg2 = SVFUtil::dyn_cast<SVFConstantInt>(svfcall->getArgOperand(op.getOperands()[2])))
1488
- sz = (dstFields.size() > static_cast<u32_t>(arg2->getSExtValue())) ? arg2->getSExtValue() : dstFields.size();
1489
- //For each field (i), add store edge *(arg0 + i) = arg1
1490
- for (u32_t index = 0; index < sz; index++)
1491
- {
1492
- const SVFType* dElementType = pag->getSymbolInfo()->getFlatternedElemType(pag->getTypeLocSetsMap(argId).first, dstFields[index].getConstantFieldIdx());
1493
- NodeID dField = getGepValVar(svfcall->getArgOperand(op.getOperands()[0]), dstFields[index], dElementType);
1494
- addStoreEdge(pag->getValueNode(svfcall->getArgOperand(op.getOperands()[1])),dField);
1495
- }
1496
- if(svfcall->getType()->isPointerTy())
1497
- addCopyEdge(pag->getValueNode(svfcall->getArgOperand(op.getOperands()[0])), pag->getValueNode(svfinst));
1498
- }
1499
- else if (op.getOperator() == "memcpy_like")
1500
- {
1501
- if(op.getOperands().size() == 3)
1502
- addComplexConsForExt(svfcall->getArgOperand(op.getOperands()[0]), svfcall->getArgOperand(op.getOperands()[1]), svfcall->getArgOperand(op.getOperands()[2]));
1503
- else
1504
- addComplexConsForExt(svfcall->getArgOperand(op.getOperands()[0]), svfcall->getArgOperand(op.getOperands()[1]), nullptr);
1505
- }
1506
- else if (op.getOperator() == "Rb_tree_ops")
1507
- {
1508
- assert(svfcall->arg_size() == 4 && "_Rb_tree_insert_and_rebalance should have 4 arguments.\n");
1509
-
1510
- // We have vArg3 points to the entry of _Rb_tree_node_base { color; parent; left; right; }.
1511
- // Now we calculate the offset from base to vArg3
1512
- NodeID vnArg3 = pag->getValueNode(svfcall->getArgOperand(3));
1513
- s32_t offset = getLocationSetFromBaseNode(vnArg3).getConstantFieldIdx();
1514
-
1515
- // We get all flattened fields of base
1516
- vector<LocationSet> fields = pag->getTypeLocSetsMap(vnArg3).second;
1517
-
1518
- // We summarize the side effects: arg3->parent = arg1, arg3->left = arg1, arg3->right = arg1
1519
- // Note that arg0 is aligned with "offset".
1520
- for (s32_t i = offset + 1; i <= offset + 3; ++i)
1521
- {
1522
- if((u32_t)i >= fields.size())
1523
- break;
1524
- const SVFType* elementType = pag->getSymbolInfo()->getFlatternedElemType(pag->getTypeLocSetsMap(vnArg3).first,
1525
- fields[i].getConstantFieldIdx());
1526
- NodeID vnD = getGepValVar(svfcall->getArgOperand(3), fields[i], elementType);
1527
- NodeID vnS = pag->getValueNode(svfcall->getArgOperand(1));
1528
- if(vnD && vnS)
1529
- addStoreEdge(vnS,vnD);
1530
- }
1531
- }
1532
- // default
1533
- // illegal function operation of external function
1534
- else
1535
- {
1536
- assert(false && "new type of SVFStmt for external calls?");
1537
- }
1538
- }
1539
- }
1540
- }
1541
-
1542
- /// create inter-procedural SVFIR edges for thread forks
1543
- if (isThreadForkCall(svfinst))
1544
- {
1545
- if (const SVFFunction* forkedFun = SVFUtil::dyn_cast<SVFFunction>(getForkedFun(svfinst)))
1546
- {
1547
- forkedFun = forkedFun->getDefFunForMultipleModule();
1548
- const SVFValue* actualParm = getActualParmAtForkSite(svfinst);
1549
- /// pthread_create has 1 arg.
1550
- /// apr_thread_create has 2 arg.
1551
- assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
1552
- if (forkedFun->arg_size() <= 2 && forkedFun->arg_size() >= 1)
1553
- {
1554
- const SVFArgument* formalParm = forkedFun->getArg(0);
1555
- /// Connect actual parameter to formal parameter of the start routine
1556
- if (actualParm->getType()->isPointerTy() && formalParm->getType()->isPointerTy())
1557
- {
1558
- CallICFGNode *icfgNode = pag->getICFG()->getCallICFGNode(svfinst);
1559
- FunEntryICFGNode *entry = pag->getICFG()->getFunEntryICFGNode(forkedFun);
1560
- addThreadForkEdge(pag->getValueNode(actualParm), pag->getValueNode(formalParm), icfgNode, entry);
1561
- }
1562
- }
1563
- }
1564
- else
1565
- {
1566
- /// handle indirect calls at pthread create APIs e.g., pthread_create(&t1, nullptr, fp, ...);
1567
- /// const Value* fun = ThreadAPI::getThreadAPI()->getForkedFun(inst);
1568
- /// if(!SVFUtil::isa<Function>(fun))
1569
- /// pag->addIndirectCallsites(cs,pag->getValueNode(fun));
1570
- }
1571
- /// If forkedFun does not pass to spawnee as function type but as void pointer
1572
- /// remember to update inter-procedural callgraph/SVFIR/SVFG etc. when indirect call targets are resolved
1573
- /// We don't connect the callgraph here, further investigation is need to hanle mod-ref during SVFG construction.
1574
- }
1575
-
1576
- /// create inter-procedural SVFIR edges for hare_parallel_for calls
1577
- else if (isHareParForCall(svfinst))
1578
- {
1579
- if (const SVFFunction* taskFunc = SVFUtil::dyn_cast<SVFFunction>(getTaskFuncAtHareParForSite(svfinst)))
1580
- {
1581
- /// The task function of hare_parallel_for has 3 args.
1582
- assert((taskFunc->arg_size() == 3) && "Size of formal parameter of hare_parallel_for's task routine should be 3");
1583
- const SVFValue* actualParm = getTaskDataAtHareParForSite(svfinst);
1584
- const SVFArgument* formalParm = taskFunc->getArg(0);
1585
- /// Connect actual parameter to formal parameter of the start routine
1586
- if (actualParm->getType()->isPointerTy() && formalParm->getType()->isPointerTy())
1587
- {
1588
- CallICFGNode *icfgNode = pag->getICFG()->getCallICFGNode(svfinst);
1589
- FunEntryICFGNode *entry = pag->getICFG()->getFunEntryICFGNode(taskFunc);
1590
- addThreadForkEdge(pag->getValueNode(actualParm), pag->getValueNode(formalParm), icfgNode, entry);
1591
- }
1592
- }
1593
- else
1594
- {
1595
- /// handle indirect calls at hare_parallel_for (e.g., hare_parallel_for(..., fp, ...);
1596
- /// const Value* fun = ThreadAPI::getThreadAPI()->getForkedFun(inst);
1597
- /// if(!SVFUtil::isa<Function>(fun))
1598
- /// pag->addIndirectCallsites(cs,pag->getValueNode(fun));
1599
- }
1600
- }
1601
-
1602
- /// TODO: inter-procedural SVFIR edges for thread joins
1603
- }
1604
- }
1605
-
1606
1184
  /*!
1607
1185
  * Indirect call is resolved on-the-fly during pointer analysis
1608
1186
  */