Static Value-Flow Analysis
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Static Private Member Functions | Private Attributes | List of all members
SVF::MTA Class Reference

#include <MTA.h>

Classes

struct  RaceOccurrence
 One occurrence of a memory access under one thread instance. More...
 
struct  RacePair
 A race pair: two statements that may race. More...
 

Public Member Functions

 MTA ()
 Constructor.
 
virtual ~MTA ()
 Destructor.
 
virtual bool runOnModule (SVFIR *module)
 We start the pass here.
 
virtual MHPcomputeMHP (TCT *tct)
 Compute MHP.
 
virtual LockAnalysiscomputeLocksets (TCT *tct)
 Compute locksets.
 
virtual void reportRaces ()
 Run the shared detector and print a race report.
 
MHPgetMHP ()
 
LockAnalysisgetLockAnalysis ()
 

Static Public Member Functions

static std::set< const SVFStmt * > detectRace (SVFIR *svfIr, AndersenBase *pta, MHP *mhp, LockAnalysis *lockAnalysis, CallGraph *callGraph, std::set< RacePair > &outRacePairs)
 
static PointsTo getGlobalObjectVariables (SVFIR *svfIr)
 Escape/points-to helpers for the shared detector.
 
static PointsTo getPointsToClosure (AndersenBase *pta, const PointsTo &pts)
 
static bool hasThreadFunctions (CallGraph *callGraph)
 

Static Private Member Functions

static bool occurrencesRace (MHP *mhp, const RaceOccurrence &first, const RaceOccurrence &second)
 Helpers for the equivalence-class race detector.
 
static void commitRacePair (std::set< RacePair > &out, const RaceOccurrence &first, const RaceOccurrence &second)
 

Private Attributes

ThreadCallGraphtcg
 
std::unique_ptr< TCTtct
 
std::unique_ptr< MTAStatstat
 
MHPmhp
 
LockAnalysislsa
 

Detailed Description

Base data race detector

Definition at line 85 of file MTA.h.

Constructor & Destructor Documentation

◆ MTA()

MTA::MTA ( )

Constructor.

Definition at line 58 of file MTA.cpp.

58 : tcg(nullptr), tct(nullptr), mhp(nullptr), lsa(nullptr)
59{
60 stat = std::make_unique<MTAStat>();
61}
ThreadCallGraph * tcg
Definition MTA.h:164
std::unique_ptr< TCT > tct
Definition MTA.h:165
LockAnalysis * lsa
Definition MTA.h:168
MHP * mhp
Definition MTA.h:167
std::unique_ptr< MTAStat > stat
Definition MTA.h:166

◆ ~MTA()

MTA::~MTA ( )
virtual

Destructor.

Definition at line 63 of file MTA.cpp.

64{
65 if (tcg)
66 delete tcg;
67
68 delete mhp;
69 delete lsa;
70}

Member Function Documentation

◆ commitRacePair()

void MTA::commitRacePair ( std::set< RacePair > &  out,
const RaceOccurrence first,
const RaceOccurrence second 
)
staticprivate

Definition at line 210 of file MTA.cpp.

212{
213 const SVFStmt* stmt1 = first.stmt;
214 const SVFStmt* stmt2 = second.stmt;
215 if (stmt2 < stmt1) std::swap(stmt1, stmt2);
216 out.insert(RacePair(stmt1, stmt2));
217}
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ computeLocksets()

LockAnalysis * MTA::computeLocksets ( TCT tct)
virtual

Compute locksets.

Compute lock sets

Definition at line 114 of file MTA.cpp.

115{
117 lsa->analyze(PAG::getPAG()->getICFG(), const_cast<CallGraph*>(PAG::getPAG()->getCallGraph()));
118 return lsa;
119}
void analyze(ICFGGraph icfg, CGGraph cg)
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:120

◆ computeMHP()

MHP * MTA::computeMHP ( TCT tct)
virtual

Compute MHP.

Definition at line 121 of file MTA.cpp.

