NationalSecurityAgency/ghidra · error · IllegalArgumentException

Processor context register not allowed

Error message

Processor context register not allowed

What it means

Thrown as IllegalArgumentException from the RegisterMergeManager constructor when the requested register is the processor context register (Register.isProcessorContext() == true). RegisterMergeManager merges a single named register's values across program versions and explicitly excludes the special processor-context register because it is handled by a different merge path.

Source

Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/RegisterMergeManager.java:134

		this.registerName = registerName;
		this.mergeManager = mergeManager;
		this.resultPgm = resultPgm;
		this.originalPgm = originalPgm;
		this.latestPgm = latestPgm;
		this.myPgm = myPgm;
		this.latestChanges = latestChanges;
		this.myChanges = myChanges;
		this.latestSet = latestChanges.getRegisterAddressSet();
		this.mySet = myChanges.getRegisterAddressSet();

		originalContext = originalPgm.getProgramContext();
		latestContext = latestPgm.getProgramContext();
		myContext = myPgm.getProgramContext();
		resultContext = resultPgm.getProgramContext();

		resultReg = resultContext.getRegister(registerName);
		if (resultReg.isProcessorContext()) {
			throw new IllegalArgumentException("Processor context register not allowed");
		}
	}

	void apply() {
		conflictOption = conflictPanel.getSelectedOptions();

		// If the "Use For All" check box is selected 
		// then save the option chosen for this conflict type.
		if (conflictPanel.getUseForAll()) {
			contextChoice = conflictOption;
		}

		merge(min, max, resultReg);
	}

	void cancel() {
		conflictOption = CANCELED;
	}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Skip registers where register.isProcessorContext() is true before constructing RegisterMergeManager.
  2. Filter the register list against the processor-context register when driving a multi-register merge loop.
  3. If you genuinely need context-register merging, use the dedicated context-merge path rather than this constructor.

Example fix

// before
for (String name : allRegisterNames) {
    new RegisterMergeManager(name, mm, result, orig, latest, my, lc, mc); // throws on context reg
}

// after — skip the processor context register
for (String name : allRegisterNames) {
    Register r = resultPgm.getProgramContext().getRegister(name);
    if (r != null && r.isProcessorContext()) {
        continue;
    }
    new RegisterMergeManager(name, mm, result, orig, latest, my, lc, mc);
}
Defensive patterns

Strategy: validation

Validate before calling

Register r = resultPgm.getProgramContext().getRegister(registerName);
if (r != null && r.isProcessorContext()) {
    // skip — not allowed for RegisterMergeManager
    return;
}

Type guard

boolean mergeable = resultReg != null && !resultReg.isProcessorContext();

Try / catch

try {
    new RegisterMergeManager(name, mm, result, orig, latest, my, lc, mc);
} catch (IllegalArgumentException e) {
    // skip processor-context register
}

Prevention

When it happens

Trigger: Constructing `new RegisterMergeManager(registerName, ...)` where registerName resolves to the processor context register (commonly "psr", "CONTEXT", or the register whose isProcessorContext() is true for the loaded language).

Common situations: Iterating all registers of a language to create a merge manager per register and forgetting to skip the processor-context register; passing a register name obtained from ProgramContext that includes the context register.

Related errors


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