NationalSecurityAgency/ghidra · error · PcodeExecutionException

No defining p-code op for {}

Error message

No defining p-code op for {}

What it means

Thrown (unchecked PcodeExecutionException) by evaluateBranch when a varnode's defining p-code op is null (def == null) or when the op's output is not the varnode itself (def.getOutput() != vn). evaluateBranch assumes the varnode is the result of a p-code op; an undefined or already-consumed varnode violates that.

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/eval/AbstractVarnodeEvaluator.java:218

		for (Varnode vn : storage.getVarnodes()) {
			T piece = evaluateVarnode(program, vn);
			value = catenate(total, value, piece, vn.getSize());
		}
		return value;
	}

	/**
	 * Evaluate the given varnode's defining p-code op
	 * 
	 * @param program the program defining the static context
	 * @param vn the varnode
	 * @param already a cache of already-evaluated varnodes and their values
	 * @return the value
	 */
	protected T evaluateBranch(Program program, Varnode vn, Map<Varnode, T> already) {
		PcodeOp def = vn.getDef();
		if (def == null || def.getOutput() != vn) {
			throw new PcodeExecutionException("No defining p-code op for " + vn);
		}
		return evaluateOp(program, def, already);
	}

	/**
	 * Evaluate a constant
	 * 
	 * @param value the constant value
	 * @param size the size of the value in bytes
	 * @return the value
	 */
	protected abstract T evaluateConstant(long value, int size);

	/**
	 * Evaluate the given register variable
	 * 
	 * @param address the address of the register
	 * @param size the size of the variable in bytes

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Route input/leaf varnodes through evaluateLeaf/evaluateVarnode (which checks the cache and handles constants) rather than evaluateBranch.
  2. Ensure the defining op is evaluated first so the varnode is cached before you need its value.
  3. Guard with vn.getDef() != null && vn.getDef().getOutput() == vn before calling evaluateBranch.
  4. If the varnode is genuinely undefined, treat it as an unknown symbol rather than throwing.

Example fix

// before
T val = evaluator.evaluateBranch(program, vn, cache); // throws if vn is an input

// after: only use evaluateBranch when vn is genuinely an op output
PcodeOp def = vn.getDef();
T val = (def != null && def.getOutput() == vn)
    ? evaluator.evaluateBranch(program, vn, cache)
    : evaluator.evaluateVarnode(program, vn, cache);
Defensive patterns

Strategy: validation

Validate before calling

// Only evaluate via branch when vn is genuinely an op output
PcodeOp def = vn.getDef();
if (def == null || def.getOutput() != vn) {
    // not an op output: use leaf evaluation instead
}

Try / catch

try {
    T val = evaluator.evaluateBranch(program, vn, cache);
} catch (PcodeExecutionException e) {
    if (e.getMessage().startsWith("No defining p-code op")) { /* evaluate as leaf instead */ }
    else throw e;
}

Prevention

When it happens

Trigger: Evaluating a varnode that is an instruction input/operand rather than an op output (def is null because it's a leaf/input), or a varnode whose defining op was rewritten so its output no longer matches. Also when the 'already' cache doesn't contain a leaf varnode and evaluation falls through to branch mode.

Common situations: Walking p-code and trying to evaluate a register/constant input varnode through evaluateBranch instead of treating it as a leaf; analyzing p-code after the op graph was mutated/cleared; a varnode reached before its defining op was evaluated.

Related errors


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