122{
123 DBOUT(DGENERAL, outs() << pasMsg("MHP analysis\n"));
124 DBOUT(DMTA, outs() << pasMsg("MHP analysis\n"));
125
126 DOTIMESTAT(double mhpStart = stat->getClk());
127 MHP* mhp = new MHP(tct);
128 mhp->analyze(PAG::getPAG()->getICFG(), const_cast<CallGraph*>(PAG::getPAG()->getCallGraph()));
129 DOTIMESTAT(double mhpEnd = stat->getClk());
130 DOTIMESTAT(stat->MHPTime += (mhpEnd - mhpStart) / TIMEINTERVAL);
131
132 DBOUT(DGENERAL, outs() << pasMsg("MHP analysis finish\n"));
133 DBOUT(DMTA, outs() << pasMsg("MHP analysis finish\n"));
134 return mhp;
135}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define TIMEINTERVAL
Definition SVFType.h:604
#define DMTA
Definition SVFType.h:597
#define DGENERAL
Definition SVFType.h:582
#define DOTIMESTAT(X)
Definition SVFType.h:578
Definition MHP.h:57
void analyze(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:120
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:105
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52

◆ detectRace()

std::set< const SVFStmt * > MTA::detectRace ( SVFIR svfIr,
AndersenBase pta,
MHP mhp,
LockAnalysis lockAnalysis,
CallGraph callGraph,
std::set< RacePair > &  outRacePairs 
)
static

Shared equivalence-class race detector (used by both MTA::reportRaces and the SlicedMTA pipeline). Returns the racy statements and fills outRacePairs.

Definition at line 221 of file MTA.cpp.

225{
226
227 std::set<const SVFStmt*> bugStmts;
228
229 // Escape set: objects shared across threads. Seed from globals + the actual
230 // argument at each fork site (the spawner's value, which a spawnee-formal
231 // closure can miss), then take the transitive points-to closure.
233 if (ThreadCallGraph* tcg = SVFUtil::dyn_cast<ThreadCallGraph>(callGraph))
234 {
235 const ThreadAPI* tapi = tcg->getThreadAPI();
236 for (auto it = tcg->forksitesBegin(), eit = tcg->forksitesEnd(); it != eit; ++it)
237 if (const CallICFGNode* cs = SVFUtil::dyn_cast<CallICFGNode>(*it))
238 if (const ValVar* actual = tapi->getActualParmAtForkSite(cs))
239 seed |= pta->getPts(actual->getId());
240 }
242
243 // One occurrence per (statement, thread instance), indexed by object (C1 ->
244 // "same bucket") as collected, so the points-to set is consumed straight into
245 // the buckets and never stored per occurrence.
246 std::vector<RaceOccurrence> occurrences;
248 for (const auto& item : *callGraph)
249 {
250 const FunObjVar* fun = item.second->getFunction();
251 if (!fun || !fun->hasBasicBlock()) continue;
252 for (auto bbIt : *fun)
253 for (const ICFGNode* node : bbIt.second->getICFGNodeList())
254 {
255 if (!mhp->hasThreadStmtSet(node)) continue; // screen 1: concurrent?
256 for (const SVFStmt* stmt : svfIr->getSVFStmtList(node))
257 {
259 bool isStore;
260 if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
261 {
262 accessedPtr = load->getRHSVarID();
263 isStore = false;
264 }
265 else if (const StoreStmt* store = SVFUtil::dyn_cast<StoreStmt>(stmt))
266 {
267 accessedPtr = store->getLHSVarID();
268 isStore = true;
269 }
270 else continue;
272 objects &= escSet; // screen 2: touches shared object?
273 if (objects.empty()) continue;
274 bool locked = lockAnalysis->isProtectedByCommonLock(node, node);
275 const size_t firstNew = occurrences.size();
276 for (const CxtThreadStmt& threadStmt : mhp->getThreadStmtSet(node))
277 occurrences.push_back({stmt, node, isStore, threadStmt.getTid(),
279 for (NodeID object : objects)
280 for (size_t k = firstNew; k < occurrences.size(); ++k)
282 }
283 }
284 }
285
286 // Within each object, occurrences sharing the race predicate's inputs (tid,
287 // interleaving, isStore, lock sig) race the same partners, so collapse into a
288 // class and judge C2/C3/C4 once per class pair -- O(classes^2) not O(occ^2).
289 for (const auto& objectAndOccs : objectToOccurrences)
290 {
291 struct RaceClass
292 {
293 bool isStore, locked;
294 size_t rep;
295 std::vector<size_t> members;
296 };
297 struct RaceKey
298 {
299 NodeID tid;
300 bool isStore;
301 NodeBS interleav;
302 const ICFGNode* lockNode;
303
304 bool operator<(const RaceKey& other) const
305 {
306 if (tid != other.tid)
307 return tid < other.tid;
308 if (isStore != other.isStore)
309 return isStore < other.isStore;
310 if (SVFUtil::cmpNodeBS(interleav, other.interleav))
311 return true;
312 if (SVFUtil::cmpNodeBS(other.interleav, interleav))
313 return false;
314 return lockNode < other.lockNode;
315 }
316 };
317 std::vector<RaceClass> classes;
319 for (size_t occIdx : objectAndOccs.second)
320 {
321 const RaceOccurrence& occ = occurrences[occIdx];
322 RaceKey key{occ.tid, occ.isStore, occ.interleav, occ.locked ? occ.node : nullptr};
323 auto found = keyToClass.find(key);
324 if (found == keyToClass.end())
325 {
326 keyToClass[key] = classes.size();
327 classes.push_back({occ.isStore, occ.locked, occIdx, {occIdx}});
328 }
329 else
330 classes[found->second].members.push_back(occIdx);
331 }
332 for (size_t firstIdx = 0; firstIdx < classes.size(); ++firstIdx)
333 for (size_t secondIdx = firstIdx; secondIdx < classes.size(); ++secondIdx)
334 {
337 if (!firstClass.isStore && !secondClass.isStore) continue; // C2: >=1 write
338 const RaceOccurrence& firstRep = occurrences[firstClass.rep];
339 const RaceOccurrence& secondRep = occurrences[secondClass.rep];
340 if (!occurrencesRace(mhp, firstRep, secondRep)) continue; // C3
341 // C4 + emit. Lock relation is uniform per class (the reps decide it),
342 // so emit a statement-COVERING set -- every racy member as an endpoint.
343 if (firstIdx != secondIdx)
344 {
345 if (firstClass.locked && secondClass.locked &&
346 lockAnalysis->isProtectedByCommonLock(firstRep.node, secondRep.node))
347 continue;
348 for (size_t memberIdx : firstClass.members)
351 for (size_t memberIdx : secondClass.members)
354 }
355 else
356 {
357 const std::vector<size_t>& members = firstClass.members;
358 // Multiforked self-race: every member self-races a concurrent
359 // instance of itself, independent of any cross-race below.
360 for (size_t memberIdx : members)
361 if (!firstClass.locked ||
362 !lockAnalysis->isProtectedByCommonLock(occurrences[memberIdx].node,
363 occurrences[memberIdx].node))
365 // Cross-race needs >=2 members: two distinct occurrences to pair.
366 if (members.size() >= 2 &&
367 (!firstClass.locked ||
368 !lockAnalysis->isProtectedByCommonLock(occurrences[members[0]].node,
369 occurrences[members[1]].node)))
370 for (size_t pos = 0; pos < members.size(); ++pos)
372 occurrences[members[pos == 0 ? 1 : 0]]);
373 }
374 }
375 }
376
377 for (const RacePair& r : outRacePairs)
378 {
379 bugStmts.insert(r.stmt1);
380 bugStmts.insert(r.stmt2);
381 }
382 return bugStmts;
383}
if(prebuffer< 0)
Definition cJSON.cpp:1269
for(i=0;a &&(i<(size_t) count);i++)
Definition cJSON.cpp:2569
cJSON * item
Definition cJSON.h:222
const PointsTo & getPts(NodeID id) override
bool hasBasicBlock() const
bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2)
const NodeBS & getInterleavingThreads(const CxtThreadStmt &cts)
Get interleaving thread for statement inst.
Definition MHP.h:112
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:130
static bool occurrencesRace(MHP *mhp, const RaceOccurrence &first, const RaceOccurrence &second)
Helpers for the equivalence-class race detector.
Definition MTA.cpp:202
static PointsTo getGlobalObjectVariables(SVFIR *svfIr)
Escape/points-to helpers for the shared detector.
Definition MTA.cpp:138
static void commitRacePair(std::set< RacePair > &out, const RaceOccurrence &first, const RaceOccurrence &second)
Definition MTA.cpp:210
static PointsTo getPointsToClosure(AndersenBase *pta, const PointsTo &pts)
Definition MTA.cpp:166
CallSiteSet::const_iterator forksitesEnd() const
CallSiteSet::const_iterator forksitesBegin() const
Fork sites iterators.
ThreadAPI * getThreadAPI() const
Thread API.
bool cmpNodeBS(const NodeBS &lpts, const NodeBS &rpts)
Definition SVFUtil.h:127
u32_t NodeID
Definition GeneralType.h:76
IntervalValue operator<(const IntervalValue &lhs, const IntervalValue &rhs)

◆ getGlobalObjectVariables()

PointsTo MTA::getGlobalObjectVariables ( SVFIR svfIr)
static

Escape/points-to helpers for the shared detector.

Definition at line 138 of file MTA.cpp.

139{
142
143 for (const SVFStmt* stmt : globalICFGNode->getSVFStmts())
144 {
145 const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt);
146 if (addrStmt != nullptr)
147 {
148 const GlobalValVar* globalVar = SVFUtil::dyn_cast<GlobalValVar>(addrStmt->getLHSVar());
149 if (globalVar != nullptr)
150 {
151 globalObjVars.set(addrStmt->getRHSVarID());
152 }
153 }
154 }
155
156 return globalObjVars;
157}
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:244
ICFG * getICFG() const
Definition SVFIR.h:231

