rea-agents 1.7.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -59
- package/bridge/ghidra/ReaGhidraBridge.java +96 -11
- package/dist/application/ArtifactExtraction.js +1 -1
- package/dist/application/ArtifactInventory/classify.js +42 -0
- package/dist/application/ArtifactInventory/hash.js +43 -0
- package/dist/application/ArtifactInventory/reader.js +41 -0
- package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
- package/dist/application/ArtifactInventory/scanReader.js +124 -0
- package/dist/application/ArtifactInventory/types.js +10 -0
- package/dist/application/ArtifactInventory.js +9 -351
- package/dist/application/AuthorizedArtifactInventory.js +2 -2
- package/dist/application/BinarySession.js +47 -270
- package/dist/application/BinarySessionExecution.js +28 -0
- package/dist/application/BinarySessionOpen.js +39 -0
- package/dist/application/BinarySessionRecords.js +149 -0
- package/dist/application/BinarySessionStatus.js +75 -0
- package/dist/application/CapabilityInventory.js +42 -2
- package/dist/application/ClientRegistrationStatus.js +1 -1
- package/dist/application/CrossVersionInventory.js +8 -2
- package/dist/application/CrossVersionInvestigation.js +11 -29
- package/dist/application/CrossVersionInvestigationCollections.js +23 -0
- package/dist/application/DirectAnalysis.js +47 -44
- package/dist/application/Doctor.js +165 -197
- package/dist/application/DoctorDiagnostics.js +180 -0
- package/dist/application/ElectronBoundaryAnalysis.js +112 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
- package/dist/application/EnhancedToolPagination.js +22 -0
- package/dist/application/EnhancedToolTypes.js +4 -0
- package/dist/application/EnhancedTools.js +58 -50
- package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
- package/dist/application/InvestigationProviders.js +30 -0
- package/dist/application/InvestigationWorkspaceStore.js +24 -10
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
- package/dist/application/JavaScriptArtifactFiles.js +6 -2
- package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
- package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
- package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
- package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
- package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
- package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
- package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
- package/dist/application/JavaScriptJsonModules.js +39 -0
- package/dist/application/JavaScriptModuleRelationships.js +262 -0
- package/dist/application/JavaScriptReplayPermission.js +16 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +292 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/LinuxHopper.js +10 -0
- package/dist/application/MacHopper.js +22 -11
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
- package/dist/application/PermissionAuthority.js +106 -63
- package/dist/application/ProcessCaptureCapability.js +1 -1
- package/dist/application/ProcessCapturePermission.js +13 -0
- package/dist/application/ProcessCli.js +2 -12
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +15 -11
- package/dist/application/ProjectPermissionStore.js +49 -9
- package/dist/application/RealHopperAssertions.js +76 -0
- package/dist/application/ReconstructionCoverageService.js +69 -0
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
- package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
- package/dist/application/Setup.js +147 -259
- package/dist/application/SetupClientConfiguration.js +220 -0
- package/dist/application/SetupClients.js +24 -2
- package/dist/application/SetupPlan.js +123 -12
- package/dist/application/SetupSkill.js +26 -12
- package/dist/application/SupportedClients.js +1 -0
- package/dist/application/Uninstall.js +6 -3
- package/dist/application/WindowsCapabilities.js +86 -0
- package/dist/application/runtime.js +2 -0
- package/dist/artifacts/AsarArtifactReader.js +11 -0
- package/dist/browser/BrowserProcessStartup.js +88 -0
- package/dist/browser/CdpCaptureDocuments.js +12 -8
- package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
- package/dist/browser/CdpCaptureEventHandlers.js +336 -0
- package/dist/browser/CdpCaptureEventHelpers.js +71 -0
- package/dist/browser/CdpCaptureEventState.js +1 -0
- package/dist/browser/CdpCaptureEventTypes.js +1 -0
- package/dist/browser/CdpCaptureEvents.js +46 -464
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +5 -1
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpObservationSession.js +51 -8
- package/dist/browser/CdpPageCapture.js +12 -129
- package/dist/browser/CdpPageCaptureScripts.js +97 -0
- package/dist/browser/CdpPageCaptureWorkers.js +46 -0
- package/dist/browser/CdpWebMcpDiscovery.js +38 -14
- package/dist/browser/PngVisualDiff.js +9 -2
- package/dist/catalogIdentity.js +8 -1
- package/dist/cli/artifactCommands.js +82 -0
- package/dist/cli/coreAnalysisCommands.js +232 -0
- package/dist/cli/managedCommands.js +397 -0
- package/dist/cli/managedProjectGraphCommand.js +24 -0
- package/dist/cli/options.js +9 -0
- package/dist/cli/setupCommands.js +108 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utilityCommands.js +122 -0
- package/dist/cli.js +13 -383
- package/dist/cliApplicationCommands.js +176 -0
- package/dist/cliBrowserAdvancedCommands.js +73 -16
- package/dist/cliBrowserCommands.js +39 -115
- package/dist/cliCommandNames.js +17 -0
- package/dist/cliElectronCommands.js +100 -27
- package/dist/cliEvidenceCommands.js +13 -2
- package/dist/cliInvestigationCommands.js +53 -10
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliObservationOptions.js +137 -0
- package/dist/cliPolicyCommands.js +80 -46
- package/dist/cliSetup.js +289 -0
- package/dist/config/environment.js +107 -0
- package/dist/config/parseConfig.js +228 -0
- package/dist/config/parsers.js +68 -0
- package/dist/config/permissions.js +30 -0
- package/dist/config/types.js +1 -0
- package/dist/config.js +1 -292
- package/dist/contracts/applicationToolContracts.js +225 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +49 -47
- package/dist/contracts/toolEffects.js +174 -0
- package/dist/contracts/toolOutputSchemaGroups.js +232 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
- package/dist/contracts/toolOutputSchemas.js +2 -535
- package/dist/doctorRuntime.js +42 -1
- package/dist/domain/analysisErrorPresentation.js +234 -0
- package/dist/domain/analysisErrorProjection.js +284 -0
- package/dist/domain/artifactComparison.js +37 -19
- package/dist/domain/binaryTarget.js +87 -37
- package/dist/domain/browserObservation.js +1 -282
- package/dist/domain/browserObservationSchemas.js +286 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +32 -448
- package/dist/domain/functionComparison.js +4 -165
- package/dist/domain/functionComparisonDimensions.js +164 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
- package/dist/domain/javascriptApplicationGraph.js +2 -1
- package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +233 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptExportInstrumentation.js +97 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +100 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
- package/dist/domain/javascriptSemanticAnalysis.js +386 -0
- package/dist/domain/javascriptSemanticIr.js +30 -0
- package/dist/domain/javascriptSemanticProjection.js +366 -0
- package/dist/domain/javascriptSemanticState.js +40 -0
- package/dist/domain/javascriptSemanticTraversal.js +22 -0
- package/dist/domain/javascriptSemanticValues.js +352 -0
- package/dist/domain/javascriptStaticAnalysis.js +26 -254
- package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
- package/dist/domain/javascriptStaticAnalysisState.js +6 -0
- package/dist/domain/knownPageCoverage.js +21 -0
- package/dist/domain/managedApplicationGraph.js +206 -0
- package/dist/domain/managedApplicationGraphCoverage.js +170 -0
- package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
- package/dist/domain/managedApplicationGraphNodes.js +336 -0
- package/dist/domain/managedArtifact.js +452 -0
- package/dist/domain/managedMemberComparison.js +211 -0
- package/dist/domain/managedMemberComparisonCoverage.js +72 -0
- package/dist/domain/managedMemberComparisonMatch.js +356 -0
- package/dist/domain/managedNativeVerification.js +46 -0
- package/dist/domain/managedNativeVerificationMatch.js +272 -0
- package/dist/domain/managedNativeVerificationSchemas.js +141 -0
- package/dist/domain/managedReconstruction.js +196 -0
- package/dist/domain/managedRuntimeCorrelation.js +184 -0
- package/dist/domain/nodeRuntimeCharacterization.js +66 -0
- package/dist/domain/permissionPolicy.js +2 -0
- package/dist/domain/reconstructionCoverage.js +387 -0
- package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
- package/dist/domain/reconstructionVerificationSchemas.js +9 -3
- package/dist/domain/runtimeCharacterization.js +85 -0
- package/dist/domain/webBundleAnalyzer.js +3 -409
- package/dist/domain/webBundleAnalyzerAst.js +77 -0
- package/dist/domain/webBundleAnalyzerInspection.js +307 -0
- package/dist/domain/webBundleAnalyzerResult.js +120 -0
- package/dist/dotnet/ManagedArtifactInspector.js +339 -0
- package/dist/dotnet/ManagedMemberInspector.js +153 -0
- package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
- package/dist/dotnet/ManagedMemberRows.js +120 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +104 -0
- package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
- package/dist/dotnet/ManagedMetadataLayout.js +259 -0
- package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
- package/dist/dotnet/ManagedPeReader.js +188 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +76 -91
- package/dist/ghidra/GhidraClientStartup.js +29 -0
- package/dist/ghidra/GhidraClientWire.js +34 -0
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraDiagnostics.js +6 -1
- package/dist/ghidra/GhidraInstallation.js +20 -15
- package/dist/ghidra/GhidraLauncher.js +93 -29
- package/dist/ghidra/GhidraProvider.js +67 -161
- package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
- package/dist/ghidra/GhidraSessionValues.js +2 -0
- package/dist/ghidra/GhidraSocketConnection.js +44 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
- package/dist/ghidra/GhidraTransport.js +71 -0
- package/dist/identity.js +3 -2
- package/dist/main/messages.js +5 -0
- package/dist/main/reload.js +49 -0
- package/dist/main/shutdown.js +25 -0
- package/dist/main/startup.js +14 -0
- package/dist/main/state.js +26 -0
- package/dist/main/transport.js +61 -0
- package/dist/main/types.js +1 -0
- package/dist/main.js +35 -132
- package/dist/process/PrivateRuntimeRoot.js +3 -2
- package/dist/process/ProcessOwnership.js +35 -0
- package/dist/process/ProviderProcess.js +2 -0
- package/dist/replay/JavaScriptReplayWorker.js +300 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayOutcome.js +95 -0
- package/dist/replay/ReplayProcessLifecycle.js +71 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/ProcessCaptureElicitation.js +157 -0
- package/dist/server/createServer.js +158 -41
- package/dist/server/registerApplicationTools/characterization.js +57 -0
- package/dist/server/registerApplicationTools/compareVersions.js +34 -0
- package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
- package/dist/server/registerApplicationTools/coverage.js +84 -0
- package/dist/server/registerApplicationTools/helpers.js +42 -0
- package/dist/server/registerApplicationTools/traceFeature.js +26 -0
- package/dist/server/registerApplicationTools/types.js +1 -0
- package/dist/server/registerApplicationTools.js +13 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +61 -60
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +39 -12
- package/dist/server/registerEnhancedTools.js +52 -15
- package/dist/server/registerEvidenceResources.js +54 -0
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools/helpers.js +74 -0
- package/dist/server/registerInvestigationTools/types.js +1 -0
- package/dist/server/registerInvestigationTools.js +103 -132
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
- package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
- package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
- package/dist/server/registerManagedWorkflowTools/types.js +1 -0
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
- package/dist/server/registerManagedWorkflowTools.js +13 -0
- package/dist/server/registerOfficialTools.js +81 -67
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionRecordTools.js +137 -0
- package/dist/server/registerSessionStatusTool.js +9 -8
- package/dist/server/registerSessionTools.js +77 -216
- package/dist/server/sessionAvailabilityPolicy.js +10 -0
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +177 -2
- package/dist/server/toolResult.js +30 -17
- package/package.json +21 -14
- package/scripts/rea.mjs +1 -1
- package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
- package/scripts/prepare-node-pty.mjs +0 -35
- package/scripts/rebuild-native.mjs +0 -22
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { err, ok } from "../domain/result.js";
|
|
5
5
|
import { silentLogger } from "../logger.js";
|
|
@@ -14,19 +14,23 @@ import { GhidraResponseRouter } from "./GhidraResponseRouter.js";
|
|
|
14
14
|
import { GhidraRequestQueue } from "./GhidraRequestQueue.js";
|
|
15
15
|
import { bindGhidraSessionFailure, GhidraSessionError, } from "./GhidraSessionError.js";
|
|
16
16
|
import { isGhidraShutdownAcknowledgement, parseGhidraSessionInfo, } from "./GhidraSessionValues.js";
|
|
17
|
-
import {
|
|
17
|
+
import { createGhidraTargetSnapshot } from "./GhidraTargetSnapshot.js";
|
|
18
|
+
import { connectGhidraSocket } from "./GhidraSocketConnection.js";
|
|
19
|
+
import { GhidraWire } from "./GhidraClientWire.js";
|
|
20
|
+
import { completeGhidraStartupHandshake } from "./GhidraClientStartup.js";
|
|
18
21
|
const SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
19
|
-
const SESSION_ROOT =
|
|
22
|
+
const SESSION_ROOT = tmpdir();
|
|
20
23
|
/** Owns one authenticated, private, read-only Ghidra headless session. */
|
|
21
24
|
export class GhidraClient {
|
|
22
25
|
#options;
|
|
23
|
-
#pending = new PendingOperations();
|
|
24
26
|
#logger;
|
|
27
|
+
#pending = new PendingOperations();
|
|
25
28
|
#socket;
|
|
26
29
|
#detachSocket;
|
|
27
30
|
#launch;
|
|
28
31
|
#process;
|
|
29
32
|
#runtimeRoot;
|
|
33
|
+
#snapshotPath;
|
|
30
34
|
#token;
|
|
31
35
|
#runId;
|
|
32
36
|
#nextId = 1;
|
|
@@ -37,6 +41,7 @@ export class GhidraClient {
|
|
|
37
41
|
#startPromise;
|
|
38
42
|
#closePromise;
|
|
39
43
|
#failure = bindGhidraSessionFailure(() => this.#diagnostics());
|
|
44
|
+
#wire;
|
|
40
45
|
#requestQueue;
|
|
41
46
|
#responseRouter = new GhidraResponseRouter({
|
|
42
47
|
pending: this.#pending,
|
|
@@ -60,13 +65,23 @@ export class GhidraClient {
|
|
|
60
65
|
this.#failAll(this.#failure("process", "Ghidra bridge socket closed"));
|
|
61
66
|
};
|
|
62
67
|
constructor(options) {
|
|
63
|
-
this.#logger = options.logger ?? silentLogger;
|
|
64
68
|
this.#options = {
|
|
65
69
|
...options,
|
|
66
70
|
requestTimeoutMs: options.requestTimeoutMs ?? GHIDRA_REQUEST_TIMEOUT_MS,
|
|
67
71
|
startupTimeoutMs: options.startupTimeoutMs ?? GHIDRA_STARTUP_TIMEOUT_MS,
|
|
72
|
+
transport: options.transport ?? "unix-socket",
|
|
68
73
|
};
|
|
69
|
-
this.#
|
|
74
|
+
this.#logger = options.logger ?? silentLogger;
|
|
75
|
+
this.#wire = new GhidraWire({
|
|
76
|
+
getSocket: () => this.#socket,
|
|
77
|
+
getToken: () => this.#token,
|
|
78
|
+
nextId: () => this.#nextId++,
|
|
79
|
+
pending: this.#pending,
|
|
80
|
+
requestTimeoutMs: this.#options.requestTimeoutMs,
|
|
81
|
+
logger: this.#logger,
|
|
82
|
+
failure: this.#failure,
|
|
83
|
+
});
|
|
84
|
+
this.#requestQueue = new GhidraRequestQueue(GHIDRA_MAX_QUEUED_REQUESTS, (method, parameters, requestOptions) => this.#wire.request(method, parameters, requestOptions), (kind, message, timeoutMs) => this.#failure(kind, message, undefined, timeoutMs === undefined ? {} : { timeoutMs }));
|
|
70
85
|
}
|
|
71
86
|
/** Launch Ghidra once and require its exact post-analysis handshake. */
|
|
72
87
|
start(signal) {
|
|
@@ -103,7 +118,7 @@ export class GhidraClient {
|
|
|
103
118
|
const started = await this.start(options.signal);
|
|
104
119
|
if (!started.ok)
|
|
105
120
|
return started;
|
|
106
|
-
const result = await this.#request("ping", {}, options);
|
|
121
|
+
const result = await this.#wire.request("ping", {}, options);
|
|
107
122
|
if (!result.ok)
|
|
108
123
|
return result;
|
|
109
124
|
return this.#parseSessionInfo(result.value);
|
|
@@ -155,16 +170,34 @@ export class GhidraClient {
|
|
|
155
170
|
}
|
|
156
171
|
if (deadline.signal.aborted)
|
|
157
172
|
return this.#startupInterrupted(deadline);
|
|
158
|
-
const
|
|
173
|
+
const endpoint = {
|
|
174
|
+
transport: this.#options.transport,
|
|
175
|
+
path: join(this.#runtimeRoot.path, this.#options.transport === "unix-socket"
|
|
176
|
+
? "bridge.sock"
|
|
177
|
+
: "bridge-endpoint.json"),
|
|
178
|
+
};
|
|
179
|
+
try {
|
|
180
|
+
const snapshot = await createGhidraTargetSnapshot(this.#options.targetPath, this.#runtimeRoot.path, this.#options.targetSha256);
|
|
181
|
+
this.#snapshotPath = snapshot.path;
|
|
182
|
+
}
|
|
183
|
+
catch (cause) {
|
|
184
|
+
const failure = this.#failure("start", "Ghidra target snapshot failed admission", cause);
|
|
185
|
+
await this.#cleanup();
|
|
186
|
+
return err(failure);
|
|
187
|
+
}
|
|
188
|
+
if (deadline.signal.aborted)
|
|
189
|
+
return this.#startupInterrupted(deadline);
|
|
159
190
|
this.#token = randomBytes(32).toString("hex");
|
|
160
191
|
this.#runId = randomUUID();
|
|
161
192
|
const launched = await this.#options.launcher
|
|
162
193
|
.launch({
|
|
163
194
|
runtimeRoot: this.#runtimeRoot.path,
|
|
164
|
-
|
|
195
|
+
transport: endpoint.transport,
|
|
196
|
+
endpointPath: endpoint.path,
|
|
165
197
|
token: this.#token,
|
|
166
198
|
runId: this.#runId,
|
|
167
|
-
targetPath: this.#
|
|
199
|
+
targetPath: this.#snapshotPath,
|
|
200
|
+
targetSha256: this.#options.targetSha256,
|
|
168
201
|
providerVersion: this.#options.providerVersion,
|
|
169
202
|
profileDigest: this.#options.profileDigest,
|
|
170
203
|
}, { signal: deadline.signal })
|
|
@@ -182,92 +215,40 @@ export class GhidraClient {
|
|
|
182
215
|
this.#process = new ProviderProcessSupervisor(launched.value, {
|
|
183
216
|
onDiagnostic: (event) => this.#onProcessDiagnostic(event),
|
|
184
217
|
});
|
|
185
|
-
const connected = await this.#connect(
|
|
218
|
+
const connected = await this.#connect(endpoint, deadline);
|
|
186
219
|
if (!connected.ok) {
|
|
187
220
|
const failure = connected.error;
|
|
188
221
|
await this.#cleanup();
|
|
189
222
|
return err(failure);
|
|
190
223
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
224
|
+
return completeGhidraStartupHandshake({
|
|
225
|
+
deadline,
|
|
226
|
+
request: (method, params, requestOptions) => this.#wire.request(method, params, requestOptions),
|
|
227
|
+
parseSessionInfo: (value) => this.#parseSessionInfo(value),
|
|
228
|
+
cleanup: () => this.#cleanup(),
|
|
229
|
+
failure: this.#failure,
|
|
230
|
+
startupTimeoutMs: this.#options.startupTimeoutMs,
|
|
194
231
|
});
|
|
195
|
-
if (!ping.ok) {
|
|
196
|
-
const failure = deadline.signal.aborted
|
|
197
|
-
? this.#interruptionFailure(deadline)
|
|
198
|
-
: ping.error;
|
|
199
|
-
await this.#cleanup();
|
|
200
|
-
return err(failure);
|
|
201
|
-
}
|
|
202
|
-
const parsed = this.#parseSessionInfo(ping.value);
|
|
203
|
-
if (!parsed.ok || parsed.value.analysis_timed_out) {
|
|
204
|
-
const failure = parsed.ok
|
|
205
|
-
? this.#failure("analysis_timeout", "Ghidra auto-analysis reached its per-file deadline")
|
|
206
|
-
: parsed.error;
|
|
207
|
-
await this.#cleanup();
|
|
208
|
-
return err(failure);
|
|
209
|
-
}
|
|
210
|
-
return parsed;
|
|
211
232
|
}
|
|
212
|
-
async #connect(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
return err(this.#interruptionFailure(deadline));
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
const connected = await connectGhidraSocketOnce(socketPath, deadline.signal);
|
|
229
|
-
if (connected.ok) {
|
|
230
|
-
this.#socket = connected.value;
|
|
231
|
-
this.#detachSocket = attachGhidraSocket(connected.value, {
|
|
232
|
-
data: this.#onSocketData,
|
|
233
|
-
error: this.#onSocketError,
|
|
234
|
-
close: this.#onSocketClose,
|
|
235
|
-
});
|
|
236
|
-
return ok(undefined);
|
|
237
|
-
}
|
|
238
|
-
if ((await deadline.wait(50)) === "aborted")
|
|
239
|
-
return err(this.#interruptionFailure(deadline));
|
|
240
|
-
}
|
|
241
|
-
return err(this.#failure("timeout", "Ghidra startup deadline elapsed", undefined, {
|
|
242
|
-
timeoutMs: this.#options.startupTimeoutMs,
|
|
243
|
-
}));
|
|
244
|
-
}
|
|
245
|
-
async #request(method, params, options) {
|
|
246
|
-
const socket = this.#socket;
|
|
247
|
-
const token = this.#token;
|
|
248
|
-
if (socket === undefined || socket.destroyed || token === undefined)
|
|
249
|
-
return err(this.#failure("process", "Ghidra bridge is unavailable"));
|
|
250
|
-
if (options.signal?.aborted === true)
|
|
251
|
-
return err(this.#failure("cancelled", "Ghidra request was cancelled"));
|
|
252
|
-
const id = this.#nextId++;
|
|
253
|
-
const timeoutMs = options.timeoutMs ?? this.#options.requestTimeoutMs;
|
|
254
|
-
if (timeoutMs <= 0)
|
|
255
|
-
return err(this.#failure("timeout", "Ghidra request deadline elapsed", undefined, {
|
|
256
|
-
timeoutMs,
|
|
257
|
-
}));
|
|
258
|
-
const response = this.#pending.wait(id, {
|
|
259
|
-
timeoutMs,
|
|
260
|
-
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
261
|
-
timeoutValue: () => err(this.#failure("timeout", "Ghidra bridge request timed out", undefined, { timeoutMs })),
|
|
262
|
-
cancelledValue: () => err(this.#failure("cancelled", "Ghidra request was cancelled")),
|
|
263
|
-
});
|
|
264
|
-
socket.write(`${JSON.stringify({ id, token, method, params })}\n`, (cause) => {
|
|
265
|
-
if (cause !== undefined && cause !== null)
|
|
266
|
-
this.#pending.settle(id, err(this.#failure("process", "Ghidra bridge write failed", cause)));
|
|
233
|
+
async #connect(endpoint, deadline) {
|
|
234
|
+
const connected = await connectGhidraSocket({
|
|
235
|
+
endpoint,
|
|
236
|
+
deadline,
|
|
237
|
+
failure: this.#failure,
|
|
238
|
+
isClosed: () => this.#closing,
|
|
239
|
+
processExited: () => this.#processSnapshot?.exitCode !== undefined,
|
|
240
|
+
startupTimeoutMs: this.#options.startupTimeoutMs,
|
|
241
|
+
handlers: {
|
|
242
|
+
data: this.#onSocketData,
|
|
243
|
+
error: this.#onSocketError,
|
|
244
|
+
close: this.#onSocketClose,
|
|
245
|
+
},
|
|
267
246
|
});
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
247
|
+
if (!connected.ok)
|
|
248
|
+
return connected;
|
|
249
|
+
this.#socket = connected.value.socket;
|
|
250
|
+
this.#detachSocket = connected.value.detach;
|
|
251
|
+
return ok(undefined);
|
|
271
252
|
}
|
|
272
253
|
#parseSessionInfo(value) {
|
|
273
254
|
const runId = this.#runId;
|
|
@@ -277,6 +258,7 @@ export class GhidraClient {
|
|
|
277
258
|
runId,
|
|
278
259
|
providerVersion: this.#options.providerVersion,
|
|
279
260
|
profileDigest: this.#options.profileDigest,
|
|
261
|
+
targetSha256: this.#options.targetSha256,
|
|
280
262
|
});
|
|
281
263
|
if (parsed.ok)
|
|
282
264
|
return parsed;
|
|
@@ -301,9 +283,9 @@ export class GhidraClient {
|
|
|
301
283
|
this.#requestQueue.failQueued(this.#failure("process", "Ghidra session closed"));
|
|
302
284
|
const socket = this.#socket;
|
|
303
285
|
if (socket !== undefined && !socket.destroyed) {
|
|
304
|
-
const shutdown = await this.#
|
|
305
|
-
timeoutMs: SHUTDOWN_TIMEOUT_MS
|
|
306
|
-
|
|
286
|
+
const shutdown = await this.#wire
|
|
287
|
+
.request("shutdown", {}, { timeoutMs: SHUTDOWN_TIMEOUT_MS })
|
|
288
|
+
.catch(() => err(this.#failure("process", "Ghidra shutdown request failed")));
|
|
307
289
|
if (!shutdown.ok || !isGhidraShutdownAcknowledgement(shutdown.value))
|
|
308
290
|
this.#logger.warn({ status: shutdown.ok ? "invalid-acknowledgement" : "failed" }, "Ghidra bridge shutdown was not confirmed");
|
|
309
291
|
}
|
|
@@ -331,6 +313,7 @@ export class GhidraClient {
|
|
|
331
313
|
const runtimeRoot = this.#runtimeRoot;
|
|
332
314
|
this.#runtimeRoot = undefined;
|
|
333
315
|
await runtimeRoot?.close();
|
|
316
|
+
this.#snapshotPath = undefined;
|
|
334
317
|
this.#token = undefined;
|
|
335
318
|
this.#runId = undefined;
|
|
336
319
|
this.#responseBuffer.reset();
|
|
@@ -386,6 +369,8 @@ export class GhidraClient {
|
|
|
386
369
|
const snapshot = this.#process?.snapshot() ?? this.#processSnapshot;
|
|
387
370
|
return createGhidraDiagnostics({
|
|
388
371
|
targetPath: this.#options.targetPath,
|
|
372
|
+
targetSha256: this.#options.targetSha256,
|
|
373
|
+
transport: this.#options.transport,
|
|
389
374
|
providerVersion: this.#options.providerVersion,
|
|
390
375
|
profileDigest: this.#options.profileDigest,
|
|
391
376
|
...(this.#runtimeRoot === undefined
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { err } from "../domain/result.js";
|
|
2
|
+
/** Ping and validate the bridge after its socket is attached. */
|
|
3
|
+
export async function completeGhidraStartupHandshake(options) {
|
|
4
|
+
const ping = await options.request("ping", {}, {
|
|
5
|
+
signal: options.deadline.signal,
|
|
6
|
+
timeoutMs: options.deadline.remainingMs(),
|
|
7
|
+
});
|
|
8
|
+
if (!ping.ok) {
|
|
9
|
+
const failure = options.deadline.signal.aborted
|
|
10
|
+
? interruptionFailure(options)
|
|
11
|
+
: ping.error;
|
|
12
|
+
await options.cleanup();
|
|
13
|
+
return err(failure);
|
|
14
|
+
}
|
|
15
|
+
const parsed = options.parseSessionInfo(ping.value);
|
|
16
|
+
if (!parsed.ok || parsed.value.analysis_timed_out) {
|
|
17
|
+
const failure = parsed.ok
|
|
18
|
+
? options.failure("analysis_timeout", "Ghidra auto-analysis reached its per-file deadline")
|
|
19
|
+
: parsed.error;
|
|
20
|
+
await options.cleanup();
|
|
21
|
+
return err(failure);
|
|
22
|
+
}
|
|
23
|
+
return parsed;
|
|
24
|
+
}
|
|
25
|
+
const interruptionFailure = (options) => options.deadline.cancelled
|
|
26
|
+
? options.failure("cancelled", "Ghidra startup was cancelled")
|
|
27
|
+
: options.failure("timeout", "Ghidra startup deadline elapsed", undefined, {
|
|
28
|
+
timeoutMs: options.startupTimeoutMs,
|
|
29
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { err } from "../domain/result.js";
|
|
2
|
+
/** Owns the socket write and pending-reply lifecycle for one bridge session. */
|
|
3
|
+
export class GhidraWire {
|
|
4
|
+
#options;
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.#options = options;
|
|
7
|
+
}
|
|
8
|
+
/** Write one authenticated request and return its correlated reply. */
|
|
9
|
+
async request(method, params, options) {
|
|
10
|
+
const socket = this.#options.getSocket();
|
|
11
|
+
const token = this.#options.getToken();
|
|
12
|
+
if (socket === undefined || socket.destroyed || token === undefined)
|
|
13
|
+
return err(this.#options.failure("process", "Ghidra bridge is unavailable"));
|
|
14
|
+
if (options.signal?.aborted === true)
|
|
15
|
+
return err(this.#options.failure("cancelled", "Ghidra request was cancelled"));
|
|
16
|
+
const id = this.#options.nextId();
|
|
17
|
+
const timeoutMs = options.timeoutMs ?? this.#options.requestTimeoutMs;
|
|
18
|
+
if (timeoutMs <= 0)
|
|
19
|
+
return err(this.#options.failure("timeout", "Ghidra request deadline elapsed", undefined, { timeoutMs }));
|
|
20
|
+
const response = this.#options.pending.wait(id, {
|
|
21
|
+
timeoutMs,
|
|
22
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
23
|
+
timeoutValue: () => err(this.#options.failure("timeout", "Ghidra bridge request timed out", undefined, { timeoutMs })),
|
|
24
|
+
cancelledValue: () => err(this.#options.failure("cancelled", "Ghidra request was cancelled")),
|
|
25
|
+
});
|
|
26
|
+
socket.write(`${JSON.stringify({ id, token, method, params })}\n`, (cause) => {
|
|
27
|
+
if (cause !== undefined && cause !== null)
|
|
28
|
+
this.#options.pending.settle(id, err(this.#options.failure("process", "Ghidra bridge write failed", cause)));
|
|
29
|
+
});
|
|
30
|
+
const result = await response;
|
|
31
|
+
this.#options.logger[result.ok ? "debug" : "warn"]({ method, status: result.ok ? "ok" : "error" }, "Ghidra bridge request completed");
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -17,4 +17,4 @@ export const GHIDRA_MAX_QUEUED_REQUESTS = 32;
|
|
|
17
17
|
/** Maximum encoded response line accepted from the Java bridge. */
|
|
18
18
|
export const GHIDRA_MAX_LINE_BYTES = 1024 * 1024;
|
|
19
19
|
/** Version of REA's Java bridge handshake and request protocol. */
|
|
20
|
-
export const GHIDRA_BRIDGE_VERSION =
|
|
20
|
+
export const GHIDRA_BRIDGE_VERSION = 4;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
/** Preserve actionable runtime coordinates after cleanup and redact bearer data. */
|
|
2
3
|
export const createGhidraDiagnostics = (options) => {
|
|
3
4
|
if (options.runtimeRoot === undefined &&
|
|
@@ -9,13 +10,17 @@ export const createGhidraDiagnostics = (options) => {
|
|
|
9
10
|
: value.replaceAll(options.token, "[REDACTED]");
|
|
10
11
|
return {
|
|
11
12
|
target_path: options.targetPath,
|
|
13
|
+
target_sha256: options.targetSha256,
|
|
14
|
+
transport: options.transport,
|
|
12
15
|
provider_version: options.providerVersion,
|
|
13
16
|
profile_digest: options.profileDigest,
|
|
14
17
|
...(options.runtimeRoot === undefined
|
|
15
18
|
? {}
|
|
16
19
|
: {
|
|
17
20
|
runtime_root: options.runtimeRoot,
|
|
18
|
-
|
|
21
|
+
endpoint_path: join(options.runtimeRoot, options.transport === "unix-socket"
|
|
22
|
+
? "bridge.sock"
|
|
23
|
+
: "bridge-endpoint.json"),
|
|
19
24
|
}),
|
|
20
25
|
...(options.launch === undefined
|
|
21
26
|
? {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { constants } from "node:fs";
|
|
3
3
|
import { accessSync, readFileSync } from "node:fs";
|
|
4
|
-
import {
|
|
4
|
+
import { posix, win32 } from "node:path";
|
|
5
5
|
/** Exact Ghidra build whose Java bridge contract this REA release supports. */
|
|
6
6
|
export const SUPPORTED_GHIDRA_VERSION = "12.1.2";
|
|
7
7
|
/** Exact JDK major documented by the supported Ghidra release. */
|
|
@@ -10,7 +10,7 @@ export const SUPPORTED_GHIDRA_JAVA_MAJOR = 21;
|
|
|
10
10
|
export const inspectGhidraInstallation = (options, host = systemGhidraInstallationHost()) => {
|
|
11
11
|
const platform = options.platform ?? process.platform;
|
|
12
12
|
const architecture = options.architecture ?? process.arch;
|
|
13
|
-
const coordinates = installationCoordinates(options, host);
|
|
13
|
+
const coordinates = installationCoordinates(options, platform, host);
|
|
14
14
|
const checks = installationChecks({
|
|
15
15
|
coordinates,
|
|
16
16
|
platform,
|
|
@@ -35,18 +35,23 @@ export const inspectGhidraInstallation = (options, host = systemGhidraInstallati
|
|
|
35
35
|
reason: failed?.remediation ?? null,
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
-
const installationCoordinates = (options, host) => {
|
|
38
|
+
const installationCoordinates = (options, platform, host) => {
|
|
39
|
+
const path = platform === "win32" ? win32 : posix;
|
|
39
40
|
const installDir = options.installDir ?? null;
|
|
40
41
|
const applicationPropertiesPath = installDir === null
|
|
41
42
|
? null
|
|
42
|
-
: join(installDir, "Ghidra", "application.properties");
|
|
43
|
-
const analyzeHeadlessPath = installDir === null
|
|
43
|
+
: path.join(installDir, "Ghidra", "application.properties");
|
|
44
|
+
const analyzeHeadlessPath = installDir === null
|
|
45
|
+
? null
|
|
46
|
+
: path.join(installDir, "support", platform === "win32" ? "analyzeHeadless.bat" : "analyzeHeadless");
|
|
44
47
|
const properties = applicationPropertiesPath === null
|
|
45
48
|
? undefined
|
|
46
49
|
: host.readText(applicationPropertiesPath);
|
|
47
50
|
const javaCommand = options.javaHome === undefined
|
|
48
|
-
? "
|
|
49
|
-
|
|
51
|
+
? platform === "win32"
|
|
52
|
+
? "java.exe"
|
|
53
|
+
: "java"
|
|
54
|
+
: path.join(options.javaHome, "bin", platform === "win32" ? "java.exe" : "java");
|
|
50
55
|
return {
|
|
51
56
|
installDir,
|
|
52
57
|
applicationPropertiesPath,
|
|
@@ -56,7 +61,7 @@ const installationCoordinates = (options, host) => {
|
|
|
56
61
|
? null
|
|
57
62
|
: propertyValue(properties, "application.version"),
|
|
58
63
|
javaCommand,
|
|
59
|
-
java: host.probeJava(javaCommand, ghidraJavaEnvironment(options.javaHome)),
|
|
64
|
+
java: host.probeJava(javaCommand, ghidraJavaEnvironment(options.javaHome, process.env, platform)),
|
|
60
65
|
};
|
|
61
66
|
};
|
|
62
67
|
const installationChecks = ({ coordinates, platform, architecture, javaHome, host, }) => [
|
|
@@ -69,17 +74,17 @@ const installationChecks = ({ coordinates, platform, architecture, javaHome, hos
|
|
|
69
74
|
}),
|
|
70
75
|
installationCheck({
|
|
71
76
|
name: "platform",
|
|
72
|
-
ok: platform === "linux",
|
|
77
|
+
ok: platform === "linux" || platform === "win32",
|
|
73
78
|
code: "unsupported_host",
|
|
74
79
|
detail: platform,
|
|
75
|
-
remediation: "REA's Ghidra
|
|
80
|
+
remediation: "Use REA's Ghidra adapter on a supported Linux or Windows x64 host.",
|
|
76
81
|
}),
|
|
77
82
|
installationCheck({
|
|
78
83
|
name: "architecture",
|
|
79
84
|
ok: architecture === "x64",
|
|
80
85
|
code: "unsupported_host",
|
|
81
86
|
detail: architecture,
|
|
82
|
-
remediation: "Use the official
|
|
87
|
+
remediation: "Use the official x86-64 Ghidra distribution on an x64 Linux or Windows host.",
|
|
83
88
|
}),
|
|
84
89
|
installationCheck({
|
|
85
90
|
name: "installation",
|
|
@@ -104,7 +109,7 @@ const installationChecks = ({ coordinates, platform, architecture, javaHome, hos
|
|
|
104
109
|
host.executable(coordinates.analyzeHeadlessPath),
|
|
105
110
|
code: "executable_missing",
|
|
106
111
|
detail: coordinates.analyzeHeadlessPath ?? "analyzeHeadless unavailable",
|
|
107
|
-
remediation: "Restore
|
|
112
|
+
remediation: "Restore support/analyzeHeadless or support/analyzeHeadless.bat from the official Ghidra release.",
|
|
108
113
|
}),
|
|
109
114
|
javaCheck(coordinates.java, coordinates.javaCommand, javaHome),
|
|
110
115
|
];
|
|
@@ -127,7 +132,7 @@ export const ghidraInstallationDiagnostics = (inspection) => ({
|
|
|
127
132
|
})),
|
|
128
133
|
});
|
|
129
134
|
/** Environment that makes an explicitly selected JDK win over PATH discovery. */
|
|
130
|
-
export const ghidraJavaEnvironment = (javaHome, environment = process.env) => {
|
|
135
|
+
export const ghidraJavaEnvironment = (javaHome, environment = process.env, platform = process.platform) => {
|
|
131
136
|
const boundedEnvironment = {
|
|
132
137
|
...environment,
|
|
133
138
|
_JAVA_OPTIONS: "",
|
|
@@ -140,7 +145,7 @@ export const ghidraJavaEnvironment = (javaHome, environment = process.env) => {
|
|
|
140
145
|
: {
|
|
141
146
|
...boundedEnvironment,
|
|
142
147
|
JAVA_HOME: javaHome,
|
|
143
|
-
PATH: `${join(javaHome, "bin")}${delimiter}${environment.PATH ?? ""}`,
|
|
148
|
+
PATH: `${(platform === "win32" ? win32 : posix).join(javaHome, "bin")}${platform === "win32" ? win32.delimiter : posix.delimiter}${environment.PATH ?? ""}`,
|
|
144
149
|
};
|
|
145
150
|
};
|
|
146
151
|
const installationCheck = (options) => ({
|
|
@@ -217,7 +222,7 @@ const systemGhidraInstallationHost = () => ({
|
|
|
217
222
|
major: javaMajor(version),
|
|
218
223
|
home,
|
|
219
224
|
bits,
|
|
220
|
-
jdk: executablePath(join(home, "bin", "javac")),
|
|
225
|
+
jdk: executablePath((process.platform === "win32" ? win32 : posix).join(home, "bin", process.platform === "win32" ? "javac.exe" : "javac")),
|
|
221
226
|
};
|
|
222
227
|
},
|
|
223
228
|
});
|