Skip to content
This repository was archived by the owner on Nov 16, 2025. It is now read-only.

Commit 489450e

Browse files
committed
Improve performance and logging in handler utilities
Increased decompiler cache refresh delay in SetPlateComment for reliability. Enhanced DecompileFunctionByAddress to use DecompInterface directly and improved error handling. Added progress logging for comment setting in DocumentFunctionComplete. Optimized BatchRenameVariables by suppressing events during batch renames to avoid repeated re-analysis. Updated ParseUtils to support HTTP keep-alive and improved type safety in map conversion.
1 parent a6c67c1 commit 489450e

5 files changed

Lines changed: 60 additions & 34 deletions

File tree

src/main/java/com/lauriewired/handlers/comments/SetPlateComment.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ private String setPlateComment(String functionAddress, String comment) {
8989
// Force event processing to ensure changes propagate to decompiler cache
9090
if (success.get()) {
9191
program.flushEvents();
92-
// Small delay to ensure decompiler cache refresh
92+
// Increased delay to ensure decompiler cache refresh
9393
try {
94-
Thread.sleep(50);
94+
Thread.sleep(200);
9595
} catch (InterruptedException e) {
9696
Thread.currentThread().interrupt();
9797
}

src/main/java/com/lauriewired/handlers/functions/DecompileFunctionByAddress.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.IOException;
1313
import java.util.Map;
1414

15+
import static com.lauriewired.GhidraMCPPlugin.*;
1516
import static com.lauriewired.util.GhidraUtils.decompileFunctionInProgram;
1617
import static com.lauriewired.util.ParseUtils.*;
1718
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;
@@ -52,22 +53,22 @@ public void handle(HttpExchange exchange) throws IOException {
5253
* @return the decompiled C code or an error message
5354
*/
5455
private String decompileFunctionByAddress(String addressStr) {
55-
Program program = getCurrentProgram(tool);
56-
if (program == null)
57-
return "No program loaded";
58-
if (addressStr == null || addressStr.isEmpty())
59-
return "Address is required";
56+
Program program = getCurrentProgram();
57+
if (program == null) return "No program loaded";
58+
if (addressStr == null || addressStr.isEmpty()) return "Address is required";
6059

6160
try {
6261
Address addr = program.getAddressFactory().getAddress(addressStr);
63-
Function func = program.getListing().getFunctionContaining(addr);
64-
if (func == null)
65-
return "No function found at or containing address " + addressStr;
62+
Function func = getFunctionForAddress(program, addr);
63+
if (func == null) return "No function found at or containing address " + addressStr;
6664

67-
String decompCode = decompileFunctionInProgram(func, program);
68-
return (decompCode != null && !decompCode.isEmpty())
69-
? decompCode
70-
: "Decompilation failed";
65+
DecompInterface decomp = new DecompInterface();
66+
decomp.openProgram(program);
67+
DecompileResults result = decomp.decompileFunction(func, DECOMPILE_TIMEOUT_SECONDS, new ConsoleTaskMonitor());
68+
69+
return (result != null && result.decompileCompleted())
70+
? result.getDecompiledFunction().getC()
71+
: "Decompilation failed";
7172
} catch (Exception e) {
7273
return "Error decompiling function: " + e.getMessage();
7374
}

src/main/java/com/lauriewired/handlers/functions/DocumentFunctionComplete.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,16 +207,23 @@ private String documentFunctionComplete(String functionAddress, String newName,
207207
if (cAddr != null) {
208208
program.getListing().setComment(cAddr, CodeUnit.PRE_COMMENT, commentText);
209209
commentsSet++;
210+
// Log progress every 10 comments
211+
if (commentsSet % 10 == 0) {
212+
Msg.info(this, "Progress: " + commentsSet + "/" + totalComments + " decompiler comments set");
213+
}
210214
}
211215
}
212216
}
213217
operationsCompleted.incrementAndGet();
214218
result.append("\"decompiler_comments_set\": ").append(commentsSet).append(", ");
219+
Msg.info(this, "Completed: " + commentsSet + " decompiler comments set");
215220
}
216221

217-
// Set disassembly comments
222+
// Set disassembly comments with process logging
218223
if (disassemblyComments != null && !disassemblyComments.isEmpty()) {
219224
int commentsSet = 0;
225+
int totalComments = disassemblyComments.size();
226+
Msg.info(this, "Setting " + totalComments + " disassembly comments...");
220227
for (Map<String, String> comment : disassemblyComments) {
221228
String commentAddr = comment.get("address");
222229
String commentText = comment.get("comment");
@@ -225,11 +232,16 @@ private String documentFunctionComplete(String functionAddress, String newName,
225232
if (cAddr != null) {
226233
program.getListing().setComment(cAddr, CodeUnit.EOL_COMMENT, commentText);
227234
commentsSet++;
235+
// Log progress every 10 comments
236+
if (commentsSet % 10 == 0) {
237+
Msg.info(this, "Progress: " + commentsSet + "/" + totalComments + " disassembly comments set");
238+
}
228239
}
229240
}
230241
}
231242
operationsCompleted.incrementAndGet();
232243
result.append("\"disassembly_comments_set\": ").append(commentsSet).append(", ");
244+
Msg.info(this, "Completed: " + commentsSet + " disassembly comments set");
233245
}
234246

235247
result.append("\"operations_completed\": ").append(operationsCompleted.get());

src/main/java/com/lauriewired/handlers/variables/BatchRenameVariables.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ private String batchRenameVariables(String functionAddress, Map<String, String>
6666
try {
6767
SwingUtilities.invokeAndWait(() -> {
6868
int tx = program.startTransaction("Batch Rename Variables");
69+
// Suppress events during batch operation to prevent re-analysis on each rename
70+
int eventTx = program.startTransaction("Suppress Events");
71+
program.flushEvents(); // Flush any pending events before we start
72+
6973
try {
7074
Address addr = program.getAddressFactory().getAddress(functionAddress);
7175
if (addr == null) {
@@ -80,7 +84,7 @@ private String batchRenameVariables(String functionAddress, Map<String, String>
8084
}
8185

8286
if (variableRenames != null && !variableRenames.isEmpty()) {
83-
// Rename parameters
87+
// Rename parameters (events suppressed - no re-analysis per rename)
8488
for (Parameter param : func.getParameters()) {
8589
String newName = variableRenames.get(param.getName());
8690
if (newName != null && !newName.isEmpty()) {
@@ -94,7 +98,7 @@ private String batchRenameVariables(String functionAddress, Map<String, String>
9498
}
9599
}
96100

97-
// Rename local variables
101+
// Rename local variables (events suppressed - no re-analysis per rename)
98102
for (Variable local : func.getLocalVariables()) {
99103
String newName = variableRenames.get(local.getName());
100104
if (newName != null && !newName.isEmpty()) {
@@ -114,6 +118,9 @@ private String batchRenameVariables(String functionAddress, Map<String, String>
114118
result.append("\"error\": \"").append(e.getMessage().replace("\"", "\\\"")).append("\"");
115119
Msg.error(this, "Error in batch rename variables", e);
116120
} finally {
121+
// End event suppression transaction - this triggers ONE re-analysis for all renames
122+
program.endTransaction(eventTx, success.get());
123+
program.flushEvents(); // Force event processing now that we're done
117124
program.endTransaction(tx, success.get());
118125
}
119126
});

src/main/java/com/lauriewired/util/ParseUtils.java

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import java.util.List;
1515
import java.util.Map;
1616

17+
import static com.lauriewired.GhidraMCPPlugin.*;
18+
1719
/**
1820
* Utility methods for parsing HTTP requests and responses.
1921
*
@@ -56,26 +58,26 @@ public FieldDefinition(String name, String type, int offset) {
5658
* @return A list of maps if the object is a list of maps, otherwise null.
5759
*/
5860
@SuppressWarnings("unchecked")
59-
public static List<Map<String, String>> convertToMapList(Object obj) {
60-
if (obj == null) {
61-
return null;
62-
}
61+
public static List<Map<String, String>> convertToMapList(Object obj) {
62+
if (obj == null) {
63+
return null;
64+
}
6365

64-
if (obj instanceof List) {
65-
List<Object> objList = (List<Object>) obj;
66-
List<Map<String, String>> result = new ArrayList<>();
66+
if (obj instanceof List) {
67+
List<Object> objList = (List<Object>) obj;
68+
List<Map<String, String>> result = new ArrayList<>();
6769

68-
for (Object item : objList) {
69-
if (item instanceof Map) {
70-
result.add((Map<String, String>) item);
71-
}
72-
}
70+
for (Object item : objList) {
71+
if (item instanceof Map) {
72+
result.add((Map<String, String>) item);
73+
}
74+
}
7375

74-
return result;
75-
}
76+
return result;
77+
}
7678

77-
return null;
78-
}
79+
return null;
80+
}
7981

8082
/**
8183
* Decode a hexadecimal string into a byte array.
@@ -506,7 +508,11 @@ public static Map<String, Long> parseValuesJson(String valuesJson) {
506508
*/
507509
public static void sendResponse(HttpExchange exchange, String response) throws IOException {
508510
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
509-
exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8");
511+
Headers headers = exchange.getResponseHeaders();
512+
headers.set("Content-Type", "text/plain; charset=utf-8");
513+
// Enable HTTP keep-alive for long-running operations
514+
headers.set("Connection", "keep-alive");
515+
headers.set("Keep-Alive", "timeout=" + HTTP_IDLE_TIMEOUT_SECONDS + ", max=100");
510516
exchange.sendResponseHeaders(200, bytes.length);
511517
try (OutputStream os = exchange.getResponseBody()) {
512518
os.write(bytes);

0 commit comments

Comments
 (0)