fix(xrefs): guide symbol lookup recovery (#8753)

* fix(xrefs): guide ambiguous name selection

* fix(xrefs): guide missing symbol lookup

* fix(xrefs): name available symbol recovery paths

* fix(xrefs): qualify exported address coordinates

* fix(xrefs): point to procedure address lookup

* fix(xrefs): keep CLI recovery focused

* test(xrefs): cover CLI ambiguity recovery
This commit is contained in:
morluto authored and GitHub committed 2026-11-05 01:43:45 +08:00
1 parent 9a79ee8e9e
commit eac28b2047
3 files changed
+41 -11

No files matched your search

+26 -10
View File
@@ -21,13 +21,21 @@ export const resolveXrefsAddress = async (
return named.value !== null
? ok(named.value)
: err(
new AnalysisInputError("xrefs", undefined, [
new AnalysisInputError(
"xrefs",
{
path: ["address"],
reason: "invalid_value",
message: `Unknown analyzed symbol name ${JSON.stringify(selector)}. Use an exact analyzed name or a hexadecimal address.`,
conformsToInputContract: true,
remediationAction:
"For a function, use rea search --kind procedures to find an analyzed address. For exports, inspect-macho (Mach-O) or inspect-native-exports (PE/ELF) may help; exports can omit local symbols and use different address coordinates. Verify the address in the selected provider, then retry xrefs.",
},
]),
[
{
path: ["address"],
reason: "invalid_value",
message: `Unknown analyzed symbol name ${JSON.stringify(selector)}. Use an exact analyzed name or a hexadecimal address.`,
},
],
),
);
};
@@ -90,12 +98,20 @@ export const resolveXrefsName = async (
const [address] = addresses;
if (addresses.size <= 1) return ok(address ?? null);
return err(
new AnalysisInputError(operation, undefined, [
new AnalysisInputError(
operation,
{
path: [operation === "xrefs" ? "address" : "name"],
reason: "invalid_value",
message: `Analyzed symbol name ${JSON.stringify(selector)} is ambiguous at ${[...addresses].sort().join(", ")}. Select an exact address.`,
conformsToInputContract: true,
remediationAction:
"Select an exact address from the candidates and call xrefs with that address.",
},
]),
[
{
path: [operation === "xrefs" ? "address" : "name"],
reason: "invalid_value",
message: `Analyzed symbol name ${JSON.stringify(selector)} is ambiguous at ${[...addresses].sort().join(", ")}. Select an exact address.`,
},
],
),
);
};
@@ -101,6 +101,9 @@ it("exact-name xrefs preserves ambiguity independently of inventory order and ac
});
expect(parseMcpToolError(rejected).error).toMatchObject({
code: "invalid_request",
remediation: {
action: expect.stringContaining("Select an exact address"),
},
details: {
issues: [
expect.objectContaining({
@@ -110,6 +113,7 @@ it("exact-name xrefs preserves ambiguity independently of inventory order and ac
],
},
});
expect(parseMcpToolError(rejected).error.recovery).toBeUndefined();
}
expect(queried).toEqual([]);
rows = [
+11 -1
View File
@@ -211,8 +211,12 @@ describe("direct CLI cross-reference name resolution", () => {
).then(projectCliAnalysisResult);
expect(missing).toMatchObject({
code: "invalid_request",
remediation: {
action: expect.stringContaining("use different address coordinates"),
},
details: { operation: "xrefs", issues: [{ path: ["address"] }] },
});
expect(missing).not.toHaveProperty("recovery");
expect(JSON.stringify(missing)).toContain("missing_symbol");
expect(provider.closed()).toBe(2);
});
@@ -228,7 +232,13 @@ describe("direct CLI cross-reference name resolution", () => {
address: "ambiguous",
},
).then(projectCliAnalysisResult);
expect(result).toMatchObject({ code: "invalid_request" });
expect(result).toMatchObject({
code: "invalid_request",
remediation: {
action: expect.stringContaining("Select an exact address"),
},
});
expect(result).not.toHaveProperty("recovery");
expect(JSON.stringify(result)).toContain("0x1000");
expect(JSON.stringify(result)).toContain("0x2000");
expect(provider.closed()).toBe(1);