windows-exe-decompiler-mcp-server 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CLAUDE_INSTALLATION.md +129 -0
  2. package/CODEX_INSTALLATION.md +25 -1
  3. package/COPILOT_INSTALLATION.md +29 -1
  4. package/LICENSE +21 -21
  5. package/README.md +232 -110
  6. package/dist/analysis-provenance.d.ts +50 -2
  7. package/dist/analysis-provenance.js +1 -0
  8. package/dist/analysis-task-runner.js +92 -0
  9. package/dist/config.d.ts +35 -16
  10. package/dist/config.js +37 -3
  11. package/dist/database.js +115 -115
  12. package/dist/decompiler-worker.d.ts +10 -5
  13. package/dist/decompiler-worker.js +240 -58
  14. package/dist/dynamic-trace.d.ts +6 -0
  15. package/dist/dynamic-trace.js +52 -1
  16. package/dist/ghidra-config.js +17 -1
  17. package/dist/index.js +38 -8
  18. package/dist/pe-runtime-functions.d.ts +90 -0
  19. package/dist/pe-runtime-functions.js +452 -0
  20. package/dist/prompts/module-reconstruction-review.d.ts +5 -0
  21. package/dist/prompts/module-reconstruction-review.js +65 -0
  22. package/dist/runtime-correlation.d.ts +5 -0
  23. package/dist/runtime-correlation.js +179 -2
  24. package/dist/sample-workspace.d.ts +28 -0
  25. package/dist/sample-workspace.js +186 -0
  26. package/dist/semantic-name-suggestion-artifacts.d.ts +56 -0
  27. package/dist/semantic-name-suggestion-artifacts.js +87 -0
  28. package/dist/server.js +1 -1
  29. package/dist/setup-guidance.d.ts +73 -0
  30. package/dist/setup-guidance.js +211 -0
  31. package/dist/tools/artifact-read.d.ts +10 -10
  32. package/dist/tools/artifacts-diff.d.ts +8 -8
  33. package/dist/tools/artifacts-list.d.ts +16 -16
  34. package/dist/tools/attack-map.d.ts +8 -8
  35. package/dist/tools/binary-role-profile.d.ts +1197 -0
  36. package/dist/tools/binary-role-profile.js +575 -0
  37. package/dist/tools/code-function-explain-apply.d.ts +12 -12
  38. package/dist/tools/code-function-explain-prepare.d.ts +12 -12
  39. package/dist/tools/code-function-explain-review.d.ts +58 -58
  40. package/dist/tools/code-function-rename-apply.d.ts +12 -12
  41. package/dist/tools/code-function-rename-prepare.d.ts +14 -14
  42. package/dist/tools/code-function-rename-review.d.ts +66 -66
  43. package/dist/tools/code-functions-define.d.ts +337 -0
  44. package/dist/tools/code-functions-define.js +337 -0
  45. package/dist/tools/code-functions-list.js +1 -1
  46. package/dist/tools/code-functions-rank.js +1 -1
  47. package/dist/tools/code-functions-reconstruct.d.ts +368 -58
  48. package/dist/tools/code-functions-reconstruct.js +130 -10
  49. package/dist/tools/code-functions-smart-recover.d.ts +352 -0
  50. package/dist/tools/code-functions-smart-recover.js +190 -0
  51. package/dist/tools/code-module-review-apply.d.ts +233 -0
  52. package/dist/tools/code-module-review-apply.js +209 -0
  53. package/dist/tools/code-module-review-prepare.d.ts +756 -0
  54. package/dist/tools/code-module-review-prepare.js +343 -0
  55. package/dist/tools/code-module-review.d.ts +474 -0
  56. package/dist/tools/code-module-review.js +566 -0
  57. package/dist/tools/code-reconstruct-export.d.ts +193 -21
  58. package/dist/tools/code-reconstruct-export.js +578 -21
  59. package/dist/tools/code-reconstruct-plan.d.ts +20 -20
  60. package/dist/tools/com-role-profile.d.ts +353 -0
  61. package/dist/tools/com-role-profile.js +186 -0
  62. package/dist/tools/dll-export-profile.d.ts +625 -0
  63. package/dist/tools/dll-export-profile.js +230 -0
  64. package/dist/tools/dotnet-metadata-extract.d.ts +122 -122
  65. package/dist/tools/dotnet-reconstruct-export.d.ts +49 -49
  66. package/dist/tools/dotnet-types-list.d.ts +66 -66
  67. package/dist/tools/dynamic-dependencies.d.ts +144 -8
  68. package/dist/tools/dynamic-dependencies.js +20 -1
  69. package/dist/tools/dynamic-memory-import.js +105 -2
  70. package/dist/tools/ghidra-analyze.d.ts +20 -0
  71. package/dist/tools/ghidra-analyze.js +10 -2
  72. package/dist/tools/ghidra-health.d.ts +177 -0
  73. package/dist/tools/ghidra-health.js +28 -0
  74. package/dist/tools/ioc-export.d.ts +8 -8
  75. package/dist/tools/packer-detect.d.ts +14 -14
  76. package/dist/tools/packer-detect.js +6 -9
  77. package/dist/tools/pe-exports-extract.d.ts +8 -8
  78. package/dist/tools/pe-exports-extract.js +6 -9
  79. package/dist/tools/pe-fingerprint.d.ts +36 -36
  80. package/dist/tools/pe-imports-extract.d.ts +8 -8
  81. package/dist/tools/pe-imports-extract.js +6 -9
  82. package/dist/tools/pe-pdata-extract.d.ts +448 -0
  83. package/dist/tools/pe-pdata-extract.js +219 -0
  84. package/dist/tools/pe-symbols-recover.d.ts +227 -0
  85. package/dist/tools/pe-symbols-recover.js +316 -0
  86. package/dist/tools/report-generate.d.ts +15 -1
  87. package/dist/tools/report-generate.js +139 -16
  88. package/dist/tools/report-summarize.d.ts +2242 -8
  89. package/dist/tools/report-summarize.js +246 -10
  90. package/dist/tools/runtime-detect.d.ts +8 -8
  91. package/dist/tools/runtime-detect.js +2 -12
  92. package/dist/tools/rust-binary-analyze.d.ts +2047 -0
  93. package/dist/tools/rust-binary-analyze.js +443 -0
  94. package/dist/tools/sample-profile-get.d.ts +135 -16
  95. package/dist/tools/sample-profile-get.js +35 -32
  96. package/dist/tools/sandbox-execute.d.ts +10 -10
  97. package/dist/tools/strings-extract.d.ts +8 -8
  98. package/dist/tools/strings-extract.js +2 -12
  99. package/dist/tools/strings-floss-decode.d.ts +8 -8
  100. package/dist/tools/system-health.d.ts +172 -36
  101. package/dist/tools/system-health.js +14 -0
  102. package/dist/tools/system-setup-guide.d.ts +179 -0
  103. package/dist/tools/system-setup-guide.js +62 -0
  104. package/dist/tools/tool-help.d.ts +16 -16
  105. package/dist/tools/tool-help.js +172 -0
  106. package/dist/tools/yara-scan.d.ts +8 -8
  107. package/dist/types.d.ts +2 -0
  108. package/dist/workflows/function-explanation-review.d.ts +3034 -76
  109. package/dist/workflows/function-explanation-review.js +172 -42
  110. package/dist/workflows/function-index-recover.d.ts +333 -0
  111. package/dist/workflows/function-index-recover.js +291 -0
  112. package/dist/workflows/module-reconstruction-review.d.ts +3537 -0
  113. package/dist/workflows/module-reconstruction-review.js +354 -0
  114. package/dist/workflows/reconstruct.d.ts +2182 -223
  115. package/dist/workflows/reconstruct.js +575 -32
  116. package/dist/workflows/semantic-name-review.d.ts +1436 -85
  117. package/dist/workflows/semantic-name-review.js +150 -58
  118. package/dist/workflows/triage.d.ts +8 -8
  119. package/ghidra_scripts/DecompileFunction.java +487 -487
  120. package/ghidra_scripts/ExtractCFG.java +256 -256
  121. package/ghidra_scripts/ExtractFunctions.java +442 -442
  122. package/ghidra_scripts/README.md +112 -112
  123. package/ghidra_scripts/SearchFunctionReferences.java +380 -380
  124. package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -9
  125. package/helpers/DotNetMetadataProbe/Program.cs +566 -566
  126. package/install-to-claude.ps1 +432 -0
  127. package/install-to-codex.ps1 +256 -178
  128. package/install-to-copilot.ps1 +389 -303
  129. package/package.json +4 -2
  130. package/requirements.txt +9 -9
  131. package/workers/requirements-dynamic.txt +11 -11
  132. package/workers/requirements.txt +8 -8
  133. package/workers/speakeasy_compat.py +175 -175
  134. package/workers/static_worker.py +3474 -3474
