diff --git a/docs/ida-provider.md b/docs/ida-provider.md index 9f2a2f262a..685d638b9a 100644 --- a/docs/ida-provider.md +++ b/docs/ida-provider.md @@ -220,6 +220,12 @@ For guided registration, set `REA_IDA_MCP_CONFIG` before `rea setup --client { ).toMatchObject({ status: "unsupported", code: "architecture_unsupported", - reason: expect.stringContaining("Hexagon"), + reason: expect.stringMatching(/hexagon.*Ghidra/su), }); }); + it("admits only the families IDA admits today, so new families stay refused", () => { + const config = parseConfig({}); + if (!config.ok) throw new Error("expected valid configuration"); + const provider = new IdaProvider(config.value, {}); + const admitted: readonly string[] = ["x86", "x86_64", "arm", "arm64"]; + for (const architecture of BINARY_ARCHITECTURES) { + // Admission reads only kind, format and family, so one ELF shape + // covers every recognized family, including any added later. + const support = provider.inspectTargetSupport({ + path: "/tmp/fixture.elf", + sha256: "a".repeat(64), + kind: "executable", + format: "elf", + architecture, + availableArchitectures: [architecture], + } as BinaryTarget); + expect(support, architecture).toMatchObject( + admitted.includes(architecture) + ? { status: "supported" } + : { + status: "unsupported", + code: "architecture_unsupported", + reason: expect.stringContaining(architecture), + }, + ); + } + }); it("declines thin arm64_32 Mach-O targets without a verified lane", () => { const config = parseConfig({}); if (!config.ok) throw new Error("expected valid configuration"); diff --git a/src/ida/IdaProvider.ts b/src/ida/IdaProvider.ts index f670c16e15..47730e621a 100644 --- a/src/ida/IdaProvider.ts +++ b/src/ida/IdaProvider.ts @@ -8,6 +8,7 @@ import { import type { AnalysisProfileCommitment } from "../domain/analysisProfile.js"; import { isElfMetadataArchitecture, + type BinaryArchitecture, type BinaryTarget, } from "../domain/binaryTargetTypes.js"; import { err, ok } from "../domain/result.js"; @@ -53,6 +54,17 @@ import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import type { ProviderInspectionScope } from "../application/ProviderInspectionScope.js"; import type { ProviderRejectionCode } from "../domain/providerSelection.js"; +/** + * Families IDA admits today. Every other family is refused, including families + * that REA recognizes after this list was written. + */ +const IDA_ARCHITECTURES = new Set([ + "x86", + "x86_64", + "arm", + "arm64", +]); + /** Bring-your-own IDA MCP candidate; discovery performs no provider startup. */ export class IdaProvider implements AnalysisProviderCandidate { readonly #ownedResources = new ArtifactResourceScope(); @@ -300,32 +312,6 @@ export class IdaProvider implements AnalysisProviderCandidate { "IDA does not admit caller-selected GameCube DOL images. Open the target with Ghidra and select format gamecube-dol.", diagnostics, }; - if ( - target.kind === "executable" && - (isElfMetadataArchitecture(target.architecture) || - target.architecture === "hexagon") - ) - return { - status: "unsupported", - code: "architecture_unsupported", - reason: `REA's IDA adapter has no verified ${ - target.architecture === "mips" - ? "MIPS" - : target.architecture === "riscv" - ? "RISC-V" - : target.architecture === "powerpc" - ? "PowerPC" - : "Hexagon" - } lane. Select a supported Ghidra profile instead.`, - diagnostics, - }; - if (target.kind === "executable" && target.architecture === "arm64_32") - return { - status: "unsupported", - code: "architecture_unsupported", - reason: "REA's IDA adapter has no verified arm64_32 lane.", - diagnostics, - }; if (target.kind !== "executable") return { status: "unsupported", @@ -342,6 +328,18 @@ export class IdaProvider implements AnalysisProviderCandidate { "IDA does not admit headerless raw binaries. Open the target with Ghidra and supply architecture and entry_point.", diagnostics, }; + if (!IDA_ARCHITECTURES.has(target.architecture)) + return { + status: "unsupported", + code: "architecture_unsupported", + // Header-declared families that Ghidra admits keep the pointer there. + reason: + isElfMetadataArchitecture(target.architecture) || + target.architecture === "hexagon" + ? `REA's IDA adapter has no verified ${target.architecture} lane. Select a supported Ghidra profile instead.` + : `REA's IDA adapter has no verified ${target.architecture} lane.`, + diagnostics, + }; return target.format === "mach-o-universal" ? { status: "unknown",