◆ getLockAnalysis()

LockAnalysis * SVF::MTA::getLockAnalysis ( )
inline

Definition at line 113 of file MTA.h.

114 {
115 return lsa;
116 }

◆ getMHP()

MHP * SVF::MTA::getMHP ( )
inline

Definition at line 108 of file MTA.h.

109 {
110 return mhp;
111 }

◆ getPointsToClosure()

PointsTo MTA::getPointsToClosure ( AndersenBase pta,
const PointsTo pts 
)
static

Definition at line 166 of file MTA.cpp.

167{
168 SVFIR* pag = pta->getPAG();
170 std::deque<NodeID> worklist;
171 for (NodeID pt : pts)
172 {
173 worklist.push_back(pt);
174 }
175
176 while (!worklist.empty())
177 {
178 NodeID obj = worklist.front();
179 worklist.pop_front();
180
181 for (NodeID target : pta->getPts(obj)) // points-to
182 if (!ptsClosure.test(target))
183 {
184 ptsClosure.set(target);
185 worklist.push_back(target);
186 }
187
188 if (pag->getBaseObject(obj) != nullptr) // containment (object nodes only)
189 for (NodeID field : pta->getAllFieldsObjVars(pta->getBaseObjVarID(obj)))
190 if (!ptsClosure.test(field))
191 {
192 ptsClosure.set(field);
193 worklist.push_back(field);
194 }
195 }
196
197 return ptsClosure;
198}
SVFIR * getPAG() const
void set(u32_t n)
Inserts n in the set.
Definition PointsTo.cpp:157
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:498

