forked from 0xAlexei/INFILTRATE2019
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ComputeCyclomaticComplexityForAllFunctions.java
126 lines (93 loc) · 3.71 KB
/
ComputeCyclomaticComplexityForAllFunctions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//Completed demo - Script to compute and print the cyclomatic complexity of all functions
//@author Alexei Bulazel
//@category INFILTRATE
//@keybinding
//@menupath
//@toolbar
import ghidra.app.script.GhidraScript;
import ghidra.app.tablechooser.AbstractComparableColumnDisplay;
import ghidra.app.tablechooser.AddressableRowObject;
import ghidra.app.tablechooser.ColumnDisplay;
import ghidra.app.tablechooser.StringColumnDisplay;
import ghidra.app.tablechooser.TableChooserDialog;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;
import ghidra.program.util.CyclomaticComplexity;
import ghidra.util.exception.CancelledException;
// based off of ComputeCyclomaticComplexity.java
// CompareFunctionSizesScript.java provides a useful example for writing plugins with UI popups
/*
./analyzeHeadless [path to directory containing .g] [project name] -process -prescript [path to this script] -noanalysis
$ ./analyzeHeadless ~/research/INFILTRATE/projects/ test.gpr -process -prescript ~/ghidra_scripts/CompletedComputeCyclomaticComplexityForAllFunctions.java -noanalysis
*/
public class ComputeCyclomaticComplexityForAllFunctions extends GhidraScript {
private CyclomaticComplexity cyclo = new CyclomaticComplexity();
@Override
protected void run() throws Exception {
if (currentProgram == null) {
printerr("no current program");
return;
}
FunctionIterator functionIterator = currentProgram.getFunctionManager().getFunctions(true);
if (!isRunningHeadless()) {
TableChooserDialog tableDialog = createTableChooserDialog(currentProgram.getName() + " - Function Cyclomatic Complexity", null, false);
configureTableColumns(tableDialog);
tableDialog.show();
for ( Function currentFunction : functionIterator ) {
FuncCycloData funcCycloData = new FuncCycloData(currentFunction);
tableDialog.add(funcCycloData);
}
}
else { //isRunningHeadless
for( Function currentFunction : functionIterator ) {
int functionCyclomaticComplexity = cyclo.calculateCyclomaticComplexity(currentFunction, getMonitor());;
printf("%s complexity: %d\n", currentFunction.getName(), functionCyclomaticComplexity);
}
}
}
private class FuncCycloData implements AddressableRowObject {
private Function function;
private Integer functionCyclomaticComplexity;
private Address functionAddress;
public FuncCycloData(Function f) throws CancelledException {
function = f;
functionAddress = function.getEntryPoint();
functionCyclomaticComplexity = cyclo.calculateCyclomaticComplexity(function, getMonitor());
}
@Override
public Address getAddress() {
return functionAddress;
}
public Function getFunction() {
return function;
}
public int getCylomaticComplexity() {
return functionCyclomaticComplexity;
}
}
private void configureTableColumns(TableChooserDialog dialog) throws CancelledException {
StringColumnDisplay functionNameColumn = new StringColumnDisplay() {
@Override
public String getColumnName() {
return "Function Name";
}
@Override
public String getColumnValue(AddressableRowObject rowObject) {
return ((FuncCycloData) rowObject).getFunction().getName();
}
};
ColumnDisplay<Integer> cyclomaticComplexityColumn = new AbstractComparableColumnDisplay<Integer>() {
@Override
public Integer getColumnValue(AddressableRowObject rowObject) {
return ((FuncCycloData) rowObject).getCylomaticComplexity();
}
@Override
public String getColumnName() {
return "Cyclomatic Complexity";
}
};
dialog.addCustomColumn(functionNameColumn);
dialog.addCustomColumn(cyclomaticComplexityColumn);
}
}