NationalSecurityAgency/ghidra · error · IllegalArgumentException

Mapping destination cannot be a TraceProgramView

Error message

Mapping destination cannot be a TraceProgramView

What it means

DebuggerStaticMappingUtils.addMapping() maps a trace location to a static program location. The destination must be a real imported Program, not a TraceProgramView (which is a view of a trace presented as a Program). Mappings must go trace -> static program; mapping trace -> trace (via its TraceProgramView) is explicitly rejected to avoid self/cross-trace mapping confusion.

Source

Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java:113

	/**
	 * Add a static mapping (relocation) from the given trace to the given program
	 * 
	 * <p>
	 * Note if the trace is backed by a Ghidra database, the caller must already have started a
	 * transaction on the relevant domain object.
	 * 
	 * @param from the source trace location, including lifespan
	 * @param to the destination program location
	 * @param length the length of the mapped region
	 * @param truncateExisting true to delete or truncate the lifespan of overlapping entries
	 * @throws TraceConflictedMappingException if a conflicting mapping overlaps the source and
	 *             {@code truncateExisting} is false.
	 */
	public static void addMapping(TraceLocation from, ProgramLocation to, long length,
			boolean truncateExisting) throws TraceConflictedMappingException {
		Program tp = to.getProgram();
		if (tp instanceof TraceProgramView) {
			throw new IllegalArgumentException(
				"Mapping destination cannot be a " + TraceProgramView.class.getSimpleName());
		}
		TraceStaticMappingManager manager = from.getTrace().getStaticMappingManager();
		URL toURL = ProgramURLUtils.getUrlFromProgram(tp);
		if (toURL == null) {
			noProject(DebuggerStaticMappingUtils.class);
		}
		Address fromAddress = from.getAddress();
		Address toAddress = to.getByteAddress();
		long maxFromLengthMinus1 =
			fromAddress.getAddressSpace().getMaxAddress().subtract(fromAddress);
		long maxToLengthMinus1 =
			toAddress.getAddressSpace().getMaxAddress().subtract(toAddress);
		if (Long.compareUnsigned(length - 1, maxFromLengthMinus1) > 0) {
			throw new IllegalArgumentException("Length would cause address overflow in trace");
		}
		if (Long.compareUnsigned(length - 1, maxToLengthMinus1) > 0) {
			throw new IllegalArgumentException("Length would cause address overflow in program");

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Use a genuine imported static Program (from the project, not a trace view) as the mapping destination.
  2. Obtain the destination program via the project domain-object API rather than trace.getProgramView().
  3. Type-check the destination: if (to.getProgram() instanceof TraceProgramView) reject early and fetch the real program.

Example fix

// before
ProgramLocation dest = new ProgramLocation(trace.getProgramView(), addr);
DebuggerStaticMappingUtils.addMapping(from, dest, len, false); // throws

// after
Program importedStatic = (Program) projectData.getDomainFolder("/").getFile("prog").getImmutableObject();
ProgramLocation dest = new ProgramLocation(importedStatic, addr);
DebuggerStaticMappingUtils.addMapping(from, dest, len, false);
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject trace-view destinations before addMapping
Program dest = to.getProgram();
if (dest instanceof TraceProgramView) {
    throw new IllegalArgumentException("Use a real imported Program, not a TraceProgramView");
}

Type guard

public static boolean isRealStaticProgram(Program p) {
    return p != null && !(p instanceof TraceProgramView);
}

Try / catch

try {
    DebuggerStaticMappingUtils.addMapping(from, to, length, false);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("TraceProgramView")) {
        // fetch the imported static Program and retry
    } else throw e;
}

Prevention

When it happens

Trigger: Passing a ProgramLocation whose getProgram() returns a TraceProgramView (i.e. the "static" side is actually another trace's view) into addMapping. Programs obtained from a Trace's program view rather than from an imported domain object.

Common situations: Scripts that grab a program reference from a trace view and try to map to it. UI actions that have a trace open as a static program and attempt to create a mapping destination from it. Confusing the trace's TraceProgramView with a real static Program.

Related errors


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