feat: add line filtering to decompile for context management
Add start_line, end_line, and max_lines parameters to decompile functions, allowing AI models to retrieve only specific portions of decompiled code for better context management. Parameters: - start_line: Start at this line number (1-indexed) - end_line: End at this line number (inclusive) - max_lines: Maximum lines to return (overrides end_line) Response includes filter metadata with total_lines when filtering is applied, helping models understand what portion they're viewing. Examples: - Get first 20 lines: max_lines=20 - Get lines 10-30: start_line=10, end_line=30 - Get 15 lines from line 25: start_line=25, max_lines=15
This commit is contained in:
parent
60124d2315
commit
662e202482
@ -1351,20 +1351,35 @@ def functions_get(name: str = None, address: str = None, port: int = None) -> di
|
||||
return simplify_response(response)
|
||||
|
||||
@mcp.tool()
|
||||
def functions_decompile(name: str = None, address: str = None,
|
||||
def functions_decompile(name: str = None, address: str = None,
|
||||
syntax_tree: bool = False, style: str = "normalize",
|
||||
start_line: int = None, end_line: int = None, max_lines: int = None,
|
||||
port: int = None) -> dict:
|
||||
"""Get decompiled code for a function
|
||||
|
||||
"""Get decompiled code for a function with optional line filtering for context management
|
||||
|
||||
Args:
|
||||
name: Function name (mutually exclusive with address)
|
||||
address: Function address in hex format (mutually exclusive with name)
|
||||
syntax_tree: Include syntax tree (default: False)
|
||||
style: Decompiler style (default: "normalize")
|
||||
start_line: Start at this line number (1-indexed, optional)
|
||||
end_line: End at this line number (inclusive, optional)
|
||||
max_lines: Maximum number of lines to return (optional, takes precedence over end_line)
|
||||
port: Specific Ghidra instance port (optional)
|
||||
|
||||
|
||||
Returns:
|
||||
dict: Contains function information and decompiled code
|
||||
dict: Contains function information and decompiled code (potentially filtered).
|
||||
If filtering is applied, includes a 'filter' object with total_lines and applied parameters.
|
||||
|
||||
Examples:
|
||||
# Get first 20 lines of decompiled code
|
||||
functions_decompile(name="main", max_lines=20)
|
||||
|
||||
# Get lines 10-30
|
||||
functions_decompile(name="main", start_line=10, end_line=30)
|
||||
|
||||
# Get 15 lines starting from line 25
|
||||
functions_decompile(name="main", start_line=25, max_lines=15)
|
||||
"""
|
||||
if not name and not address:
|
||||
return {
|
||||
@ -1375,22 +1390,30 @@ def functions_decompile(name: str = None, address: str = None,
|
||||
},
|
||||
"timestamp": int(time.time() * 1000)
|
||||
}
|
||||
|
||||
|
||||
port = _get_instance_port(port)
|
||||
|
||||
|
||||
params = {
|
||||
"syntax_tree": str(syntax_tree).lower(),
|
||||
"style": style
|
||||
}
|
||||
|
||||
|
||||
# Add line filtering parameters if provided
|
||||
if start_line is not None:
|
||||
params["start_line"] = str(start_line)
|
||||
if end_line is not None:
|
||||
params["end_line"] = str(end_line)
|
||||
if max_lines is not None:
|
||||
params["max_lines"] = str(max_lines)
|
||||
|
||||
if address:
|
||||
endpoint = f"functions/{address}/decompile"
|
||||
else:
|
||||
endpoint = f"functions/by-name/{quote(name)}/decompile"
|
||||
|
||||
|
||||
response = safe_get(port, endpoint, params)
|
||||
simplified = simplify_response(response)
|
||||
|
||||
|
||||
return simplified
|
||||
|
||||
@mcp.tool()
|
||||
|
||||
@ -1090,20 +1090,67 @@ public class FunctionEndpoints extends AbstractEndpoint {
|
||||
String style = params.getOrDefault("style", "normalize");
|
||||
String format = params.getOrDefault("format", "structured");
|
||||
int timeout = parseIntOrDefault(params.get("timeout"), 30);
|
||||
|
||||
|
||||
// Line filtering parameters for context management
|
||||
int startLine = parseIntOrDefault(params.get("start_line"), -1);
|
||||
int endLine = parseIntOrDefault(params.get("end_line"), -1);
|
||||
int maxLines = parseIntOrDefault(params.get("max_lines"), -1);
|
||||
|
||||
// Decompile function
|
||||
String decompilation = GhidraUtil.decompileFunction(function);
|
||||
|
||||
|
||||
// Apply line filtering if requested
|
||||
String filteredDecompilation = decompilation;
|
||||
int totalLines = 0;
|
||||
if (decompilation != null) {
|
||||
String[] lines = decompilation.split("\n");
|
||||
totalLines = lines.length;
|
||||
|
||||
// Apply line range filtering
|
||||
if (startLine > 0 || endLine > 0 || maxLines > 0) {
|
||||
int start = startLine > 0 ? Math.max(0, startLine - 1) : 0;
|
||||
int end = endLine > 0 ? Math.min(lines.length, endLine) : lines.length;
|
||||
|
||||
// If maxLines is specified, limit the range
|
||||
if (maxLines > 0) {
|
||||
end = Math.min(end, start + maxLines);
|
||||
}
|
||||
|
||||
if (start < lines.length) {
|
||||
StringBuilder filtered = new StringBuilder();
|
||||
for (int i = start; i < end && i < lines.length; i++) {
|
||||
if (i > start) {
|
||||
filtered.append("\n");
|
||||
}
|
||||
filtered.append(lines[i]);
|
||||
}
|
||||
filteredDecompilation = filtered.toString();
|
||||
} else {
|
||||
filteredDecompilation = "// No lines in specified range";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create function info
|
||||
Map<String, Object> functionInfo = new HashMap<>();
|
||||
functionInfo.put("address", function.getEntryPoint().toString());
|
||||
functionInfo.put("name", function.getName());
|
||||
|
||||
|
||||
// Create the result structure according to GHIDRA_HTTP_API.md
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("function", functionInfo);
|
||||
result.put("decompiled", decompilation != null ? decompilation : "// Decompilation failed");
|
||||
|
||||
result.put("decompiled", filteredDecompilation != null ? filteredDecompilation : "// Decompilation failed");
|
||||
|
||||
// Add metadata about line filtering if applied
|
||||
if (startLine > 0 || endLine > 0 || maxLines > 0) {
|
||||
Map<String, Object> filterInfo = new HashMap<>();
|
||||
filterInfo.put("total_lines", totalLines);
|
||||
if (startLine > 0) filterInfo.put("start_line", startLine);
|
||||
if (endLine > 0) filterInfo.put("end_line", endLine);
|
||||
if (maxLines > 0) filterInfo.put("max_lines", maxLines);
|
||||
result.put("filter", filterInfo);
|
||||
}
|
||||
|
||||
// Add syntax tree if requested
|
||||
if (syntaxTree) {
|
||||
result.put("syntax_tree", "Syntax tree not implemented");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user