{"record":{"id":"87aee436221acb60","repo":"NationalSecurityAgency/ghidra","slug":"issue-executing-callee-fixup","errorCode":null,"errorMessage":"Issue executing callee fixup: ","messagePattern":"Issue executing callee fixup: ","errorType":"exception","errorClass":"PcodeExecutionException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java","lineNumber":161,"sourceCode":"\t}\n\n\t@Override\n\tpublic void executeCall(PcodeOp op, PcodeFrame frame, PcodeUseropLibrary<Sym> library) {\n\t\tAddress target = op.getInput(0).getAddress();\n\t\tFunction callee = program.getFunctionManager().getFunctionAt(target);\n\t\tif (callee == null) {\n\t\t\tthrow new PcodeExecutionException(\"Callee at \" + target + \" is not a function.\", frame);\n\t\t}\n\t\tString fixupName = callee.getCallFixup();\n\t\tif (fixupName != null && !\"\".equals(fixupName)) {\n\t\t\tPcodeProgram snippet;\n\t\t\ttry {\n\t\t\t\tsnippet = PcodeProgram.fromInject(program, fixupName, InjectPayload.CALLFIXUP_TYPE);\n\t\t\t\texecute(snippet, library);\n\t\t\t}\n\t\t\tcatch (MemoryAccessException | UnknownInstructionException | NotFoundException\n\t\t\t\t\t| IOException e) {\n\t\t\t\tthrow new PcodeExecutionException(\"Issue executing callee fixup: \", e);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tint change = computeStackChange(callee);\n\t\tadjustStack(change);\n\t}\n\n\t/**\n\t * Decompile the given low p-code op to its high p-code op\n\t * \n\t * <p>\n\t * Note this is not decompilation of the op in isolation. Decompilation usually requires a\n\t * complete function for context. This will decompile the full containing function then examine\n\t * the resulting high p-code ops at the same address as the given op, which are presumably those\n\t * derived from it. It then seeks a unique call (or call indirect) op.\n\t * \n\t * @param op the low p-code op\n\t * @return the high p-code op","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java#L143-L179","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// The exception wraps its cause; inspect it:\n// catch (PcodeExecutionException e) {\n//     Throwable cause = e.getCause();\n//     if (cause instanceof NotFoundException) {\n//         // fixup name not registered — check .pspec injection definitions\n//     }\n// }","handlingStrategy":"try-catch","validationCode":"// Before executing a call fixup, verify the injection exists:\nString fixupName = callee.getCallFixup();\nif (fixupName != null && !fixupName.isEmpty()) {\n    // check if injection is registered — use InjectPayload checks\n    // if not registered, skip fixup or log warning\n}","typeGuard":"// No compile-time type guard; injection availability is runtime-discovered.\n// Use PcodeProgram.fromInject in a try block.","tryCatchPattern":"try {\n    executor.executeCall(op, frame, library);\n} catch (PcodeExecutionException e) {\n    if (e.getMessage().startsWith(\"Issue executing callee fixup\")) {\n        Throwable cause = e.getCause();\n        // log cause type, optionally continue without fixup\n    } else { throw e; }\n}","preventionTips":["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."],"tags":["pcode","emulation","call-fixup","injection"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}