2222using namespace llvm ;
2323using namespace klee ;
2424
25- namespace klee {
26- llvm::cl::opt<TargetCalculateBy> TargetCalculatorMode (
27- " target-calculator-kind" , cl::desc(" Specifiy the target calculator mode." ),
28- cl::values(
29- clEnumValN (TargetCalculateBy::Default, " default" ,
30- " Looks for the closest uncovered block." ),
31- clEnumValN(
32- TargetCalculateBy::Blocks, " blocks" ,
33- " Looks for the closest uncovered block by state blocks history." ),
34- clEnumValN(TargetCalculateBy::Transitions, " transitions" ,
35- " Looks for the closest uncovered block by state transitions "
36- " history." )),
37- cl::init(TargetCalculateBy::Default), cl::cat(ExecCat));
38- } // namespace klee
25+ llvm::cl::opt<TrackCoverageBy> TrackCoverage (
26+ " track-coverage" , cl::desc(" Specifiy the track coverage mode." ),
27+ cl::values(clEnumValN(TrackCoverageBy::None, " none" , " Not track coverage." ),
28+ clEnumValN(TrackCoverageBy::Blocks, " blocks" ,
29+ " Track only covered block." ),
30+ clEnumValN(TrackCoverageBy::Branches, " branches" ,
31+ " Track only covered conditional branches." ),
32+ clEnumValN(TrackCoverageBy::All, " all" , " Track all." )),
33+ cl::init(TrackCoverageBy::None), cl::cat(ExecCat));
3934
4035void TargetCalculator::update (const ExecutionState &state) {
4136 Function *initialFunction = state.getInitPCBlock ()->getParent ();
4237
43- if (state.prevPC == state.prevPC ->parent ->getLastInstruction ()) {
44- coveredBlocks[state.getPrevPCBlock ()->getParent ()].insert (
45- state.prevPC ->parent );
46- }
4738 if (state.prevPC == state.prevPC ->parent ->getLastInstruction () &&
4839 !fullyCoveredFunctions.count (state.prevPC ->parent ->parent )) {
40+ auto &fBranches = getCoverageTargets (state.prevPC ->parent ->parent );
4941
5042 if (!coveredFunctionsInBranches.count (state.prevPC ->parent ->parent )) {
51- unsigned index = 0 ;
52- if (!coveredBranches[state.prevPC ->parent ->parent ].count (
53- state.prevPC ->parent )) {
54- state.coverNew ();
55- coveredBranches[state.prevPC ->parent ->parent ][state.prevPC ->parent ];
56- }
57- for (auto succ : successors (state.getPrevPCBlock ())) {
58- if (succ == state.getPCBlock ()) {
59- if (!coveredBranches[state.prevPC ->parent ->parent ]
60- [state.prevPC ->parent ]
61- .count (index)) {
62- state.coverNew ();
63- coveredBranches[state.prevPC ->parent ->parent ][state.prevPC ->parent ]
64- .insert (index);
43+ if (fBranches .count (state.prevPC ->parent ) != 0 ) {
44+ if (!coveredBranches[state.prevPC ->parent ->parent ].count (
45+ state.prevPC ->parent )) {
46+ state.coverNew ();
47+ coveredBranches[state.prevPC ->parent ->parent ][state.prevPC ->parent ];
48+ }
49+ if (!fBranches .at (state.prevPC ->parent ).empty ()) {
50+ unsigned index = 0 ;
51+ for (auto succ : successors (state.getPrevPCBlock ())) {
52+ if (succ == state.getPCBlock ()) {
53+ if (!coveredBranches[state.prevPC ->parent ->parent ]
54+ [state.prevPC ->parent ]
55+ .count (index)) {
56+ state.coverNew ();
57+ coveredBranches[state.prevPC ->parent ->parent ]
58+ [state.prevPC ->parent ]
59+ .insert (index);
60+ }
61+ break ;
62+ }
63+ ++index;
6564 }
66- break ;
6765 }
68- ++index;
6966 }
70- if (codeGraphInfo. getFunctionBranches (state.prevPC ->parent ->parent ) ==
67+ if (getCoverageTargets (state.prevPC ->parent ->parent ) ==
7168 coveredBranches[state.prevPC ->parent ->parent ]) {
7269 coveredFunctionsInBranches.insert (state.prevPC ->parent ->parent );
7370 }
@@ -88,12 +85,15 @@ void TargetCalculator::update(const ExecutionState &state) {
8885 KFunction *calledKFunction = state.prevPC ->parent ->parent ->parent
8986 ->functionMap [calledFunction];
9087 if (calledKFunction->numInstructions != 0 &&
91- coveredFunctionsInBranches.count (calledKFunction) == 0 ) {
88+ coveredFunctionsInBranches.count (calledKFunction) == 0 &&
89+ !getCoverageTargets (calledKFunction).empty ()) {
9290 covered = false ;
9391 break ;
9492 }
9593 if (!fnsTaken.count (calledKFunction) &&
96- fullyCoveredFunctions.count (calledKFunction) == 0 ) {
94+ fullyCoveredFunctions.count (calledKFunction) == 0 &&
95+ calledKFunction->numInstructions != 0 &&
96+ !getCoverageTargets (calledKFunction).empty ()) {
9797 fns.push_back (calledKFunction);
9898 }
9999 }
@@ -106,25 +106,6 @@ void TargetCalculator::update(const ExecutionState &state) {
106106 }
107107 }
108108 }
109-
110- switch (TargetCalculatorMode) {
111- case TargetCalculateBy::Default:
112- blocksHistory[initialFunction][state.getPrevPCBlock ()].insert (
113- state.initPC ->parent );
114- break ;
115-
116- case TargetCalculateBy::Blocks:
117- blocksHistory[initialFunction][state.getPrevPCBlock ()].insert (
118- state.level .begin (), state.level .end ());
119- break ;
120-
121- case TargetCalculateBy::Transitions:
122- blocksHistory[initialFunction][state.getPrevPCBlock ()].insert (
123- state.level .begin (), state.level .end ());
124- transitionsHistory[initialFunction][state.getPrevPCBlock ()].insert (
125- state.transitionLevel .begin (), state.transitionLevel .end ());
126- break ;
127- }
128109}
129110
130111void TargetCalculator::update (
@@ -151,73 +132,48 @@ void TargetCalculator::update(
151132 localStates.clear ();
152133}
153134
154- bool TargetCalculator::differenceIsEmpty (
155- const ExecutionState &state,
156- const std::unordered_map<llvm::BasicBlock *, VisitedBlocks> &history,
157- KBlock *target) {
158- std::vector<KBlock *> diff;
159- std::set<KBlock *> left (state.level .begin (), state.level .end ());
160- std::set<KBlock *> right (history.at (target->basicBlock ).begin (),
161- history.at (target->basicBlock ).end ());
162- std::set_difference (left.begin (), left.end (), right.begin (), right.end (),
163- std::inserter (diff, diff.begin ()));
164- return diff.empty ();
165- }
135+ const std::map<KBlock *, std::set<unsigned >> &
136+ TargetCalculator::getCoverageTargets (KFunction *kf) {
137+ switch (TrackCoverage) {
138+ case TrackCoverageBy::Blocks:
139+ return codeGraphInfo.getFunctionBlocks (kf);
140+ case TrackCoverageBy::Branches:
141+ return codeGraphInfo.getFunctionConditionalBranches (kf);
142+ case TrackCoverageBy::None:
143+ case TrackCoverageBy::All:
144+ return codeGraphInfo.getFunctionBranches (kf);
166145
167- bool TargetCalculator::differenceIsEmpty (
168- const ExecutionState &state,
169- const std::unordered_map<llvm::BasicBlock *, VisitedTransitions> &history,
170- KBlock *target) {
171- std::vector<Transition> diff;
172- std::set<Transition> left (state.transitionLevel .begin (),
173- state.transitionLevel .end ());
174- std::set<Transition> right (history.at (target->basicBlock ).begin (),
175- history.at (target->basicBlock ).end ());
176- std::set_difference (left.begin (), left.end (), right.begin (), right.end (),
177- std::inserter (diff, diff.begin ()));
178- return diff.empty ();
146+ default :
147+ assert (0 && " not implemented" );
148+ }
179149}
180150
181151bool TargetCalculator::uncoveredBlockPredicate (ExecutionState *state,
182152 KBlock *kblock) {
183153 Function *initialFunction = state->getInitPCBlock ()->getParent ();
184- std::unordered_map<llvm::BasicBlock *, VisitedBlocks> &history =
185- blocksHistory[initialFunction];
186- std::unordered_map<llvm::BasicBlock *, VisitedTransitions>
187- &transitionHistory = transitionsHistory[initialFunction];
188154 bool result = false ;
189- if (coveredBranches[kblock->parent ].count (kblock) == 0 ) {
190- result = true ;
191- } else {
192- auto &cb = coveredBranches[kblock->parent ][kblock];
193- if (isa<KCallBlock>(kblock) &&
194- cast<KCallBlock>(kblock)->calledFunctions .size () == 1 ) {
195- auto calledFunction = *cast<KCallBlock>(kblock)->calledFunctions .begin ();
196- KFunction *calledKFunction =
197- kblock->parent ->parent ->functionMap [calledFunction];
198- result = fullyCoveredFunctions.count (calledKFunction) == 0 &&
199- calledKFunction->numInstructions ;
200- }
201- result |=
202- kblock->basicBlock ->getTerminator ()->getNumSuccessors () > cb.size ();
203- }
204155
205- switch (TargetCalculatorMode) {
206- case TargetCalculateBy::Default: {
207- break ;
208- }
209- case TargetCalculateBy::Blocks: {
210- if (history[kblock->basicBlock ].size () != 0 ) {
211- result |= !differenceIsEmpty (*state, history, kblock);
212- }
213- break ;
214- }
215- case TargetCalculateBy::Transitions: {
216- if (history[kblock->basicBlock ].size () != 0 ) {
217- result |= !differenceIsEmpty (*state, transitionHistory, kblock);
156+ auto &fBranches = getCoverageTargets (kblock->parent );
157+
158+ if (fBranches .count (kblock) != 0 || isa<KCallBlock>(kblock)) {
159+ if (coveredBranches[kblock->parent ].count (kblock) == 0 ) {
160+ result = true ;
161+ } else {
162+ auto &cb = coveredBranches[kblock->parent ][kblock];
163+ if (isa<KCallBlock>(kblock) &&
164+ cast<KCallBlock>(kblock)->calledFunctions .size () == 1 ) {
165+ auto calledFunction =
166+ *cast<KCallBlock>(kblock)->calledFunctions .begin ();
167+ KFunction *calledKFunction =
168+ kblock->parent ->parent ->functionMap [calledFunction];
169+ result = fullyCoveredFunctions.count (calledKFunction) == 0 &&
170+ calledKFunction->numInstructions ;
171+ }
172+ if (fBranches .at (kblock) != cb) {
173+ result |=
174+ kblock->basicBlock ->getTerminator ()->getNumSuccessors () > cb.size ();
175+ }
218176 }
219- break ;
220- }
221177 }
222178
223179 return result;
@@ -246,29 +202,36 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) {
246202 if (!blocks.empty ()) {
247203 TargetHashSet targets;
248204 for (auto block : blocks) {
249- if (coveredBranches[block->parent ].count (block) == 0 ) {
250- targets.insert (ReachBlockTarget::create (block, false ));
251- } else {
252- auto &cb = coveredBranches[block->parent ][block];
253- bool notCoveredFunction = false ;
254- if (isa<KCallBlock>(block) &&
255- cast<KCallBlock>(block)->calledFunctions .size () == 1 ) {
256- auto calledFunction =
257- *cast<KCallBlock>(block)->calledFunctions .begin ();
258- KFunction *calledKFunction =
259- block->parent ->parent ->functionMap [calledFunction];
260- notCoveredFunction =
261- fullyCoveredFunctions.count (calledKFunction) == 0 &&
262- calledKFunction->numInstructions ;
263- }
264- if (notCoveredFunction) {
265- targets.insert (ReachBlockTarget::create (block, true ));
205+ auto &fBranches = getCoverageTargets (block->parent );
206+
207+ if (fBranches .count (block) != 0 || isa<KCallBlock>(block)) {
208+ if (coveredBranches[block->parent ].count (block) == 0 ) {
209+ targets.insert (ReachBlockTarget::create (block, false ));
266210 } else {
267- for (unsigned index = 0 ;
268- index < block->basicBlock ->getTerminator ()->getNumSuccessors ();
269- ++index) {
270- if (!cb.count (index))
271- targets.insert (CoverBranchTarget::create (block, index));
211+ auto &cb = coveredBranches[block->parent ][block];
212+ bool notCoveredFunction = false ;
213+ if (isa<KCallBlock>(block) &&
214+ cast<KCallBlock>(block)->calledFunctions .size () == 1 ) {
215+ auto calledFunction =
216+ *cast<KCallBlock>(block)->calledFunctions .begin ();
217+ KFunction *calledKFunction =
218+ block->parent ->parent ->functionMap [calledFunction];
219+ notCoveredFunction =
220+ fullyCoveredFunctions.count (calledKFunction) == 0 &&
221+ calledKFunction->numInstructions ;
222+ }
223+ if (notCoveredFunction) {
224+ targets.insert (ReachBlockTarget::create (block, true ));
225+ } else {
226+ if (fBranches .at (block) != cb) {
227+ for (unsigned index = 0 ;
228+ index <
229+ block->basicBlock ->getTerminator ()->getNumSuccessors ();
230+ ++index) {
231+ if (!cb.count (index))
232+ targets.insert (CoverBranchTarget::create (block, index));
233+ }
234+ }
272235 }
273236 }
274237 }
@@ -289,3 +252,7 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) {
289252
290253 return {};
291254}
255+
256+ bool TargetCalculator::isCovered (KFunction *kf) const {
257+ return fullyCoveredFunctions.count (kf) != 0 ;
258+ }
0 commit comments