diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e67229..8a81ddf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
+## [Unreleased]
+
+### Added
+- Added decompiler output controls to customize analysis results:
+ - Choose between clean C-like pseudocode (default) or raw decompiler output
+ - Toggle syntax tree visibility for detailed analysis
+ - Select different simplification styles for alternate views
+ - Useful for comparing different decompilation approaches or focusing on specific aspects of the code
+
+ Example showing how to get raw decompiler output with syntax tree:
+ ```xml
+
+ ghydra
+ decompile_function_by_address
+
+ {
+ "address": "0x1000",
+ "cCode": false,
+ "syntaxTree": true
+ }
+
+
+ ```
+
## [1.4.0] - 2025-04-08
### Added
diff --git a/bridge_mcp_hydra.py b/bridge_mcp_hydra.py
index a64fafe..89570fa 100644
--- a/bridge_mcp_hydra.py
+++ b/bridge_mcp_hydra.py
@@ -333,9 +333,24 @@ def list_classes(port: int = DEFAULT_GHIDRA_PORT, offset: int = 0, limit: int =
return safe_get(port, "classes", {"offset": offset, "limit": limit})
@mcp.tool()
-def get_function(port: int = DEFAULT_GHIDRA_PORT, name: str = "") -> dict:
- """Get decompiled code for a specific function"""
- response = safe_get(port, f"functions/{quote(name)}", {})
+def get_function(port: int = DEFAULT_GHIDRA_PORT, name: str = "", cCode: bool = True, syntaxTree: bool = False, simplificationStyle: str = "normalize") -> dict:
+ """Get decompiled code for a specific function
+
+ Args:
+ port: Ghidra instance port (default: 8192)
+ name: Name of the function to decompile
+ cCode: Whether to output C code (default: True)
+ syntaxTree: Whether to include syntax tree (default: False)
+ simplificationStyle: Decompiler analysis style (default: "normalize")
+
+ Returns:
+ Dict containing function details including decompiled code
+ """
+ response = safe_get(port, f"functions/{quote(name)}", {
+ "cCode": str(cCode).lower(),
+ "syntaxTree": str(syntaxTree).lower(),
+ "simplificationStyle": simplificationStyle
+ })
# Check if the response is a string (old format) or already a dict with proper structure
if isinstance(response, dict) and "success" in response:
@@ -524,17 +539,25 @@ def get_current_function(port: int = DEFAULT_GHIDRA_PORT) -> dict: # Return dict
return safe_get(port, "get_current_function")
@mcp.tool()
-def decompile_function_by_address(port: int = DEFAULT_GHIDRA_PORT, address: str = "") -> dict:
+def decompile_function_by_address(port: int = DEFAULT_GHIDRA_PORT, address: str = "", cCode: bool = True, syntaxTree: bool = False, simplificationStyle: str = "normalize") -> dict:
"""Decompile a function at a specific memory address
Args:
port: Ghidra instance port (default: 8192)
address: Memory address of the function (hex string)
+ cCode: Whether to output C code (default: True)
+ syntaxTree: Whether to include syntax tree (default: False)
+ simplificationStyle: Decompiler analysis style (default: "normalize")
Returns:
Dict containing the decompiled pseudocode in the 'result.decompilation' field
"""
- response = safe_get(port, "decompile_function", {"address": address})
+ response = safe_get(port, "decompile_function", {
+ "address": address,
+ "cCode": str(cCode).lower(),
+ "syntaxTree": str(syntaxTree).lower(),
+ "simplificationStyle": simplificationStyle
+ })
# Check if the response is a string (old format) or already a dict with proper structure
if isinstance(response, dict) and "success" in response:
diff --git a/src/main/java/eu/starsong/ghidra/GhydraMCPPlugin.java b/src/main/java/eu/starsong/ghidra/GhydraMCPPlugin.java
index 54c6e16..b783a40 100644
--- a/src/main/java/eu/starsong/ghidra/GhydraMCPPlugin.java
+++ b/src/main/java/eu/starsong/ghidra/GhydraMCPPlugin.java
@@ -438,6 +438,9 @@ public class GhydraMCPPlugin extends Plugin implements ApplicationLevelPlugin {
if ("GET".equals(exchange.getRequestMethod())) {
Map qparams = parseQueryParams(exchange);
String address = qparams.get("address");
+ boolean cCode = Boolean.parseBoolean(qparams.getOrDefault("cCode", "true"));
+ boolean syntaxTree = Boolean.parseBoolean(qparams.getOrDefault("syntaxTree", "false"));
+ String simplificationStyle = qparams.getOrDefault("simplificationStyle", "normalize");
if (address == null || address.isEmpty()) {
sendErrorResponse(exchange, 400, "Address parameter is required");
@@ -472,6 +475,11 @@ public class GhydraMCPPlugin extends Plugin implements ApplicationLevelPlugin {
DecompInterface decomp = new DecompInterface();
try {
+ // Set decompilation options from parameters
+ decomp.toggleCCode(cCode);
+ decomp.setSimplificationStyle(simplificationStyle);
+ decomp.toggleSyntaxTree(syntaxTree);
+
if (!decomp.openProgram(program)) {
sendErrorResponse(exchange, 500, "Failed to initialize decompiler");
return;
@@ -1105,6 +1113,11 @@ public class GhydraMCPPlugin extends Plugin implements ApplicationLevelPlugin {
DecompInterface decomp = new DecompInterface();
try {
+ // Default to C code output and no syntax tree for better readability
+ decomp.toggleCCode(true);
+ decomp.setSimplificationStyle("normalize");
+ decomp.toggleSyntaxTree(false);
+
if (!decomp.openProgram(program)) {
resultObj.addProperty("decompilation_error", "Failed to initialize decompiler");
} else {