◆ hasThreadFunctions()

bool MTA::hasThreadFunctions ( CallGraph callGraph)
static

Whether the program has any thread (fork-target) function reachable via a fork edge.

Definition at line 1039 of file MTA.cpp.

1040{
1041 for (CallGraph::iterator it = callGraph->begin(), eit = callGraph->end(); it != eit; ++it)
1042 {
1043 const CallGraphNode* node = it->second;
1044 for (const CallGraphEdge* edge : node->getOutEdges())
1045 {
1046 if (edge->getEdgeKind() == CallGraphEdge::TDForkEdge &&
1047 edge->getDstNode()->getFunction() != nullptr)
1048 {
1049 return true;
1050 }
1051 }
1052 }
1053 return false;
1054}
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
Node Iterators.

◆ occurrencesRace()

bool MTA::occurrencesRace ( MHP mhp,
const RaceOccurrence first,
const RaceOccurrence second 
)
staticprivate

Helpers for the equivalence-class race detector.

Definition at line 202 of file MTA.cpp.

203{
204 if (first.tid != second.tid)
205 return first.interleav.test(second.tid) && second.interleav.test(first.tid);
206 return mhp->getTCT()->getTCTNode(first.tid)->isMultiforked();
207}
TCT * getTCT() const
Get Thread Creation Tree.
Definition MHP.h:95
bool isMultiforked() const
Definition TCT.h:121
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:203

