30 #ifndef THREADAPI_CPP_
31 #define THREADAPI_CPP_
64 {
"pthread_create", ThreadAPI::TD_FORK},
65 {
"apr_thread_create", ThreadAPI::TD_FORK},
66 {
"pthread_join", ThreadAPI::TD_JOIN},
67 {
"\01_pthread_join", ThreadAPI::TD_JOIN},
68 {
"pthread_cancel", ThreadAPI::TD_JOIN},
69 {
"pthread_mutex_lock", ThreadAPI::TD_ACQUIRE},
70 {
"pthread_rwlock_rdlock", ThreadAPI::TD_ACQUIRE},
71 {
"sem_wait", ThreadAPI::TD_ACQUIRE},
72 {
"_spin_lock", ThreadAPI::TD_ACQUIRE},
73 {
"SRE_SplSpecLockEx", ThreadAPI::TD_ACQUIRE},
74 {
"pthread_mutex_trylock", ThreadAPI::TD_TRY_ACQUIRE},
75 {
"pthread_mutex_unlock", ThreadAPI::TD_RELEASE},
76 {
"pthread_rwlock_unlock", ThreadAPI::TD_RELEASE},
77 {
"sem_post", ThreadAPI::TD_RELEASE},
78 {
"_spin_unlock", ThreadAPI::TD_RELEASE},
79 {
"SRE_SplSpecUnlockEx", ThreadAPI::TD_RELEASE},
81 {
"pthread_exit", ThreadAPI::TD_EXIT},
82 {
"pthread_detach", ThreadAPI::TD_DETACH},
83 {
"pthread_cond_wait", ThreadAPI::TD_COND_WAIT},
84 {
"pthread_cond_signal", ThreadAPI::TD_COND_SIGNAL},
85 {
"pthread_cond_broadcast", ThreadAPI::TD_COND_BROADCAST},
86 {
"pthread_cond_init", ThreadAPI::TD_CONDVAR_INI},
87 {
"pthread_cond_destroy", ThreadAPI::TD_CONDVAR_DESTROY},
88 {
"pthread_mutex_init", ThreadAPI::TD_MUTEX_INI},
89 {
"pthread_mutex_destroy", ThreadAPI::TD_MUTEX_DESTROY},
90 {
"pthread_barrier_init", ThreadAPI::TD_BAR_INIT},
91 {
"pthread_barrier_wait", ThreadAPI::TD_BAR_WAIT},
94 {
"hare_parallel_for", ThreadAPI::HARE_PAR_FOR},
97 {0, ThreadAPI::TD_DUMMY}
103 void ThreadAPI::init()
107 t_seen.insert(TD_DUMMY);
114 if(t_seen.count(
p->t))
118 assert(!
"ei_pairs not grouped by type");
123 if(tdAPIMap.count(
p->n))
127 assert(!
"duplicate name in ei_pairs");
129 tdAPIMap[
p->n]=
p->t;
166 assert(isTDFork(inst) &&
"not a thread fork function!");
172 assert(isTDFork(inst) &&
"not a thread fork function!");
180 assert(isTDFork(inst) &&
"not a thread fork function!");
186 assert(PAG::getPAG()->hasFunArgsList(
F) &&
"forked function has no args list!");
189 assert(funArgList.size() == 1 &&
"num of pthread forked function args is not 1!");
190 return funArgList[0];
195 assert(isTDJoin(inst) &&
"not a thread join function!");
201 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(cs);
202 assert(call &&
"not a call ICFGNode?");
203 assert((isTDAcquire(call) || isTDRelease(call)) &&
"not a lock acquire or release function");
209 assert(isTDJoin(cs) &&
"not a thread join function!");
213 if(SVFUtil::isa<LoadStmt>(stmt))
214 return stmt->getSrcNode();
216 if(SVFUtil::isa<SVFArgument>(join->
getValue()))
219 assert(
false &&
"the value of the first argument at join is not a load instruction?");
229 tdAPIStatMap[
"pthread_create"] = 0;
231 tdAPIStatMap[
"pthread_join"] = 0;
233 tdAPIStatMap[
"pthread_mutex_lock"] = 0;
235 tdAPIStatMap[
"pthread_mutex_trylock"] = 0;
237 tdAPIStatMap[
"pthread_mutex_unlock"] = 0;
239 tdAPIStatMap[
"pthread_cancel"] = 0;
241 tdAPIStatMap[
"pthread_exit"] = 0;
243 tdAPIStatMap[
"pthread_detach"] = 0;
245 tdAPIStatMap[
"pthread_cond_wait"] = 0;
247 tdAPIStatMap[
"pthread_cond_signal"] = 0;
249 tdAPIStatMap[
"pthread_cond_broadcast"] = 0;
251 tdAPIStatMap[
"pthread_cond_init"] = 0;
253 tdAPIStatMap[
"pthread_cond_destroy"] = 0;
255 tdAPIStatMap[
"pthread_mutex_init"] = 0;
257 tdAPIStatMap[
"pthread_mutex_destroy"] = 0;
259 tdAPIStatMap[
"pthread_barrier_init"] = 0;
261 tdAPIStatMap[
"pthread_barrier_wait"] = 0;
263 tdAPIStatMap[
"hare_parallel_for"] = 0;
271 statInit(tdAPIStatMap);
273 PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
274 for (
const auto&
item: *svfirCallGraph)
284 const SVFFunction* fun = SVFUtil::cast<CallICFGNode>(svfInst)->getCalledFunction();
290 tdAPIStatMap[
"pthread_create"]++;
295 tdAPIStatMap[
"pthread_join"]++;
300 tdAPIStatMap[
"pthread_mutex_lock"]++;
305 tdAPIStatMap[
"pthread_mutex_trylock"]++;
310 tdAPIStatMap[
"pthread_mutex_unlock"]++;
315 tdAPIStatMap[
"pthread_cancel"]++;
320 tdAPIStatMap[
"pthread_exit"]++;
325 tdAPIStatMap[
"pthread_detach"]++;
330 tdAPIStatMap[
"pthread_cond_wait"]++;
335 tdAPIStatMap[
"pthread_cond_signal"]++;
338 case TD_COND_BROADCAST:
340 tdAPIStatMap[
"pthread_cond_broadcast"]++;
345 tdAPIStatMap[
"pthread_cond_init"]++;
348 case TD_CONDVAR_DESTROY:
350 tdAPIStatMap[
"pthread_cond_destroy"]++;
355 tdAPIStatMap[
"pthread_mutex_init"]++;
358 case TD_MUTEX_DESTROY:
360 tdAPIStatMap[
"pthread_mutex_destroy"]++;
365 tdAPIStatMap[
"pthread_barrier_init"]++;
370 tdAPIStatMap[
"pthread_barrier_wait"]++;
375 tdAPIStatMap[
"hare_parallel_for"]++;
390 if (fullNames.size() > 1)
392 name = fullNames[fullNames.size() - 1];
395 <<
")###############\n";
397 unsigned field_width = 20;
399 tdAPIStatMap.end(); it != eit; ++it)
403 SVFUtil::outs() << std::setw(field_width) << apiName <<
" : " << it->second
406 SVFUtil::outs() <<
"#######################################################"
static const ei_pair ei_pairs[]
const SVFFunction * getCalledFunction() const
const SVFVar * getArgument(u32_t ArgNo) const
Parameter operations.
const GEdgeSetTy & getInEdges() const
const std::vector< const ICFGNode * > & getICFGNodeList() const
std::vector< const SVFBasicBlock * >::const_iterator const_iterator
std::vector< const SVFVar * > SVFVarList
const std::string & getModuleIdentifier() const
const SVFValue * getValue() const
Get/has methods of the components.
bool isCallSite(const Instruction *inst)
Whether an instruction is a call or invoke instruction.
const SVFVar * getActualParmAtForkSite(const CallICFGNode *cs)
Return sole argument of the thread routine.
const SVFVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
std::vector< std::string > split(const std::string &s, char separator)
Split into two substrings around the first occurrence of a separator string.
std::ostream & outs()
Overwrite llvm::outs()
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map