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.

Solutions

  1. Inspect the wrapped exception (the 'e' cause) to identify which of the four exception types was thrown.
  2. If NotFoundException: verify the fixup name exists in the program's injection table (check .pspec/.cspec files).
  3. If MemoryAccessException: ensure the emulated memory state covers addresses the fixup accesses.
  4. Disable or override the call-fixup for the problematic function if emulation doesn't need it.
  5. 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

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


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/87aee436221acb60. Report an issue: GitHub.

Appendix: 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 op

View on GitHub (pinned to d5f144c24d)