NationalSecurityAgency/ghidra · error · PcodeExecutionException
Issue executing callee fixup:
Error message
Issue executing callee fixup:
What it means
Thrown when executing a callee's call-fixup p-code injection snippet fails with one of four exceptions: MemoryAccessException, UnknownInstructionException, NotFoundException, or IOException. The callee function has a named call-fixup (via getCallFixup()), and SymPcodeExecutor loads and executes the injection, but the snippet itself errors during symbolic execution. The original exception is wrapped as the cause.
Source
Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java:161
}
@Override
public void executeCall(PcodeOp op, PcodeFrame frame, PcodeUseropLibrary<Sym> library) {
Address target = op.getInput(0).getAddress();
Function callee = program.getFunctionManager().getFunctionAt(target);
if (callee == null) {
throw new PcodeExecutionException("Callee at " + target + " is not a function.", frame);
}
String fixupName = callee.getCallFixup();
if (fixupName != null && !"".equals(fixupName)) {
PcodeProgram snippet;
try {
snippet = PcodeProgram.fromInject(program, fixupName, InjectPayload.CALLFIXUP_TYPE);
execute(snippet, library);
}
catch (MemoryAccessException | UnknownInstructionException | NotFoundException
| IOException e) {
throw new PcodeExecutionException("Issue executing callee fixup: ", e);
}
return;
}
int change = computeStackChange(callee);
adjustStack(change);
}
/**
* Decompile the given low p-code op to its high p-code op
*
* <p>
* Note this is not decompilation of the op in isolation. Decompilation usually requires a
* complete function for context. This will decompile the full containing function then examine
* the resulting high p-code ops at the same address as the given op, which are presumably those
* derived from it. It then seeks a unique call (or call indirect) op.
*
* @param op the low p-code op
* @return the high p-code opView on GitHub (pinned to d5f144c24d)
Solutions
- Inspect the wrapped exception (the 'e' cause) to identify which of the four exception types was thrown.
- If NotFoundException: verify the fixup name exists in the program's injection table (check .pspec/.cspec files).
- If MemoryAccessException: ensure the emulated memory state covers addresses the fixup accesses.
- Disable or override the call-fixup for the problematic function if emulation doesn't need it.
- Update processor specification files to match the Ghidra version being used.
Example fix
// The exception wraps its cause; inspect it:
// catch (PcodeExecutionException e) {
// Throwable cause = e.getCause();
// if (cause instanceof NotFoundException) {
// // fixup name not registered — check .pspec injection definitions
// }
// } Defensive patterns
Strategy: try-catch
Validate before calling
// Before executing a call fixup, verify the injection exists:
String fixupName = callee.getCallFixup();
if (fixupName != null && !fixupName.isEmpty()) {
// check if injection is registered — use InjectPayload checks
// if not registered, skip fixup or log warning
} Type guard
// No compile-time type guard; injection availability is runtime-discovered. // Use PcodeProgram.fromInject in a try block.
Try / catch
try {
executor.executeCall(op, frame, library);
} catch (PcodeExecutionException e) {
if (e.getMessage().startsWith("Issue executing callee fixup")) {
Throwable cause = e.getCause();
// log cause type, optionally continue without fixup
} else { throw e; }
} Prevention
- Ensure .pspec and .cspec files define all referenced call-fixups for the target architecture.
- Keep the emulated memory state complete enough for fixup snippets to execute.
- Update processor specification files when upgrading Ghidra versions.
- Test call-fixups in isolation before full emulation runs.
When it happens
Trigger: SymPcodeExecutor.executeCall() finds callee.getCallFixup() returns a non-empty string, loads PcodeProgram.fromInject(program, fixupName, InjectPayload.CALLFIXUP_TYPE), and calls execute(snippet, library) which throws. Happens when the call-fixup injection references memory not present in the emulated state, uses an unknown p-code instruction, the fixup name isn't registered in the program's injection table, or an I/O error occurs loading the injection.
Common situations: A compiler/platform-specific call-fixup (e.g., for Windows SEH, stack cookie checks) references symbols or memory that aren't available during emulation. The fixup p-code was written for a different processor model. The program's .cspec or .pspec injection definitions are malformed or missing. Ghidra version change introduced a different injection format.
Related errors
- Timed out reading or writing target
- Error reading or writing target
- Callee at {target} is not a function.
- Cannot get stack change for indirect call: {op}
- Unrecognized address space in {}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/87aee436221acb60.
Report an issue: GitHub.