Skip to content

Commit 31a7ff2

Browse files
committed
add loop analysis to CC
1 parent 1db3b81 commit 31a7ff2

File tree

3 files changed

+77
-14
lines changed

3 files changed

+77
-14
lines changed

instrumentation/SanitizerCoveragePCGUARD.so.cc

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
#endif
7171
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
7272
#include "llvm/Transforms/Utils/ModuleUtils.h"
73+
#include "llvm/Analysis/LoopInfo.h"
74+
#include "llvm/Analysis/LoopPass.h"
7375

7476
#include "config.h"
7577
#include "debug.h"
@@ -119,6 +121,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
119121

120122
}
121123

124+
using LoopInfoCallback = function_ref<const LoopInfo *(Function &F)>;
122125
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
123126
using PostDomTreeCallback =
124127
function_ref<const PostDominatorTree *(Function &F)>;
@@ -135,11 +138,13 @@ class ModuleSanitizerCoverageAFL
135138

136139
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
137140
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
138-
PostDomTreeCallback PDTCallback);
141+
PostDomTreeCallback PDTCallback,
142+
LoopInfoCallback LCallback);
139143

140144
private:
141145
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
142-
PostDomTreeCallback PDTCallback);
146+
PostDomTreeCallback PDTCallback,
147+
LoopInfoCallback LCallback);
143148
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
144149
void InjectTraceForSwitch(Function &F,
145150
ArrayRef<Instruction *> SwitchTraceTargets);
@@ -233,8 +238,10 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
233238
ModuleAnalysisManager &MAM) {
234239

235240
ModuleSanitizerCoverageAFL ModuleSancov(Options);
241+
236242
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
237-
auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{
243+
244+
auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
238245

239246
return &FAM.getResult<DominatorTreeAnalysis>(F);
240247

@@ -246,9 +253,21 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
246253

247254
};
248255

249-
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
256+
auto LoopCallback = [&FAM](Function &F) -> const LoopInfo * {
257+
258+
return &FAM.getResult<LoopAnalysis>(F);
259+
260+
};
261+
262+
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback)) {
263+
250264
return PreservedAnalyses::none();
251-
return PreservedAnalyses::all();
265+
266+
} else {
267+
268+
return PreservedAnalyses::all();
269+
270+
}
252271

253272
}
254273

@@ -324,7 +343,8 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
324343
}
325344

326345
bool ModuleSanitizerCoverageAFL::instrumentModule(
327-
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
346+
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
347+
LoopInfoCallback LCallback) {
328348

329349
setvbuf(stdout, NULL, _IONBF, 0);
330350

@@ -429,7 +449,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
429449
M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
430450

431451
for (auto &F : M)
432-
instrumentFunction(F, DTCallback, PDTCallback);
452+
instrumentFunction(F, DTCallback, PDTCallback, LCallback);
433453

434454
Function *Ctor = nullptr;
435455

@@ -568,7 +588,8 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
568588
#endif
569589

570590
void ModuleSanitizerCoverageAFL::instrumentFunction(
571-
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
591+
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
592+
LoopInfoCallback LCallback) {
572593

573594
if (F.empty()) return;
574595
if (!isInInstrumentList(&F, FMNAME)) return;
@@ -604,6 +625,7 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
604625

605626
const DominatorTree *DT = DTCallback(F);
606627
const PostDominatorTree *PDT = PDTCallback(F);
628+
const LoopInfo *LI = LCallback(F);
607629
bool IsLeafFunc = true;
608630

609631
for (auto &BB : F) {
@@ -640,7 +662,7 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
640662
// InjectTraceForCmp(F, CmpTraceTargets);
641663
// InjectTraceForSwitch(F, SwitchTraceTargets);
642664

643-
if (dump_cc) { calcCyclomaticComplexity(&F); }
665+
if (dump_cc) { calcCyclomaticComplexity(&F, LI); }
644666

645667
}
646668

instrumentation/afl-llvm-common.cc

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <cmath>
1616

1717
#include <llvm/Support/raw_ostream.h>
18+
#include <llvm/Analysis/LoopInfo.h>
19+
#include <llvm/Analysis/LoopPass.h>
1820

1921
#define IS_EXTERN extern
2022
#include "afl-llvm-common.h"
@@ -26,11 +28,39 @@ static std::list<std::string> allowListFunctions;
2628
static std::list<std::string> denyListFiles;
2729
static std::list<std::string> denyListFunctions;
2830

29-
unsigned int calcCyclomaticComplexity(llvm::Function *F) {
31+
static void countNestedLoops(Loop *L, int depth, unsigned int &loopCount,
32+
unsigned int &nestedLoopCount,
33+
unsigned int &maxNestingLevel) {
34+
35+
loopCount++;
36+
if (!L->getSubLoops().empty()) {
37+
38+
// Increment nested loop count by the number of sub-loops
39+
nestedLoopCount += L->getSubLoops().size();
40+
// Update maximum nesting level
41+
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
42+
43+
// Recursively count sub-loops
44+
for (Loop *SubLoop : L->getSubLoops()) {
45+
46+
countNestedLoops(SubLoop, depth + 1, loopCount, nestedLoopCount,
47+
maxNestingLevel);
48+
49+
}
50+
51+
}
52+
53+
}
54+
55+
unsigned int calcCyclomaticComplexity(llvm::Function *F,
56+
const llvm::LoopInfo *LI) {
3057

3158
unsigned int numBlocks = 0;
3259
unsigned int numEdges = 0;
3360
unsigned int numCalls = 0;
61+
unsigned int numLoops = 0;
62+
unsigned int numNestedLoops = 0;
63+
unsigned int maxLoopNesting = 0;
3464

3565
// Iterate through each basic block in the function
3666
for (BasicBlock &BB : *F) {
@@ -55,15 +85,25 @@ unsigned int calcCyclomaticComplexity(llvm::Function *F) {
5585

5686
}
5787

88+
for (Loop *L : *LI) {
89+
90+
countNestedLoops(L, 1, numLoops, numNestedLoops, maxLoopNesting);
91+
92+
}
93+
5894
// Cyclomatic Complexity V(G) = E - N + 2P
5995
// For a single function, P (number of connected components) is 1
6096
// Calls are considered to be an edge
61-
unsigned int CC = 2 + numCalls + numEdges - numBlocks;
97+
unsigned int CC = 2 + numCalls + numEdges - numBlocks + numLoops +
98+
numNestedLoops + maxLoopNesting;
6299

63100
// if (debug) {
64101

65-
fprintf(stderr, "CyclomaticComplexity for %s: %u\n",
66-
F->getName().str().c_str(), CC);
102+
fprintf(stderr,
103+
"CyclomaticComplexity for %s: %u (calls=%u edges=%u blocks=%u "
104+
"loops=%u nested_loops=%u max_loop_nesting_level=%u)\n",
105+
F->getName().str().c_str(), CC, numCalls, numEdges, numBlocks,
106+
numLoops, numNestedLoops, maxLoopNesting);
67107

68108
//}
69109

instrumentation/afl-llvm-common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ void initInstrumentList();
5555
bool isInInstrumentList(llvm::Function *F, std::string Filename);
5656
unsigned long long int calculateCollisions(uint32_t edges);
5757
void scanForDangerousFunctions(llvm::Module *M);
58-
unsigned int calcCyclomaticComplexity(llvm::Function *F);
58+
unsigned int calcCyclomaticComplexity(llvm::Function *F,
59+
const llvm::LoopInfo *LI);
5960

6061
#ifndef IS_EXTERN
6162
#define IS_EXTERN

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy