Skip to content
This repository was archived by the owner on Nov 16, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build Ghidra Extension

on:
push:
branches: [ main, master ]
branches: [ main, master, fix-build-action ]
pull_request:
branches: [ main, master ]

Expand All @@ -21,7 +21,9 @@ jobs:
distribution: 'temurin'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v5
with:
gradle-version: current

- name: Download Ghidra
run: |
Expand All @@ -31,7 +33,9 @@ jobs:
echo "GHIDRA_INSTALL_DIR=$GHIDRA_DIR" >> $GITHUB_ENV

- name: Build with Gradle
run: ./gradle build -PGHIDRA_INSTALL_DIR=$GHIDRA_INSTALL_DIR
env:
GHIDRA_INSTALL_DIR: ${{ env.GHIDRA_INSTALL_DIR }}
run: gradle build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
Expand Down
18 changes: 9 additions & 9 deletions src/main/java/com/lauriewired/GhidraMCPPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,22 @@ public class GhidraMCPPlugin extends Plugin {
public static final int MIN_FUNCTIONS_TO_ANALYZE = 1;

/** Maximum number of structure fields to analyze */
private static final int MAX_STRUCT_FIELDS = 256;
public static final int MAX_STRUCT_FIELDS = 256;

/** Maximum number of field examples to return */
private static final int MAX_FIELD_EXAMPLES = 50;
public static final int MAX_FIELD_EXAMPLES = 50;

/** Decompilation timeout in seconds */
private static final int DECOMPILE_TIMEOUT_SECONDS = 30;
public static final int DECOMPILE_TIMEOUT_SECONDS = 30;

/** Minimum token length for searches */
private static final int MIN_TOKEN_LENGTH = 3;
public static final int MIN_TOKEN_LENGTH = 3;

/** Maximum field offset for structure analysis */
private static final int MAX_FIELD_OFFSET = 65536;
public static final int MAX_FIELD_OFFSET = 65536;

/** Set of C language keywords to filter from field name suggestions */
private static final Set<String> C_KEYWORDS = Set.of(
public static final Set<String> C_KEYWORDS = Set.of(
"if", "else", "for", "while", "do", "switch", "case", "default",
"break", "continue", "return", "goto", "int", "void", "char",
"float", "double", "long", "short", "struct", "union", "enum",
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/lauriewired/handlers/Handler.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ public String getPath() {
return path;
}

/**
* Returns the paths this handler responds to.
*
* @return an array of paths
*/
public String[] getPaths() {
return new String[] { path };
}

/**
* Handles an HTTP request.
* Subclasses must implement this method to define how requests are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ public final class GetFunctionJumpTargets extends Handler {
* @param tool the plugin tool
*/
public GetFunctionJumpTargets(PluginTool tool) {
super(tool, "/function_jump_target_addresses", "/function_jump_targets");
super(tool, "/function_jump_target_addresses");
}

/**
* Returns the paths this handler responds to.
*
* @return an array of paths
*/
@Override
public String[] getPaths() {
return new String[] { "/function_jump_target_addresses", "/function_jump_targets" };
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Map;
import javax.swing.SwingUtilities;

import static com.lauriewired.util.GhidraUtils.getCurrentProgram;
import static com.lauriewired.util.ParseUtils.*;

public final class BatchSetComments extends Handler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public void handle(HttpExchange exchange) throws Exception {
Map<String, String> params = parsePostParams(exchange);
String address = params.get("address");
String comment = params.get("comment");
String result = setDecompilerComment(address, comment);
boolean success = setDecompilerComment(address, comment);
String result = success ? "Decompiler comment set successfully" : "Failed to set decompiler comment";
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public void handle(HttpExchange exchange) throws Exception {
Map<String, String> params = parsePostParams(exchange);
String address = params.get("address");
String comment = params.get("comment");
String result = setDisassemblyComment(address, comment);
boolean success = setDisassemblyComment(address, comment);
String result = success ? "Disassembly comment set successfully" : "Failed to set disassembly comment";
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Map;
import javax.swing.SwingUtilities;

import static com.lauriewired.util.GhidraUtils.getCurrentProgram;
import static com.lauriewired.util.ParseUtils.*;

public final class SetPlateComment extends Handler {
Expand Down Expand Up @@ -43,7 +44,7 @@ public void handle(HttpExchange exchange) throws Exception {
*/
@SuppressWarnings("deprecation")
private String setPlateComment(String functionAddress, String comment) {
Program program = getCurrentProgram();
Program program = getCurrentProgram(tool);
if (program == null) {
return "Error: No program loaded";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.program.Program;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.program.model.symbol.Symbol;

import java.nio.charset.StandardCharsets;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void handle(HttpExchange exchange) throws IOException {
Map<String, String> qparams = parseQueryParams(exchange);
String text = qparams.get("text");
int size = parseIntOrDefault(qparams.get("size"), 4);
sendResponse(exchange, formatNumberConversion(text, size));
sendResponse(exchange, formatNumberConversions(text, size));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
import ghidra.program.model.mem.Memory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static com.lauriewired.util.GhidraUtils.getCurrentProgram;
import static com.lauriewired.util.ParseUtils.*;
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;

public final class InspectMemoryContent extends Handler {
public InspectMemoryContent(PluginTool tool) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Parameter;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.Variable;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Variable;
import ghidra.util.Msg;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.Map;
import javax.swing.*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;;
import ghidra.program.model.listing.FunctionIterator;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.listing.Program;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public RenameFunction(PluginTool tool) {
@Override
public void handle(HttpExchange exchange) throws IOException {
Map<String, String> params = parsePostParams(exchange);
String result = renameFunction(params.get("oldName"), params.get("newName"));
boolean success = rename(params.get("oldName"), params.get("newName"));
String result = success ? "Function renamed successfully" : "Failed to rename function";
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public void handle(HttpExchange exchange) throws Exception {
Map<String, String> params = parsePostParams(exchange);
String functionAddress = params.get("function_address");
String newName = params.get("new_name");
String result = renameFunctionByAddress(functionAddress, newName);
boolean success = renameFunctionByAddress(functionAddress, newName);
String result = success ? "Function renamed successfully" : "Failed to rename function";
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public RenameData(PluginTool tool) {
@Override
public void handle(HttpExchange exchange) throws IOException {
Map<String, String> params = parsePostParams(exchange);
String result = renameDataAtAddress(params.get("address"), params.get("newName"));
sendResponse(exchange, result);
renameDataAtAddress(tool, params.get("address"), params.get("newName"));
sendResponse(exchange, "Data renamed successfully");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public void handle(HttpExchange exchange) throws IOException {
Map<String, String> params = parsePostParams(exchange);
String oldName = params.get("old_name");
String newName = params.get("new_name");
String result = renameGlobalVariable(oldName, newName);
boolean success = renameGlobalVariable(oldName, newName);
String result = success ? "Global variable renamed successfully" : "Failed to rename global variable";
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.io.IOException;
import java.util.Map;

import static com.lauriewired.util.GhidraUtils.createLabel;
import static com.lauriewired.util.ParseUtils.*;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ private String renameOrLabel(String addressStr, String newName) {

if (data != null) {
// Defined data exists - use rename_data logic
return renameDataAtAddress(addressStr, newName);
renameDataAtAddress(tool, addressStr, newName);
return "Data renamed successfully";
} else {
// No defined data - use create_label logic
return createLabel(addressStr, newName);
return createLabel(tool, addressStr, newName);
}

} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.lauriewired.handlers.misc;

import com.lauriewired.handlers.Handler;
import com.sun.net.httpserver.HttpExchange;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;

import java.io.IOException;

import static com.lauriewired.util.GhidraUtils.getCurrentProgram;
import static com.lauriewired.util.ParseUtils.sendResponse;
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;

/**
* Handler to check if the GhidraMCP plugin is running and if a program is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import javax.swing.SwingUtilities;

import static com.lauriewired.GhidraMCPPlugin.*;
import static com.lauriewired.util.GhidraUtils.*;
import static com.lauriewired.util.ParseUtils.*;
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;

/**
* Handler to analyze struct field usage in decompiled code.
Expand Down Expand Up @@ -215,7 +215,7 @@ private String analyzeStructFieldUsage(String addressStr, String structName, int
try {
SwingUtilities.invokeAndWait(() -> {
try {
Program program = getCurrentProgram();
Program program = getCurrentProgram(tool);
if (program == null) {
result.set("{\"error\": \"No program loaded\"}");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import java.util.Map;
import javax.swing.SwingUtilities;

import static com.lauriewired.GhidraMCPPlugin.*;
import static com.lauriewired.util.GhidraUtils.*;
import static com.lauriewired.util.ParseUtils.*;
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;

public final class GetFieldAccessContext extends Handler {
/**
Expand Down Expand Up @@ -66,7 +66,7 @@ private String getFieldAccessContext(String structAddressStr, int fieldOffset, i
try {
SwingUtilities.invokeAndWait(() -> {
try {
Program program = getCurrentProgram();
Program program = getCurrentProgram(tool);
if (program == null) {
result.set("{\"error\": \"No program loaded\"}");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import com.sun.net.httpserver.HttpExchange;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.Data;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeComponent;
import ghidra.program.model.data.Structure;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import ghidra.util.Msg;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.Map;
import javax.swing.*;
Expand All @@ -34,10 +34,12 @@ public BatchSetVariableTypes(PluginTool tool) {

@Override
public void handle(HttpExchange exchange) throws IOException {
Map<String, String> qparams = parseQueryParams(exchange);
String functionName = qparams.get("function_name");
Map<String, Object> params = parseJsonParams(exchange);
String functionAddress = (String) params.get("function_address");
@SuppressWarnings("unchecked")
Map<String, String> variableTypes = (Map<String, String>) params.get("variable_types");

String result = BatchSetVariableTypes(functionName);
String result = batchSetVariableTypes(functionAddress, variableTypes);
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ public void handle(HttpExchange exchange) throws Exception {
}

// Try to set the type
String result = setLocalVariableType(functionAddress, variableName, newType);
boolean success = setLocalVariableType(functionAddress, variableName, newType);
String result = success ? "Variable type set successfully" : "Failed to set variable type";
sendResponse(exchange, result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.util.task.ConsoleTaskMonitor;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static com.lauriewired.util.GhidraUtils.getCurrentProgram;
import static com.lauriewired.util.ParseUtils.*;
import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram;

public final class BatchDecompileXrefSources extends Handler {
/**
Expand Down
Loading