NationalSecurityAgency/ghidra · error · OverlappingFunctionException
Invalid referenced function: circular thunk reference at
Error message
Invalid referenced function: circular thunk reference at
What it means
Thrown by CreateFunctionCmd.resolveThunk when the entry being resolved appears in the referringThunkAddresses list - i.e. the function is a thunk that points back to itself (directly or via a chain being constructed), forming a cycle. CreateThunkFunctionCmd refuses to create such a self-referential thunk, so the command aborts with OverlappingFunctionException.
Source
Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CreateFunctionCmd.java:506
* @param body new function body
* @param monitor task monitor
* @return true if the entry resolved to a thunk
*
* @throws OverlappingFunctionException if thunk thunks itself
*/
private boolean resolveThunk(Address entry, AddressSetView body, TaskMonitor monitor)
throws OverlappingFunctionException {
Address thunkedAddr =
CreateThunkFunctionCmd.getThunkedExternalFunctionAddress(program, entry);
if (thunkedAddr == null) {
thunkedAddr = CreateThunkFunctionCmd.getThunkedAddr(program, entry);
}
if (thunkedAddr == null || thunkedAddr.equals(entry)) {
return false;
}
if (referringThunkAddresses != null && referringThunkAddresses.contains(entry)) {
throw new OverlappingFunctionException(
"Invalid referenced function: circular thunk reference at " + entry);
}
// Handles simple check for single computed jump - may need to add more complex cases
CreateThunkFunctionCmd cmd =
new CreateThunkFunctionCmd(entry, body, thunkedAddr, referringThunkAddresses);
if (cmd.applyTo(program, monitor)) {
this.newFunc = cmd.getThunkFunction();
return true;
}
return false;
}
/**
* using the body map revert any changes made to function bodies
*
* @param bodyChangeMap map of functions to original bodies
*/
private static void restoreOriginalBodies(Map<Function, AddressSetView> bodyChangeMap) {View on GitHub (pinned to d5f144c24d)
Solutions
- Do not mark such an entry as a thunk; create it as a normal function (the 'thunked' address equals the entry, which resolveThunk already skips via thunkedAddr.equals(entry)).
- Break the cycle by removing one of the thunk references before re-running the command.
- If using CreateFunctionCmd(entry, referringThunkAddresses), ensure the entry is not in that list.
- Run auto-analysis 'Thunk' identification with care on obfuscated binaries.
Example fix
// before new CreateFunctionCmd(entry, List.of(entry)).applyTo(program, monitor); // entry is in referringThunkAddresses -> OverlappingFunctionException // after - do not include entry in its own referring-thunk list List<Address> referring = new ArrayList<>(thunkChain); referring.remove(entry); // break self-reference new CreateFunctionCmd(entry, referring).applyTo(program, monitor);
Defensive patterns
Strategy: validation
Validate before calling
if (referringThunkAddresses != null && referringThunkAddresses.contains(entry)) {
// would form a self/circular thunk - do not call resolveThunk/CreateFunctionCmd
} Type guard
boolean isSelfReferentialThunk(Address entry, List<Address> referring) {
return referring != null && referring.contains(entry);
} Try / catch
try {
cmd.applyTo(program, monitor);
} catch (OverlappingFunctionException e) {
if (e.getMessage().contains("circular thunk reference")) {
// remove entry from referringThunkAddresses and retry as a normal function
} else throw e;
} Prevention
- Never include the entry in its own referringThunkAddresses list.
- Break thunk cycles before re-running CreateFunctionCmd.
- Be cautious with thunk auto-analysis on obfuscated binaries.
When it happens
Trigger: Creating a function at an entry whose thunk target resolves back to the same entry, while that entry is already in the referring-thunk chain. Common with self-jumping trampolines, obfuscated dispatchers, or misidentified thunks where the 'thunked' address equals the entry.
Common situations: Obfuscated code with self-referential jumps misclassified as thunks. Manually constructing thunk chains that loop. Re-running CreateFunctionCmd on a half-created thunk graph.
Related errors
- Parameter name conflict, likely due to concurrent operation
- Function name conflict occurred when applying function signa
- Could not resolve filter specifying function: [
- Already inserted
- Could not find function: {entry.funcName}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/1e34af625773c3ef.
Report an issue: GitHub.