Skip to content

Commit ce856ce

Browse files
authored
Merge pull request #188 from cyberkaida/drop-11.3
Drop Ghidra 11.3 support
2 parents 8ddd0f1 + eb49c4f commit ce856ce

File tree

7 files changed

+44
-46
lines changed

7 files changed

+44
-46
lines changed

.github/copilot-instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- This is a Ghidra extensions for Ghidra 11.3 and later called "ReVa", the Reverse Engineering Assistant.
1+
- This is a Ghidra extensions for Ghidra 11.4 and later called "ReVa", the Reverse Engineering Assistant.
22
- The extension provides a Model Context Protocol (MCP) server for Ghidra. The server is implemented in Java and uses the MCP Java SDK.
33
- Remember that MCP is in development, so make sure to check the MCP documentation for the latest information.
44

@@ -10,4 +10,4 @@ Some good resources include:
1010
- We don't use a gradle wrapper, so just run `gradle` in the root directory to build the project. We do have the Java tools installed in VSCode so you can just check for errors with VSCode instead.
1111
- When writing tests, use the Ghidra test framework. The tests are in the `src/test` directory. It is easy to run them with `gradle test --info` and the integration tests with `gradle integrationTest --info`.
1212
- You can use standard gradle test filtering to run specific tests with both of the test targets.
13-
- We target Ghidra 11.3 and later. Note we should use Java 21.
13+
- We target Ghidra 11.4 and later. Note we should use Java 21.

.github/workflows/publish-ghidra.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@ jobs:
2323
# Build only on Linux since the extension is Java-only and platform-independent
2424
# This simplifies the build process and reduces CI time
2525
ghidra-version: [
26+
"11.4.2",
2627
"11.4",
27-
"11.3.2",
28-
"11.3.1",
29-
"11.3",
3028
"latest",
3129
]
3230
name: Build distribution 📦

.github/workflows/test-ghidra.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ jobs:
1818
matrix:
1919
os: [ubuntu-latest]
2020
ghidra-version: [
21+
"11.4.2",
2122
"11.4",
22-
"11.3.2",
23-
"11.3.1",
24-
"11.3",
2523
"latest",
2624
]
2725
name: Test on Ghidra ${{ matrix.ghidra-version }}

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ The server uses streamable transport (SSE) on port 8080 by default. Configuratio
117117
- MCP SDK: io.modelcontextprotocol.sdk v0.11.1 (uses MCP BOM)
118118
- Jackson: 2.17.0 (forced version for compatibility)
119119
- Jetty: 11.0.25 (embedded servlet support)
120-
- Target: Java 21, Ghidra 11.3+
120+
- Target: Java 21, Ghidra 11.4+
121121

122122
## Program Identification
123123
- **ALWAYS use `programPath` for program identifiers** in both tool inputs and outputs
@@ -136,7 +136,7 @@ The server uses streamable transport (SSE) on port 8080 by default. Configuratio
136136
- **Tool Pattern**: AbstractToolProvider base class with consistent parameter extraction and error handling
137137

138138
### Development Constraints
139-
- **Java**: Target Java 21, minimum Ghidra 11.3+
139+
- **Java**: Target Java 21, minimum Ghidra 11.4+
140140
- **Testing**: Integration tests require `java.awt.headless=false` (GUI environment)
141141
- **Build**: Use `gradle` directly, not gradle wrapper
142142
- **MCP SDK**: v0.11.1 with forced Jackson 2.17.0 for compatibility

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ You can ask questions like:
4949

5050
# Installation
5151

52-
> NOTE: ReVa only supports Ghidra 11.3 and above!
52+
> NOTE: ReVa only supports Ghidra 11.4 and above!
5353
5454
ReVa is a Ghidra extension. To install it, you can download the release for your
5555
version of Ghidra from the releases page and install it using the Ghidra extension manager.

