NationalSecurityAgency/ghidra · warning · FunctionComparisonException

Couldn't get remote function {} at {}.

Error message

Couldn't get remote function {} at {}.

What it means

After successfully opening the remote program, BSimSearchResultsProvider.getMatchFunction() computes the match entry point address from the FunctionDescription and looks it up in the remote program's FunctionManager. If getFunctionAt(matchEntryPoint) returns null it throws FunctionComparisonException — the remote program was opened but the expected function at the stored offset doesn't exist.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/results/BSimSearchResultsProvider.java:544

	}

	private Function getMatchFunction(BSimMatchResult resultRow, Set<Program> opened)
			throws FunctionComparisonException {
		// Determine the match function (remote program's function; right side)
		Program matchProgram = getCachedRemoteProgram(resultRow.getExecutableURLString(), opened);
		if (matchProgram == null) {
			throw new FunctionComparisonException(
				"Couldn't open remote program: " + resultRow.getExecutableURLString() + " for " +
					resultRow.getSimilarFunctionName() + ".");
		}
		FunctionDescription matchFunctionDescription = resultRow.getMatchFunctionDescription();
		long matchOffset = matchFunctionDescription.getAddress();
		Address matchEntryPoint =
			matchProgram.getAddressFactory().getDefaultAddressSpace().getAddress(matchOffset);
		FunctionManager matchFunctionManager = matchProgram.getFunctionManager();
		Function matchFunction = matchFunctionManager.getFunctionAt(matchEntryPoint);
		if (matchFunction == null) {
			throw new FunctionComparisonException("Couldn't get remote function " +
				matchFunctionDescription.getFunctionName() + " at " + matchEntryPoint + ".");
		}
		return matchFunction;
	}

	private class BSimMatchesTableActionContext extends DefaultActionContext {

		BSimMatchesTableActionContext() {
			super(BSimSearchResultsProvider.this);
		}

		public int getSelectedRowCount() {
			return matchesTable.getTable().getSelectedRowCount();
		}

	}

	private class ExecutableTableActionContext extends DefaultActionContext {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Re-generate BSim signatures for the remote program and re-ingest so offsets are current.
  2. Verify the remote program version matches the one that was indexed (compare MD5 if available).
  3. Re-analyze the remote program if function boundaries may have changed.
  4. Check for address base/relocation differences between the indexed and live remote program.
Defensive patterns

Strategy: validation

Validate before calling

// After opening the remote program, verify function exists before comparing
FunctionManager rfm = matchProgram.getFunctionManager();
if (rfm.getFunctionAt(matchEntryPoint) == null) {
    // remote program version mismatch — warn and skip
}

Try / catch

try {
    getMatchFunction(resultRow, opened);
} catch (FunctionComparisonException e) {
    if (e.getMessage().startsWith("Couldn't get remote function")) {
        // skip: remote program version differs from indexed version
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling getMatchFunction where the remote Program opened successfully but matchFunctionManager.getFunctionAt(matchEntryPoint) returns null. The address computed from matchFunctionDescription.getAddress() has no function in the remote program.

Common situations: The remote program version differs from what was indexed in BSim (function deleted or moved in a newer version); the remote program was re-analyzed with different function boundaries; the BSim stored offset is stale; address space mismatch between the indexed and current remote program (e.g., different base address); the remote program is a different binary than expected (same name, different content).

Related errors


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