◆ reportRaces()

void MTA::reportRaces ( )
virtual

Run the shared detector and print a race report.

Definition at line 385 of file MTA.cpp.

386{
387 DBOUT(DGENERAL, outs() << pasMsg("Starting Race Detection\n"));
388
389 SVFIR* pag = SVFIR::getPAG();
391 CallGraph* callGraph = pta->getCallGraph();
392
393 // Shared equivalence-class detector (the same one the slicing pipeline uses),
394 // run over the Andersen pre-analysis with this MTA's MHP/lock results.
395 std::set<RacePair> racePairs;
396 detectRace(pag, pta, mhp, lsa, callGraph, racePairs);
397
398 for (const RacePair& rp : racePairs)
399 outs() << SVFUtil::bugMsg1("race pair(") << " stmt1: " << rp.stmt1->toString()
400 << ", stmt2: " << rp.stmt2->toString() << SVFUtil::bugMsg1(")") << "\n";
401}
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition Andersen.h:408
static std::set< const SVFStmt * > detectRace(SVFIR *svfIr, AndersenBase *pta, MHP *mhp, LockAnalysis *lockAnalysis, CallGraph *callGraph, std::set< RacePair > &outRacePairs)
Definition MTA.cpp:221
CallGraph * getCallGraph() const
Return call graph.
std::string bugMsg1(const std::string &msg)
Definition SVFUtil.cpp:87

◆ runOnModule()

bool MTA::runOnModule ( SVFIR pag)
virtual

We start the pass here.

Perform data race detection

Definition at line 75 of file MTA.cpp.

76{
77 DBOUT(DGENERAL, outs() << pasMsg("MTA analysis\n"));
78 DBOUT(DMTA, outs() << pasMsg("MTA analysis\n"));
79
82 pta->getCallGraph()->dump("ptacg");
83 pag->getICFG()->updateCallGraph(pta->getCallGraph());
84
85 DBOUT(DGENERAL, outs() << pasMsg("Build TCT\n"));
86 DBOUT(DMTA, outs() << pasMsg("Build TCT\n"));
87 DOTIMESTAT(double tctStart = stat->getClk());
88 tct = std::make_unique<TCT>(pta);
89 tcg = tct->getThreadCallGraph();
90 DOTIMESTAT(double tctEnd = stat->getClk());
91 DOTIMESTAT(stat->TCTTime += (tctEnd - tctStart) / TIMEINTERVAL);
92
93 if (pta->printStat())
94 {
95 stat->performThreadCallGraphStat(tcg);
96 stat->performTCTStat(tct.get());
97 }
98
100 tcg->dump("tcg");
101
102 mhp = computeMHP(tct.get());
103 lsa = computeLocksets(tct.get());
104
105 // MTA's only client is race detection; always report.
106 reportRaces();
107
108 return false;
109}
void dump(const std::string &filename)
Dump the graph.
void updateCallGraph(CallGraph *callgraph)
update ICFG for indirect calls
Definition ICFG.cpp:428
virtual LockAnalysis * computeLocksets(TCT *tct)
Compute locksets.
Definition MTA.cpp:114
virtual MHP * computeMHP(TCT *tct)
Compute MHP.
Definition MTA.cpp:121
virtual void reportRaces()
Run the shared detector and print a race report.
Definition MTA.cpp:385
static const Option< bool > DumpMTAGraphs
MTA: dump the pointer-analysis and thread call graphs (ptacg/tcg.dot), Default: false.
Definition Options.h:258
bool printStat()
Whether print statistics.

Member Data Documentation

◆ lsa

LockAnalysis* SVF::MTA::lsa
private

Definition at line 168 of file MTA.h.

◆ mhp

MHP* SVF::MTA::mhp
private

Definition at line 167 of file MTA.h.

◆ stat

std::unique_ptr<MTAStat> SVF::MTA::stat
private

Definition at line 166 of file MTA.h.

◆ tcg

ThreadCallGraph* SVF::MTA::tcg
private

Definition at line 164 of file MTA.h.

◆ tct

std::unique_ptr<TCT> SVF::MTA::tct
private

Definition at line 165 of file MTA.h.


The documentation for this class was generated from the following files: