NationalSecurityAgency/ghidra · error · UnwindException

Cannot compute stack address for offset %d.\nFrame error: %s

Error message

Cannot compute stack address for offset %d.\nFrame error: %s

What it means

AnalysisUnwoundFrame.applyBase() computes a stack address from an offset by adding it to the frame's base. When base == null the frame's stack base could not be determined (the analysis recorded an error in info.error()), so applyBase throws UnwindException("Cannot compute stack address for offset %d.\nFrame error: %s") chaining the original analysis error. This propagates during variable/storage evaluation that needs a stack base.

Source

Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AnalysisUnwoundFrame.java:138

	 * proceeds the same as the starting frame.
	 * 
	 * @param monitor a monitor for cancellation
	 * @return the next frame up
	 * @throws CancelledException if the monitor is cancelled
	 * @throws UnwindException if unwinding fails
	 */
	public AnalysisUnwoundFrame<WatchValue> unwindNext(TaskMonitor monitor)
			throws CancelledException {
		if (info == null || info.ofReturn() == null) {
			throw new NoSuchElementException();
		}
		return unwinder.getFrame(coordinates, state, level + 1, null, monitor);
	}

	@Override
	protected Address applyBase(long offset) {
		if (base == null) {
			throw new UnwindException("Cannot compute stack address for offset %d.\nFrame error: %s"
					.formatted(offset, info.error().getMessage()),
				info.error());
		}
		return base.add(offset);
	}

	@Override
	protected SavedRegisterMap computeRegisterMap() {
		return registerMap;
	}

	@Override
	protected Address computeAddressOfReturnAddress() {
		return info.ofReturn(base);
	}

	@Override
	public Address getReturnAddress() {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Inspect the chained cause (info.error()) to fix the underlying analysis problem (e.g. recover SP, provide annotations).
  2. Catch UnwindException around frame/variable evaluation and skip the frame that lacks a base.
  3. Improve symbol/annotation data so the unwinder can compute the base (re-analyze, fix function signatures).
  4. Stop unwinding at the frame where analysis failed rather than descending further.

Example fix

// before
Address sa = frame.applyBase(offset); // throws UnwindException: base==null

// after
try {
    Address sa = frame.applyBase(offset);
} catch (UnwindException e) {
    Msg.warn(this, "Stack base unavailable for frame; skipping: " + e.getCause());
    return null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// No purely local check; base==null stems from failed analysis. Best pre-check:
// confirm analysis produced a base before evaluating variables relative to it.
if (frame.getBase() == null) { // if a getter exists
    // do not call applyBase; skip frame or re-analyze
}

Try / catch

try {
    Address sa = frame.applyBase(offset);
} catch (UnwindException e) {
    // e.getCause() is the original analysis error (info.error())
    // skip this frame or fix the underlying analysis
}

Prevention

When it happens

Trigger: Unwinding a frame whose stack-pointer/base analysis failed (e.g. could not recover SP, missing or unreliable saved registers). Evaluating variables relative to a base that was never computed. Deeper frames past a frame that failed analysis.

Common situations: Stripped or optimized binaries where SP recovery is unreliable. Frames where the unwinder could not find a return address or stack-adjustment info. Corrupt or incomplete decompilation/stack annotations.

Related errors


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