@@ -1,256 +1,256 @@
1
- // ExtractCFG.java - Java fallback for CFG extraction
2
- // @category Analysis
3
- // @description Extracts a control-flow graph for a function and returns JSON
4
-
5
- import ghidra.app.script.GhidraScript;
6
- import ghidra.program.model.address.Address;
7
- import ghidra.program.model.block.BasicBlockModel;
8
- import ghidra.program.model.block.CodeBlock;
9
- import ghidra.program.model.block.CodeBlockIterator;
10
- import ghidra.program.model.block.CodeBlockReference;
11
- import ghidra.program.model.block.CodeBlockReferenceIterator;
12
- import ghidra.program.model.listing.Function;
13
- import ghidra.program.model.listing.FunctionIterator;
14
- import ghidra.program.model.listing.FunctionManager;
15
- import ghidra.program.model.listing.Instruction;
16
- import ghidra.program.model.symbol.Symbol;
17
- import ghidra.program.model.symbol.SymbolIterator;
18
- import ghidra.program.model.symbol.SymbolType;
19
-
20
- import java.util.LinkedHashMap;
21
- import java.util.Map;
22
-
23
- public class ExtractCFG extends GhidraScript {
24
-
25
- private String escapeJson(String value) {
26
- if (value == null) {
27
- return "";
28
- }
29
- StringBuilder out = new StringBuilder(value.length() + 16);
30
- for (int i = 0; i < value.length(); i++) {
31
- char c = value.charAt(i);
32
- switch (c) {
33
- case '"':
34
- out.append("\\\"");
35
- break;
36
- case '\\':
37
- out.append("\\\\");
38
- break;
39
- case '\b':
40
- out.append("\\b");
41
- break;
42
- case '\f':
43
- out.append("\\f");
44
- break;
45
- case '\n':
46
- out.append("\\n");
47
- break;
48
- case '\r':
49
- out.append("\\r");
50
- break;
51
- case '\t':
52
- out.append("\\t");
53
- break;
54
- default:
55
- if (c < 0x20) {
56
- out.append(String.format("\\u%04x", (int) c));
57
- } else {
58
- out.append(c);
59
- }
60
- }
61
- }
62
- return out.toString();
63
- }
64
-
65
- private Function resolveFunction(String addressOrSymbol) {
66
- FunctionManager manager = currentProgram.getFunctionManager();
67
- try {
68
- Address address = currentProgram.getAddressFactory().getAddress(addressOrSymbol);
69
- Function byAddress = manager.getFunctionAt(address);
70
- if (byAddress != null) {
71
- return byAddress;
72
- }
73
- } catch (Exception ignored) {
74
- }
75
-
76
- SymbolIterator iterator = currentProgram.getSymbolTable().getSymbols(addressOrSymbol);
77
- while (iterator.hasNext()) {
78
- Symbol symbol = iterator.next();
79
- if (symbol.getSymbolType() != SymbolType.FUNCTION) {
80
- continue;
81
- }
82
- Function bySymbol = manager.getFunctionAt(symbol.getAddress());
83
- if (bySymbol != null) {
84
- return bySymbol;
85
- }
86
- }
87
-
88
- FunctionIterator functions = manager.getFunctions(true);
89
- while (functions.hasNext()) {
90
- Function function = functions.next();
91
- if (addressOrSymbol.equals(function.getName())) {
92
- return function;
93
- }
94
- }
95
-
96
- return null;
97
- }
98
-
99
- private String getBlockType(CodeBlock block, Function function) throws Exception {
100
- if (block.getFirstStartAddress().equals(function.getEntryPoint())) {
101
- return "entry";
102
- }
103
-
104
- CodeBlockReferenceIterator destinations = block.getDestinations(monitor);
105
- if (!destinations.hasNext()) {
106
- return "exit";
107
- }
108
-
109
- Instruction instruction = currentProgram.getListing().getInstructionAt(block.getFirstStartAddress());
110
- while (instruction != null && block.contains(instruction.getAddress())) {
111
- if (instruction.getFlowType().isCall()) {
112
- return "call";
113
- }
114
- if (instruction.getFlowType().isTerminal()) {
115
- return "return";
116
- }
117
- instruction = instruction.getNext();
118
- }
119
-
120
- return "basic";
121
- }
122
-
123
- private String getEdgeType(CodeBlock sourceBlock) {
124
- Instruction instruction = currentProgram.getListing().getInstructionAt(sourceBlock.getMaxAddress());
125
- if (instruction == null) {
126
- return "fallthrough";
127
- }
128
- if (instruction.getFlowType().isCall()) {
129
- return "call";
130
- }
131
- if (instruction.getFlowType().isJump()) {
132
- return "jump";
133
- }
134
- if (instruction.getFlowType().isTerminal()) {
135
- return "return";
136
- }
137
- return "fallthrough";
138
- }
139
-
140
- @Override
141
- protected void run() throws Exception {
142
- if (currentProgram == null) {
143
- println("{\"error\":\"No program loaded\"}");
144
- return;
145
- }
146
-
147
- String[] args = getScriptArgs();
148
- if (args.length < 1) {
149
- println("{\"error\":\"Usage: ExtractCFG.java <address|symbol>\"}");
150
- return;
151
- }
152
-
153
- Function function = resolveFunction(args[0]);
154
- if (function == null) {
155
- println("{\"error\":\"Function not found: " + escapeJson(args[0]) + "\"}");
156
- return;
157
- }
158
-
159
- BasicBlockModel blockModel = new BasicBlockModel(currentProgram);
160
- Map<String, String> blockIds = new LinkedHashMap<>();
161
- StringBuilder nodes = new StringBuilder(16384);
162
- StringBuilder edges = new StringBuilder(16384);
163
-
164
- boolean firstNode = true;
165
- int blockIndex = 0;
166
- CodeBlockIterator blocks = blockModel.getCodeBlocksContaining(function.getBody(), monitor);
167
- while (blocks.hasNext()) {
168
- CodeBlock block = blocks.next();
169
- String blockAddress = block.getFirstStartAddress().toString();
170
- String blockId = "block_" + blockIndex++;
171
- blockIds.put(blockAddress, blockId);
172
-
173
- if (!firstNode) {
174
- nodes.append(',');
175
- }
176
- firstNode = false;
177
-
178
- nodes.append('{');
179
- nodes.append("\"id\":\"").append(escapeJson(blockId)).append("\",");
180
- nodes.append("\"address\":\"").append(escapeJson(blockAddress)).append("\",");
181
- nodes.append("\"instructions\":[");
182
-
183
- boolean firstInstruction = true;
184
- Instruction instruction = currentProgram.getListing().getInstructionAt(block.getFirstStartAddress());
185
- while (instruction != null && block.contains(instruction.getAddress())) {
186
- if (!firstInstruction) {
187
- nodes.append(',');
188
- }
189
- firstInstruction = false;
190
- String operand =
191
- instruction.getNumOperands() > 0
192
- ? instruction.getDefaultOperandRepresentation(0)
193
- : "";
194
- nodes.append("\"")
195
- .append(escapeJson(
196
- instruction.getAddress().toString()
197
- + ": "
198
- + instruction.getMnemonicString()
199
- + (operand.length() > 0 ? " " + operand : "")
200
- ))
201
- .append("\"");
202
- instruction = instruction.getNext();
203
- }
204
-
205
- nodes.append("],\"type\":\"")
206
- .append(escapeJson(getBlockType(block, function)))
207
- .append("\"}");
208
- }
209
-
210
- boolean firstEdge = true;
211
- blocks = blockModel.getCodeBlocksContaining(function.getBody(), monitor);
212
- while (blocks.hasNext()) {
213
- CodeBlock block = blocks.next();
214
- String fromId = blockIds.get(block.getFirstStartAddress().toString());
215
- if (fromId == null) {
216
- continue;
217
- }
218
-
219
- CodeBlockReferenceIterator destinations = block.getDestinations(monitor);
220
- while (destinations.hasNext()) {
221
- CodeBlockReference destination = destinations.next();
222
- if (!function.getBody().contains(destination.getDestinationAddress())) {
223
- continue;
224
- }
225
-
226
- String toId = blockIds.get(destination.getDestinationAddress().toString());
227
- if (toId == null) {
228
- continue;
229
- }
230
-
231
- if (!firstEdge) {
232
- edges.append(',');
233
- }
234
- firstEdge = false;
235
-
236
- edges.append("{\"from\":\"")
237
- .append(escapeJson(fromId))
238
- .append("\",\"to\":\"")
239
- .append(escapeJson(toId))
240
- .append("\",\"type\":\"")
241
- .append(escapeJson(getEdgeType(block)))
242
- .append("\"}");
243
- }
244
- }
245
-
246
- StringBuilder output = new StringBuilder(32768);
247
- output.append('{');
248
- output.append("\"function\":\"").append(escapeJson(function.getName())).append("\",");
249
- output.append("\"address\":\"").append(escapeJson(function.getEntryPoint().toString())).append("\",");
250
- output.append("\"nodes\":[").append(nodes).append("],");
251
- output.append("\"edges\":[").append(edges).append("]");
252
- output.append('}');
253
-
254
- println(output.toString());
255
- }
256
- }
1
+ // ExtractCFG.java - Java fallback for CFG extraction
2
+ // @category Analysis
3
+ // @description Extracts a control-flow graph for a function and returns JSON
4
+
5
+ import ghidra.app.script.GhidraScript;
6
+ import ghidra.program.model.address.Address;
7
+ import ghidra.program.model.block.BasicBlockModel;
8
+ import ghidra.program.model.block.CodeBlock;
9
+ import ghidra.program.model.block.CodeBlockIterator;
10
+ import ghidra.program.model.block.CodeBlockReference;
11
+ import ghidra.program.model.block.CodeBlockReferenceIterator;
12
+ import ghidra.program.model.listing.Function;
13
+ import ghidra.program.model.listing.FunctionIterator;
14
+ import ghidra.program.model.listing.FunctionManager;
15
+ import ghidra.program.model.listing.Instruction;
16
+ import ghidra.program.model.symbol.Symbol;
17
+ import ghidra.program.model.symbol.SymbolIterator;
18
+ import ghidra.program.model.symbol.SymbolType;
19
+
20
+ import java.util.LinkedHashMap;
21
+ import java.util.Map;
22
+
23
+ public class ExtractCFG extends GhidraScript {
24
+
25
+ private String escapeJson(String value) {
26
+ if (value == null) {
27
+ return "";
28
+ }
29
+ StringBuilder out = new StringBuilder(value.length() + 16);
30
+ for (int i = 0; i < value.length(); i++) {
31
+ char c = value.charAt(i);
32
+ switch (c) {
33
+ case '"':
34
+ out.append("\\\"");
35
+ break;
36
+ case '\\':
37
+ out.append("\\\\");
38
+ break;
39
+ case '\b':
40
+ out.append("\\b");
41
+ break;
42
+ case '\f':
43
+ out.append("\\f");
44
+ break;
45
+ case '\n':
46
+ out.append("\\n");
47
+ break;
48
+ case '\r':
49
+ out.append("\\r");
50
+ break;
51
+ case '\t':
52
+ out.append("\\t");
53
+ break;
54
+ default:
55
+ if (c < 0x20) {
56
+ out.append(String.format("\\u%04x", (int) c));
57
+ } else {
58
+ out.append(c);
59
+ }
60
+ }
61
+ }
62
+ return out.toString();
63
+ }
64
+
65
+ private Function resolveFunction(String addressOrSymbol) {
66
+ FunctionManager manager = currentProgram.getFunctionManager();
67
+ try {
68
+ Address address = currentProgram.getAddressFactory().getAddress(addressOrSymbol);
69
+ Function byAddress = manager.getFunctionAt(address);
70
+ if (byAddress != null) {
71
+ return byAddress;
72
+ }
73
+ } catch (Exception ignored) {
74
+ }
75
+
76
+ SymbolIterator iterator = currentProgram.getSymbolTable().getSymbols(addressOrSymbol);
77
+ while (iterator.hasNext()) {
78
+ Symbol symbol = iterator.next();
79
+ if (symbol.getSymbolType() != SymbolType.FUNCTION) {
80
+ continue;
81
+ }
82
+ Function bySymbol = manager.getFunctionAt(symbol.getAddress());
83
+ if (bySymbol != null) {
84
+ return bySymbol;
85
+ }
86
+ }
87
+
88
+ FunctionIterator functions = manager.getFunctions(true);
89
+ while (functions.hasNext()) {
90
+ Function function = functions.next();
91
+ if (addressOrSymbol.equals(function.getName())) {
92
+ return function;
93
+ }
94
+ }
95
+
96
+ return null;
97
+ }
98
+
99
+ private String getBlockType(CodeBlock block, Function function) throws Exception {
100
+ if (block.getFirstStartAddress().equals(function.getEntryPoint())) {
101
+ return "entry";
102
+ }
103
+
104
+ CodeBlockReferenceIterator destinations = block.getDestinations(monitor);
105
+ if (!destinations.hasNext()) {
106
+ return "exit";
107
+ }
108
+
109
+ Instruction instruction = currentProgram.getListing().getInstructionAt(block.getFirstStartAddress());
110
+ while (instruction != null && block.contains(instruction.getAddress())) {
111
+ if (instruction.getFlowType().isCall()) {
112
+ return "call";
113
+ }
114
+ if (instruction.getFlowType().isTerminal()) {
115
+ return "return";
116
+ }
117
+ instruction = instruction.getNext();
118
+ }
119
+
120
+ return "basic";
121
+ }
122
+
123
+ private String getEdgeType(CodeBlock sourceBlock) {
124
+ Instruction instruction = currentProgram.getListing().getInstructionAt(sourceBlock.getMaxAddress());
125
+ if (instruction == null) {
126
+ return "fallthrough";
127
+ }
128
+ if (instruction.getFlowType().isCall()) {
129
+ return "call";
130
+ }
131
+ if (instruction.getFlowType().isJump()) {
132
+ return "jump";
133
+ }
134
+ if (instruction.getFlowType().isTerminal()) {
135
+ return "return";
136
+ }
137
+ return "fallthrough";
138
+ }
139
+
140
+ @Override
141
+ protected void run() throws Exception {
142
+ if (currentProgram == null) {
143
+ println("{\"error\":\"No program loaded\"}");
144
+ return;
145
+ }
146
+
147
+ String[] args = getScriptArgs();
148
+ if (args.length < 1) {
149
+ println("{\"error\":\"Usage: ExtractCFG.java <address|symbol>\"}");
150
+ return;
151
+ }
152
+
153
+ Function function = resolveFunction(args[0]);
154
+ if (function == null) {
155
+ println("{\"error\":\"Function not found: " + escapeJson(args[0]) + "\"}");
156
+ return;
157
+ }
158
+
159
+ BasicBlockModel blockModel = new BasicBlockModel(currentProgram);
160
+ Map<String, String> blockIds = new LinkedHashMap<>();
161
+ StringBuilder nodes = new StringBuilder(16384);
162
+ StringBuilder edges = new StringBuilder(16384);
163
+
164
+ boolean firstNode = true;
165
+ int blockIndex = 0;
166
+ CodeBlockIterator blocks = blockModel.getCodeBlocksContaining(function.getBody(), monitor);
167
+ while (blocks.hasNext()) {
168
+ CodeBlock block = blocks.next();
169
+ String blockAddress = block.getFirstStartAddress().toString();
170
+ String blockId = "block_" + blockIndex++;
171
+ blockIds.put(blockAddress, blockId);
172
+
173
+ if (!firstNode) {
174
+ nodes.append(',');
175
+ }
176
+ firstNode = false;
177
+
178
+ nodes.append('{');
179
+ nodes.append("\"id\":\"").append(escapeJson(blockId)).append("\",");
180
+ nodes.append("\"address\":\"").append(escapeJson(blockAddress)).append("\",");
181
+ nodes.append("\"instructions\":[");
182
+
183
+ boolean firstInstruction = true;
184
+ Instruction instruction = currentProgram.getListing().getInstructionAt(block.getFirstStartAddress());
185
+ while (instruction != null && block.contains(instruction.getAddress())) {
186
+ if (!firstInstruction) {
187
+ nodes.append(',');
188
+ }
189
+ firstInstruction = false;
190
+ String operand =
191
+ instruction.getNumOperands() > 0
192
+ ? instruction.getDefaultOperandRepresentation(0)
193
+ : "";
194
+ nodes.append("\"")
195
+ .append(escapeJson(
196
+ instruction.getAddress().toString()
197
+ + ": "
198
+ + instruction.getMnemonicString()
199
+ + (operand.length() > 0 ? " " + operand : "")
200
+ ))
201
+ .append("\"");
202
+ instruction = instruction.getNext();
203
+ }
204
+
205
+ nodes.append("],\"type\":\"")
206
+ .append(escapeJson(getBlockType(block, function)))
207
+ .append("\"}");
208
+ }
209
+
210
+ boolean firstEdge = true;
211
+ blocks = blockModel.getCodeBlocksContaining(function.getBody(), monitor);
212
+ while (blocks.hasNext()) {
213
+ CodeBlock block = blocks.next();
214
+ String fromId = blockIds.get(block.getFirstStartAddress().toString());
215
+ if (fromId == null) {
216
+ continue;
217
+ }
218
+
219
+ CodeBlockReferenceIterator destinations = block.getDestinations(monitor);
220
+ while (destinations.hasNext()) {
221
+ CodeBlockReference destination = destinations.next();
222
+ if (!function.getBody().contains(destination.getDestinationAddress())) {
223
+ continue;
224
+ }
225
+
226
+ String toId = blockIds.get(destination.getDestinationAddress().toString());
227
+ if (toId == null) {
228
+ continue;
229
+ }
230
+
231
+ if (!firstEdge) {
232
+ edges.append(',');
233
+ }
234
+ firstEdge = false;
235
+
236
+ edges.append("{\"from\":\"")
237
+ .append(escapeJson(fromId))
238
+ .append("\",\"to\":\"")
239
+ .append(escapeJson(toId))
240
+ .append("\",\"type\":\"")
241
+ .append(escapeJson(getEdgeType(block)))
242
+ .append("\"}");
243
+ }
244
+ }
245
+
246
+ StringBuilder output = new StringBuilder(32768);
247
+ output.append('{');
248
+ output.append("\"function\":\"").append(escapeJson(function.getName())).append("\",");
249
+ output.append("\"address\":\"").append(escapeJson(function.getEntryPoint().toString())).append("\",");
250
+ output.append("\"nodes\":[").append(nodes).append("],");
251
+ output.append("\"edges\":[").append(edges).append("]");
252
+ output.append('}');
253
+
254
+ println(output.toString());
255
+ }
256
+ }