NationalSecurityAgency/ghidra · error · PcodeExecutionException

Cannot evaluate unique $U%x:%d

Error message

Cannot evaluate unique $U%x:%d

What it means

Thrown (unchecked PcodeExecutionException) by the default evaluateUnique when a unique-space varnode ($U offset) is evaluated as a leaf. Uniques are p-code temporaries that only have meaning through their defining op; the base implementation deliberately rejects leaf evaluation of them because a unique has no independent value.

Source

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

	 * @param address the address of the variable
	 * @param size the size of the variable in bytes
	 * @return the value
	 */
	protected abstract T evaluateMemory(Address address, int size);

	/**
	 * Evaluate a unique variable
	 * 
	 * <p>
	 * This is only invoked when trying to evaluate a leaf, which should never occur for a unique
	 * variable. Thus, by default, this throws a {@link PcodeExecutionException}.
	 * 
	 * @param offset the offset of the variable
	 * @param size the size of the variable in bytes
	 * @return the value
	 */
	protected T evaluateUnique(long offset, int size) {
		throw new PcodeExecutionException(
			String.format("Cannot evaluate unique $U%x:%d", offset, size));
	}

	/**
	 * Evaluate a variable with an abstract offset
	 * 
	 * <p>
	 * The three parameters {@code space}, {@code offset}, and {@code size} imitate the varnode
	 * triple, except that the offset is abstract. This is typically invoked for a
	 * {@link PcodeOp#LOAD}, i.e., a dereference.
	 * 
	 * @param program the program defining the static context
	 * @param space the address space of the variable
	 * @param offset the offset of the variable
	 * @param size the size of the variable in bytes
	 * @param already a cache of already-evaluated varnodes and their values
	 * @return the value
	 */

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure unique varnodes are always reached via their defining op so the result is cached before leaf evaluation (evaluate defining ops in topological/data-flow order).
  2. Override evaluateUnique in your subclass to return a symbolic/unknown value instead of throwing, if leaf evaluation of uniques is expected in your analysis.
  3. Pre-populate the 'already' cache with modelled values for the uniques you will encounter.

Example fix

// before: default evaluateUnique throws
// (occurs when a $U varnode is reached as a leaf)

// after: override in your evaluator subclass to model uniques symbolically
@Override
protected T evaluateUnique(long offset, int size) {
    return model.newUnique(offset, size); // symbolic value, no throw
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure uniques are reached via their defining op, not as a leaf
PcodeOp def = vn.getDef();
boolean isUniqueLeaf = vn.isUniqueAddress() && (def == null || !cache.containsKey(vn));
if (isUniqueLeaf) {
    // will throw by default; override evaluateUnique or seed the cache first
}

Try / catch

try {
    T val = evaluator.evaluateVarnode(program, vn, cache);
} catch (PcodeExecutionException e) {
    if (e.getMessage().startsWith("Cannot evaluate unique")) { /* model symbolically */ }
    else throw e;
}

Prevention

When it happens

Trigger: The evaluator's cache ('already') lacks an entry for a unique varnode and evaluation reaches it as a leaf instead of through its defining p-code op. This indicates the unique's defining op was not evaluated first, or the varnode was reached out of order.

Common situations: Symbolic/abstract execution that follows data flow but skips the op that defines a temporary; analyzing partial p-code where the defining op for a $U varnode is outside the examined window; a custom evaluator that doesn't seed the cache from defining ops.

Related errors


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