NationalSecurityAgency/ghidra · error · IOException
gdis execution error
Error message
gdis execution error
What it means
Thrown when the GNU external disassembler (gdis) process encounters an IOException while writing the disassembly request to the process's stdin or while reading back the result. The error wraps the underlying IOException. The code logs the last request that failed and then re-throws, forcing the caller to handle the broken pipe / I/O failure. A TODO comment notes the process is intentionally not destroyed to avoid repeated failures, so subsequent calls may also fail until the process recovers or the config is reloaded.
Source
Thrown at Ghidra/Extensions/SleighDevTools/src/main/java/ghidra/app/util/disassemble/GNUExternalDisassembler.java:639
disassemblyRequest += '\n';
}
else {
disassemblyRequest += OPTIONS_SEPARATOR + disassemblerOptions + SEPARATOR_CHARACTER;
}
try {
outputWriter.write(disassemblyRequest);
outputWriter.flush();
return getDisassembledInstruction();
}
catch (IOException e) {
// force a restart of the disassembler on next call to this function
// TODO: Should we not do this to avoid repeated failure and severe slowdown?
// User must exit or switch configs/programs to retry after failure
//disassemblerProcess.destroy();
//disassemblerProcess = null; // assumes process exit
Msg.error(this, "Last gdis request failed: " + disassemblyRequest);
throw new IOException("gdis execution error", e);
}
}
private List<GnuDisassembledInstruction> getDisassembledInstruction() throws IOException {
List<GnuDisassembledInstruction> results = new ArrayList<>();
String instructionLine;
boolean error = false;
do {
instructionLine = buffReader.readLine();
if (!error && instructionLine != null && !instructionLine.equals(ENDING_STRING) &&
(instructionLine.indexOf(ADDRESS_OUT_OF_BOUNDS) < 0) &&
!instructionLine.startsWith("Usage:") && !instructionLine.startsWith("Debug:")) {
String instructionMetadataLine = buffReader.readLine();
if (!instructionMetadataLine.startsWith("Info: ")) {
// TODO, throw an "ExternalDisassemblerInterfaceException"View on GitHub (pinned to d5f144c24d)
Solutions
- Check the application log for the preceding 'Last gdis request failed' message — it shows the exact request that broke the pipe.
- Verify the gdis executable path and version configured for this language match a working binary (run it manually with the same input).
- Restart the Ghidra session or switch/reload the disassembler configuration to force a fresh gdis process spawn.
- If the crash is reproducible, isolate the specific instruction bytes in the request and test them against gdis directly to find the offending input.
- Check system resources (memory, file descriptors) — native child processes may be killed by the OS under pressure.
Defensive patterns
Strategy: retry
Validate before calling
// Before sending a request, verify the process is alive
if (disassemblerProcess == null || !disassemblerProcess.isAlive()) {
// restart the gdis process
startDisassembler();
} Try / catch
try {
return disassemble(...);
} catch (IOException e) {
if ("gdis execution error".equals(e.getMessage())) {
// reset process state and retry once
resetDisassemblerProcess();
return disassemble(...);
}
throw e;
} Prevention
- Monitor the gdis process health (isAlive) before each disassembly request.
- Log the failing request bytes so crashes are reproducible.
- Keep the gdis binary version matched to the expected protocol.
- Watch system memory — native child processes are OOM-kill candidates.
When it happens
Trigger: Calling the disassembly method that writes disassemblyRequest to outputWriter and calls getDisassembledInstruction(); any IOException during outputWriter.write/flush or during the subsequent read triggers this. Commonly a broken pipe because the gdis process crashed between requests.
Common situations: The gdis binary crashed or was killed (OOM, segfault); the pipe between JVM and the native gdis process broke; the gdis executable is mismatched with the expected protocol version; the host system is under memory pressure causing the child process to die; a corrupt or unexpectedly long instruction stream causes gdis to error out and close its stdout.
Related errors
- GNU disassembler process died unexpectedly.
- Unable to read {} bytes
- GhidraRandomAccessFile is closed
- Usage: %s target-str, arch, mach, disassembly base-addr (for
- exiting, no ASCII hex found\n
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/c71087941b8c01d6.
Report an issue: GitHub.