src/main/java/reva/tools/comments/CommentToolProvider.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import ghidra.program.model.address.AddressSetView;
2626
import ghidra.program.model.address.AddressIterator;
2727
import ghidra.program.model.listing.CodeUnit;
28+
import ghidra.program.model.listing.CommentType;
2829
import ghidra.program.model.listing.Program;
2930
import ghidra.program.model.listing.Listing;
3031
import ghidra.program.model.listing.CodeUnitIterator;
@@ -41,12 +42,12 @@
4142
*/
4243
public class CommentToolProvider extends AbstractToolProvider {
4344

44-
private static final Map<String, Integer> COMMENT_TYPES = Map.of(
45-
"pre", CodeUnit.PRE_COMMENT,
46-
"eol", CodeUnit.EOL_COMMENT,
47-
"post", CodeUnit.POST_COMMENT,
48-
"plate", CodeUnit.PLATE_COMMENT,
49-
"repeatable", CodeUnit.REPEATABLE_COMMENT
45+
private static final Map<String, CommentType> COMMENT_TYPES = Map.of(
46+
"pre", CommentType.PRE,
47+
"eol", CommentType.EOL,
48+
"post", CommentType.POST,
49+
"plate", CommentType.PLATE,
50+
"repeatable", CommentType.REPEATABLE
5051
);
5152

5253
/**
@@ -93,7 +94,7 @@ private void registerSetCommentTool() throws McpError {
9394
String commentTypeStr = getOptionalString(request, "commentType", "eol");
9495
String comment = getString(request, "comment");
9596

96-
Integer commentType = COMMENT_TYPES.get(commentTypeStr.toLowerCase());
97+
CommentType commentType = COMMENT_TYPES.get(commentTypeStr.toLowerCase());
9798
if (commentType == null) {
9899
return createErrorResult("Invalid comment type: " + commentTypeStr +
99100
". Must be one of: pre, eol, post, plate, repeatable");
@@ -187,10 +188,10 @@ private void registerGetCommentsTool() throws McpError {
187188
return createErrorResult("Either 'address' or 'addressRange' must be provided");
188189
}
189190

190-
List<Integer> types = new ArrayList<>();
191+
List<CommentType> types = new ArrayList<>();
191192
if (commentTypes != null && !commentTypes.isEmpty()) {
192193
for (String typeStr : commentTypes) {
193-
Integer type = COMMENT_TYPES.get(typeStr.toLowerCase());
194+
CommentType type = COMMENT_TYPES.get(typeStr.toLowerCase());
194195
if (type == null) {
195196
return createErrorResult("Invalid comment type: " + typeStr);
196197
}
@@ -208,7 +209,7 @@ private void registerGetCommentsTool() throws McpError {
208209
CodeUnit codeUnit = codeUnits.next();
209210
Address addr = codeUnit.getAddress();
210211

211-
for (int type : types) {
212+
for (CommentType type : types) {
212213
String comment = codeUnit.getComment(type);
213214
if (comment != null && !comment.isEmpty()) {
214215
Map<String, Object> commentInfo = new HashMap<>();
@@ -254,7 +255,7 @@ private void registerRemoveCommentTool() throws McpError {
254255
Address address = getAddressFromArgs(request, program, "addressOrSymbol");
255256
String commentTypeStr = getString(request, "commentType");
256257

257-
Integer commentType = COMMENT_TYPES.get(commentTypeStr.toLowerCase());
258+
CommentType commentType = COMMENT_TYPES.get(commentTypeStr.toLowerCase());
258259
if (commentType == null) {
259260
return createErrorResult("Invalid comment type: " + commentTypeStr +
260261
". Must be one of: pre, eol, post, plate, repeatable");
@@ -317,10 +318,10 @@ private void registerSearchCommentsTool() throws McpError {
317318
List<String> commentTypes = getOptionalStringList(request.arguments(), "commentTypes", null);
318319
int maxResults = getOptionalInt(request, "maxResults", 100);
319320

320-
List<Integer> types = new ArrayList<>();
321+
List<CommentType> types = new ArrayList<>();
321322
if (commentTypes != null && !commentTypes.isEmpty()) {
322323
for (String typeStr : commentTypes) {
323-
Integer type = COMMENT_TYPES.get(typeStr.toLowerCase());
324+
CommentType type = COMMENT_TYPES.get(typeStr.toLowerCase());
324325
if (type == null) {
325326
return createErrorResult("Invalid comment type: " + typeStr);
326327
}
@@ -334,7 +335,7 @@ private void registerSearchCommentsTool() throws McpError {
334335
List<Map<String, Object>> results = new ArrayList<>();
335336
Listing listing = program.getListing();
336337

337-
for (int type : types) {
338+
for (CommentType type : types) {
338339
if (results.size() >= maxResults) break;
339340

340341
AddressIterator commentAddrs = listing.getCommentAddressIterator(
@@ -376,11 +377,11 @@ private void registerSearchCommentsTool() throws McpError {
376377

377378
/**
378379
* Get the string name for a comment type constant
379-
* @param commentType The comment type constant
380+
* @param commentType The comment type enum
380381
* @return The string name
381382
*/
382-
private String getCommentTypeName(int commentType) {
383-
for (Map.Entry<String, Integer> entry : COMMENT_TYPES.entrySet()) {
383+
private String getCommentTypeName(CommentType commentType) {
384+
for (Map.Entry<String, CommentType> entry : COMMENT_TYPES.entrySet()) {
384385
if (entry.getValue() == commentType) {
385386
return entry.getKey();
386387
}

src/main/java/reva/tools/decompiler/DecompilerToolProvider.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import ghidra.program.model.address.Address;
3838
import ghidra.program.model.address.AddressSetView;
3939
import ghidra.program.model.listing.CodeUnit;
40+
import ghidra.program.model.listing.CommentType;
4041
import ghidra.program.model.listing.CodeUnitIterator;
4142
import ghidra.program.model.listing.Function;
4243
import ghidra.program.model.listing.FunctionIterator;
@@ -1206,17 +1207,17 @@ private List<Map<String, Object>> getCommentsForDecompLine(Program program, List
12061207

12071208
// Get comments at these addresses
12081209
Listing listing = program.getListing();
1209-
Map<Integer, String> commentTypes = Map.of(
1210-
CodeUnit.PRE_COMMENT, "pre",
1211-
CodeUnit.EOL_COMMENT, "eol",
1212-
CodeUnit.POST_COMMENT, "post",
1213-
CodeUnit.PLATE_COMMENT, "plate",
1214-
CodeUnit.REPEATABLE_COMMENT, "repeatable"
1210+
Map<CommentType, String> commentTypes = Map.of(
1211+
CommentType.PRE, "pre",
1212+
CommentType.EOL, "eol",
1213+
CommentType.POST, "post",
1214+
CommentType.PLATE, "plate",
1215+
CommentType.REPEATABLE, "repeatable"
12151216
);
12161217
for (Address addr : lineAddresses) {
12171218
CodeUnit cu = listing.getCodeUnitAt(addr);
12181219
if (cu != null) {
1219-
for (Map.Entry<Integer, String> entry : commentTypes.entrySet()) {
1220+
for (Map.Entry<CommentType, String> entry : commentTypes.entrySet()) {
12201221
addCommentIfExists(comments, cu, entry.getKey(), entry.getValue(), addr);
12211222
}
12221223
}
@@ -1243,19 +1244,19 @@ private List<Map<String, Object>> getAllCommentsInFunction(Program program, Func
12431244
AddressSetView body = function.getBody();
12441245

12451246
CodeUnitIterator codeUnits = listing.getCodeUnits(body, true);
1246-
Map<Integer, String> commentTypes = Map.of(
1247-
CodeUnit.PRE_COMMENT, "pre",
1248-
CodeUnit.EOL_COMMENT, "eol",
1249-
CodeUnit.POST_COMMENT, "post",
1250-
CodeUnit.PLATE_COMMENT, "plate",
1251-
CodeUnit.REPEATABLE_COMMENT, "repeatable"
1247+
Map<CommentType, String> commentTypes = Map.of(
1248+
CommentType.PRE, "pre",
1249+
CommentType.EOL, "eol",
1250+
CommentType.POST, "post",
1251+
CommentType.PLATE, "plate",
1252+
CommentType.REPEATABLE, "repeatable"
12521253
);
12531254
while (codeUnits.hasNext()) {
12541255
CodeUnit cu = codeUnits.next();
12551256
Address addr = cu.getAddress();
12561257

12571258
// Check all comment types
1258-
for (Map.Entry<Integer, String> entry : commentTypes.entrySet()) {
1259+
for (Map.Entry<CommentType, String> entry : commentTypes.entrySet()) {
12591260
addCommentIfExists(comments, cu, entry.getKey(), entry.getValue(), addr);
12601261
}
12611262
}
@@ -1275,7 +1276,7 @@ private List<Map<String, Object>> getAllCommentsInFunction(Program program, Func
12751276
* @param address The address
12761277
*/
12771278
private void addCommentIfExists(List<Map<String, Object>> comments, CodeUnit cu,
1278-
int commentType, String typeString, Address address) {
1279+
CommentType commentType, String typeString, Address address) {
12791280
String comment = cu.getComment(commentType);
12801281
if (comment != null && !comment.isEmpty()) {
12811282
Map<String, Object> commentInfo = new HashMap<>();
@@ -1334,11 +1335,11 @@ private void registerSetDecompilationCommentTool() throws McpError {
13341335
String comment = getString(request, "comment");
13351336

13361337
// Validate comment type
1337-
int commentType;
1338+
CommentType commentType;
13381339
if ("pre".equals(commentTypeStr)) {
1339-
commentType = CodeUnit.PRE_COMMENT;
1340+
commentType = CommentType.PRE;
13401341
} else if ("eol".equals(commentTypeStr)) {
1341-
commentType = CodeUnit.EOL_COMMENT;
1342+
commentType = CommentType.EOL;
13421343
} else {
13431344
return createErrorResult("Invalid comment type: " + commentTypeStr +
13441345
". Must be 'pre' or 'eol' for decompilation comments.");

0 commit comments

Comments
 (0)