mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
* refactor(application): build application cancellations with a required reason Migrate every AnalysisCancelledError construction under src/application to cancelledBy and lower the guard baseline from 671 to 442. Shutdown refusals in BinarySession report OwnerCancellation.ownerClosed when the caller did not abort, instead of an undefined reason. ReverseEngineeringService and DesktopBuildOwnedWork close their work with the typed owner reason. SharedStartupAttempt returns the departing caller's reason with a cancelled wait. One shared isAborted predicate replaces eleven local copies and narrows a checked signal for cancelledBy. * refactor(desktop): drop an unused cancellation import from desktop capture state
110 lines
3.8 KiB
TypeScript
110 lines
3.8 KiB
TypeScript
import { permitsCapabilityFallback } from "./CapabilityFallback.js";
|
|
import { listNamesFact } from "../domain/native/nativeOperationFacts.js";
|
|
import { executeFact } from "./AnalysisOperationFacts.js";
|
|
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
import {
|
|
AnalysisInputError,
|
|
AnalysisOutputError,
|
|
cancelledBy,
|
|
} from "../domain/analysisErrorCore.js";
|
|
import { err, ok, type Result } from "../domain/result.js";
|
|
import type { AnalysisOperationPort } from "./AnalysisProvider.js";
|
|
import { resolveProcedureAddress } from "./ProcedureAddressResolution.js";
|
|
|
|
/** Resolve an exact symbol after the provider rejects the caller address format. */
|
|
export const resolveXrefsAddress = async (
|
|
analysis: AnalysisOperationPort,
|
|
selector: string,
|
|
signal: AbortSignal,
|
|
): Promise<Result<string, AnalysisError>> => {
|
|
const named = await resolveXrefsName(analysis, selector, signal);
|
|
if (!named.ok) return named;
|
|
return named.value !== null
|
|
? ok(named.value)
|
|
: err(
|
|
new AnalysisInputError(
|
|
"xrefs",
|
|
{
|
|
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.`,
|
|
},
|
|
],
|
|
),
|
|
);
|
|
};
|
|
|
|
/** Exact name resolution has one ambiguity owner for enhanced tools and CLI fallback. */
|
|
export const resolveXrefsName = async (
|
|
analysis: AnalysisOperationPort,
|
|
selector: string,
|
|
signal?: AbortSignal,
|
|
operation: "xrefs" | "find_xrefs_to_name" = "xrefs",
|
|
): Promise<Result<string | null, AnalysisError>> => {
|
|
if (signal?.aborted) return err(cancelledBy(operation, signal));
|
|
const inventory = await executeFact(
|
|
analysis,
|
|
listNamesFact,
|
|
{},
|
|
signal === undefined ? {} : { signal },
|
|
);
|
|
if (!inventory.ok) {
|
|
if (
|
|
operation === "xrefs" &&
|
|
permitsCapabilityFallback(inventory.error) &&
|
|
inventory.error.operation === "list_names"
|
|
)
|
|
return resolveProcedureAddress(
|
|
async (operation, parameters, signal) => {
|
|
const result = await analysis.execute(
|
|
operation,
|
|
parameters,
|
|
signal === undefined ? {} : { signal },
|
|
);
|
|
return result.ok ? ok(result.value.result) : result;
|
|
},
|
|
selector,
|
|
signal,
|
|
);
|
|
return inventory;
|
|
}
|
|
if (signal?.aborted) return err(cancelledBy(operation, signal));
|
|
const addresses = new Set<string>();
|
|
for (const [index, row] of inventory.value.fact.entries()) {
|
|
// An empty address cannot be passed back to xrefs.
|
|
if (row.address.length === 0)
|
|
return err(
|
|
new AnalysisOutputError(
|
|
"list_names",
|
|
`Invalid symbol inventory entry at index ${index}`,
|
|
),
|
|
);
|
|
if (row.value === selector) addresses.add(row.address);
|
|
}
|
|
const [address] = addresses;
|
|
if (addresses.size <= 1) return ok(address ?? null);
|
|
return err(
|
|
new AnalysisInputError(
|
|
operation,
|
|
{
|
|
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.`,
|
|
},
|
|
],
|
|
),
|
|
);
|
|
};
|