rea-agents 6.0.0 → 6.2.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 +26 -18
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +205 -51
- package/bridge/hopper_bridge.py +314 -127
- package/bridge/mitmproxy/capture.py +0 -2
- package/bridge/native/rea_lldb_tracer.py +630 -94
- package/bridge/process/ProcessRunTokenReader.swift +39 -5
- package/bridge/pwntools/recorded_crash_impl.py +4 -0
- package/dist/android/JadxConfiguration.js +274 -31
- package/dist/android/JadxMcpTransport.js +18 -2
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +76 -37
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/BinaryTargetResolver.js +5 -3
- package/dist/application/BrowserEvidence.js +3 -8
- package/dist/application/BrowserScenarioEvidence.js +2 -18
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +48 -11
- package/dist/application/ClientConfigurationDocument.js +917 -8
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +56 -51
- package/dist/application/DirectAnalysisCleanup.js +72 -0
- package/dist/application/DirectAnalysisStatus.js +4 -5
- package/dist/application/Doctor.js +19 -21
- package/dist/application/DoctorDiagnostics.js +1 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +64 -17
- package/dist/application/EvidenceBundleFiles.js +30 -13
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +11 -2
- package/dist/application/JsonFiles.js +83 -28
- package/dist/application/LinuxHopper.js +9 -6
- package/dist/application/MacHopper.js +15 -18
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/RealHopperAssertions.js +0 -11
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +1 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/ReferenceSourceImportEntries.js +1 -1
- package/dist/application/Setup.js +21 -17
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +21 -29
- package/dist/application/SetupPlan.js +11 -9
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +82 -29
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateMaintenance.js +7 -5
- package/dist/application/UpdateRuntime.js +57 -36
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCaptureService.js +4 -2
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +32 -6
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WorkflowEvidence.js +105 -0
- package/dist/application/XrefsAddressResolution.js +45 -0
- package/dist/application/analysisView/AnalysisViewService.js +76 -0
- package/dist/application/binary/AnalysisClientCleanup.js +30 -5
- package/dist/application/binary/AnalysisProviderEvaluation.js +22 -7
- package/dist/application/binary/AnalysisProviderRegistry.js +4 -6
- package/dist/application/binary/AnalysisSnapshotCache.js +13 -14
- package/dist/application/binary/BinarySession.js +161 -93
- package/dist/application/binary/BinarySessionComposition.js +1 -3
- package/dist/application/binary/BinarySessionExecution.js +3 -5
- package/dist/application/binary/BinarySessionOpen.js +4 -4
- package/dist/application/binary/BinarySessionRecords.js +26 -4
- package/dist/application/binary/BinarySessionStatus.js +18 -7
- package/dist/application/binary/CompositeProvider.js +16 -17
- package/dist/application/binary/LazyAnalysisProvider.js +8 -5
- package/dist/application/binary/SessionProviderRouter.js +27 -135
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
- package/dist/application/evm/EvmInterfaceService.js +4 -2
- package/dist/application/homebrew.js +48 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +9 -13
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +21 -4
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +27 -15
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +10 -7
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +44 -10
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +11 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +9 -0
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +8 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +12 -3
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +0 -1
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +49 -19
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +56 -8
- package/dist/application/javascript/JavaScriptModuleRelationships.js +38 -9
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +6 -4
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -2
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +1 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +75 -46
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +64 -19
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +9 -5
- package/dist/application/managed/ManagedNativeVerificationService.js +6 -4
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/process/ProcessCli.js +25 -17
- package/dist/application/process/ProcessEvidence.js +4 -4
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +48 -13
- package/dist/artifacts/ArtifactReader.js +31 -0
- package/dist/artifacts/DirectoryArtifactReader.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +106 -15
- package/dist/artifacts/NativeDmgArtifactReader.js +73 -21
- package/dist/artifacts/SafeOutputTree.js +16 -2
- package/dist/artifacts/ZipArtifactReader.js +11 -4
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +26 -5
- package/dist/artifacts/apple/DylibResolutionReader.js +17 -7
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +55 -23
- package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/artifacts/extraction/ArtifactExtraction.js +78 -21
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +79 -68
- package/dist/artifacts/inventory/ArtifactInventory.js +0 -1
- package/dist/artifacts/inventory/reader.js +3 -3
- package/dist/artifacts/inventory/scanCanonical.js +59 -38
- package/dist/artifacts/inventory/scanReader.js +5 -9
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/browser/BrowserScenarioPartialObservation.js +106 -0
- package/dist/browser/CdpBrowserProvider.js +2 -3
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +78 -15
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +25 -1
- package/dist/browser/CdpCaptureValues.js +20 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpElectronProvider.js +0 -2
- package/dist/browser/CdpElectronScriptEvents.js +2 -8
- package/dist/browser/CdpElectronScripts.js +2 -3
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/CdpPageCaptureScripts.js +2 -3
- package/dist/browser/CdpSafeMetadata.js +10 -10
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +59 -44
- package/dist/browser/PlaywrightElectronActiveActions.js +34 -79
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +133 -130
- package/dist/browser/PlaywrightScenarioArtifacts.js +1 -1
- package/dist/browser/PlaywrightScenarioBrowser.js +139 -39
- package/dist/browser/PlaywrightScenarioEvents.js +1 -1
- package/dist/browser/PlaywrightScenarioSession.js +39 -22
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/assets/ScriptCaptureAdapters.js +1 -1
- package/dist/browser/history/CaptureFailures.js +41 -1
- package/dist/browser/history/CaptureRelease.js +5 -0
- package/dist/browser/history/HarCaptureAdapter.js +3 -3
- package/dist/browser/history/HarJson.js +3 -2
- package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
- package/dist/browser/history/MitmproxyCaptureAdapter.js +4 -2
- package/dist/catalogIdentity.js +0 -1
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/analysisViewCommands.js +36 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/artifactCommands.js +11 -12
- package/dist/cli/coreAnalysisCommands.js +3 -3
- package/dist/cli/coreBinaryCommands.js +100 -37
- package/dist/cli/coreNativeCommands.js +9 -10
- package/dist/cli/electronCommands.js +10 -9
- package/dist/cli/interactiveSetup.js +6 -6
- package/dist/cli/javascriptApplicationAnalysis.js +7 -3
- package/dist/cli/jsonOutput.js +4 -99
- package/dist/cli/managedCommands.js +7 -8
- package/dist/cli/nativeCallCommands.js +3 -5
- package/dist/cli/omittableDefaults.js +50 -0
- package/dist/cli/processCommands.js +3 -2
- package/dist/cli/setupCommands.js +16 -15
- package/dist/cli/utilityCommands.js +9 -9
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +18 -9
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +1 -1
- package/dist/cliJsonInput.js +24 -5
- package/dist/cliOutput.js +0 -38
- package/dist/composition/auxiliaryAnalysisProviders.js +27 -23
- package/dist/composition/binary.js +9 -9
- package/dist/composition/browserScenario.js +2 -1
- package/dist/composition/directAnalysis.js +20 -13
- package/dist/composition/electronScenario.js +1 -1
- package/dist/composition/optionalObservationProviders.js +12 -7
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraStartupTimeout.js +12 -0
- package/dist/config/homeDirectory.js +12 -0
- package/dist/config/mcpResponseBudget.js +30 -0
- package/dist/config/parseConfig.js +8 -3
- package/dist/config/parsers.js +19 -22
- package/dist/contracts/analysisViewToolContracts.js +56 -0
- package/dist/contracts/applicationToolContracts.js +5 -4
- package/dist/contracts/artifactComparisonExample.js +2 -2
- package/dist/contracts/artifactToolContracts.js +1 -1
- package/dist/contracts/browserScenarioToolContracts.js +1 -1
- package/dist/contracts/browserToolContracts.js +19 -15
- package/dist/contracts/enhancedInputs.js +7 -5
- package/dist/contracts/enhancedToolContracts.js +7 -6
- package/dist/contracts/evm/evmToolContracts.js +1 -1
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/inputSchemaPresentation.js +90 -0
- package/dist/contracts/investigationExamples.js +4 -3
- package/dist/contracts/javascript/electronToolContracts.js +2 -2
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +0 -20
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +245 -0
- package/dist/contracts/javascript/javascriptRuntimeObservationToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +7 -14
- package/dist/contracts/managed/managedWorkflowToolContracts.js +1 -1
- package/dist/contracts/mobileApplicationGraphExamples.js +3 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +1 -1
- package/dist/contracts/native/nativeToolContracts.js +5 -3
- package/dist/contracts/officialToolContracts.js +16 -16
- package/dist/contracts/promptContracts.js +5 -5
- package/dist/contracts/providerSelection.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +3 -7
- package/dist/contracts/sessionStatusContract.js +2 -4
- package/dist/contracts/sessionToolContracts.js +18 -8
- package/dist/contracts/sessionToolSchemas.js +3 -19
- package/dist/contracts/toolContractExamples.js +0 -1
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +2 -0
- package/dist/contracts/toolEffects.js +1 -1
- package/dist/contracts/toolOutputSchemaGroups.js +160 -115
- package/dist/contracts/toolOutputSchemaPrimitives.js +28 -20
- package/dist/contracts/toolSchemaMetadata.js +41 -33
- package/dist/contracts/webNetworkCaptureToolContracts.js +2 -2
- package/dist/contracts/webRuntimeToolContracts.js +1 -1
- package/dist/contracts/webScriptToolContracts.js +1 -1
- package/dist/doctorRuntime.js +7 -5
- package/dist/domain/analysisErrorBase.js +8 -3
- package/dist/domain/analysisErrorCore.js +6 -1
- package/dist/domain/analysisErrorPresentation.js +90 -20
- package/dist/domain/analysisErrorProjection.js +130 -32
- package/dist/domain/analysisSnapshot.js +29 -31
- package/dist/domain/analysisView/analysisView.js +243 -0
- package/dist/domain/analysisView/analysisViewCoverage.js +19 -0
- package/dist/domain/analysisView/binaryLayoutView.js +159 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +238 -0
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +18 -10
- package/dist/domain/apple/appleApplication.js +42 -15
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dylibResolution.js +130 -12
- package/dist/domain/apple/dylibResolutionFindings.js +9 -7
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -14
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +35 -3
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactComparison.js +15 -6
- package/dist/domain/artifactGraph.js +16 -3
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +28 -40
- package/dist/domain/artifactOperationError.js +3 -3
- package/dist/domain/artifactPartialObservation.js +1 -0
- package/dist/domain/artifactPathSyntax.js +49 -0
- package/dist/domain/binaryTarget.js +39 -13
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCaptureComparison.js +13 -49
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserNetworkEvidence.js +10 -4
- package/dist/domain/browserObservation.js +0 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +14 -3
- package/dist/domain/browserScenario.js +0 -1
- package/dist/domain/browserScenarioCapture.js +1 -2
- package/dist/domain/browserScenarioDiff.js +0 -2
- package/dist/domain/browserScenarioDiffEvidence.js +0 -12
- package/dist/domain/browserScenarioDiffValues.js +2 -2
- package/dist/domain/browserScenarioValues.js +5 -10
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPath.js +8 -9
- package/dist/domain/callPathSchemas.js +2 -2
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +9 -9
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/completionLedgerGeneration.js +2 -1
- package/dist/domain/configurationErrors.js +13 -1
- package/dist/domain/conformancePackage.js +4 -3
- package/dist/domain/evidence.js +65 -36
- package/dist/domain/evidenceBundle.js +47 -8
- package/dist/domain/evidenceCompletionLedger.js +2 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/explicitSensitiveFailure.js +17 -1
- package/dist/domain/firmware/firmwareAnalysis.js +6 -7
- package/dist/domain/functionComparison.js +4 -5
- package/dist/domain/functionComparisonDimensions.js +120 -87
- package/dist/domain/functionComparisonNormalization.js +23 -34
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/functionComparisonSchemas.js +2 -8
- package/dist/domain/functionDossierEvidence.js +2 -37
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +47 -64
- package/dist/domain/javascript/electronObservation.js +14 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +10 -9
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +2 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +39 -3
- package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +9 -2
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +5 -2
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +2 -1
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/{application/javascript/JavaScriptReturnShapeProjection.js → domain/javascript/javascriptExportReturnShapeProjection.js} +4 -4
- package/dist/domain/javascript/javascriptExportShapeComparison.js +7 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonIdentity.js +6 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +29 -1
- package/dist/domain/javascript/javascriptExportShapeSelection.js +5 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +67 -14
- package/dist/domain/javascript/javascriptFeatureSeed.js +20 -0
- package/dist/domain/javascript/javascriptFeatureTraversal.js +0 -1
- package/dist/domain/javascript/javascriptNativeHandoff.js +1 -1
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +0 -1
- package/dist/domain/javascript/javascriptRuntimeObservation.js +10 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +3 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +0 -1
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +106 -5
- package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCalls.js +2 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +23 -6
- package/dist/domain/javascript/javascriptSemanticGraph.js +98 -43
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +77 -20
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +21 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +83 -42
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +18 -21
- package/dist/domain/javascript/javascriptSemanticProjection.js +2 -3
- package/dist/domain/javascript/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticResources.js +1 -1
- package/dist/domain/javascript/javascriptSemanticReturns.js +32 -17
- package/dist/domain/javascript/javascriptSemanticSlots.js +72 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +126 -61
- package/dist/domain/javascript/javascriptSourceMapPaths.js +104 -0
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +16 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -17
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/javascript/sourceToBundleComparison.js +12 -3
- package/dist/domain/javascript/sourceToBundleSignals.js +47 -19
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +90 -6
- package/dist/domain/localPath.js +6 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedArtifact.js +6 -4
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparison.js +2 -9
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -11
- package/dist/domain/managed/managedNativeVerificationMatch.js +9 -3
- package/dist/domain/native/binaryLayout.js +2 -3
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeApiBoundary.js +1 -1
- package/dist/domain/native/nativeCallObservation.js +37 -13
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/native/nativeInstruction.js +7 -0
- package/dist/domain/native/recordedCrash.js +2 -3
- package/dist/domain/offsetDateTime.js +17 -0
- package/dist/domain/process/processCapture.js +21 -16
- package/dist/domain/process/processCaptureCoverage.js +67 -0
- package/dist/domain/process/processCaptureExample.js +2 -1
- package/dist/domain/process/processCaptureParsing.js +1 -34
- package/dist/domain/process/processCaptureValidation.js +81 -13
- package/dist/domain/process/processComparison.js +79 -26
- package/dist/domain/process/processObservation.js +10 -2
- package/dist/domain/process/processScenario.js +35 -12
- package/dist/domain/process/processTraceComparison.js +0 -2
- package/dist/domain/process/processTraceDimensionProjection.js +1 -1
- package/dist/domain/process/processTraceEvaluation.js +15 -11
- package/dist/domain/process/processTraceSpecification.js +3 -4
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +3 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/reconstructionCoverage.js +5 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +2 -1
- package/dist/domain/reconstructionReadinessSchemas.js +2 -1
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +4 -3
- package/dist/domain/referenceSourceGraph.js +20 -21
- package/dist/domain/staticRuntimeCorrelation.js +8 -45
- package/dist/domain/stringPatterns.js +6 -0
- package/dist/domain/swiftSymbolClassification.js +61 -0
- package/dist/domain/symbolAnalysis.js +66 -18
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webCaptureDiff.js +0 -1
- package/dist/domain/webCaptureDiffSchemas.js +6 -3
- package/dist/domain/webEventListeners.js +3 -2
- package/dist/domain/webExecution.js +3 -2
- package/dist/domain/webRuntime.js +19 -7
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/dotnet/ManagedArtifactInspector.js +2 -19
- package/dist/dotnet/ManagedMemberInspector.js +12 -18
- package/dist/dotnet/ManagedMemberInspectorCore.js +47 -44
- package/dist/dotnet/ManagedMemberRows.js +75 -62
- package/dist/dotnet/ManagedMetadataInventory.js +16 -22
- package/dist/dotnet/ManagedMethodBodyReader.js +4 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +109 -94
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +12 -21
- package/dist/dotnet/ManagedReaderFailure.js +16 -0
- package/dist/dotnet/ManagedStaticProvider.js +3 -5
- package/dist/evaluation/AgentEvaluationFixtures.js +250 -0
- package/dist/evaluation/AgentEvaluationReport.js +28 -0
- package/dist/evaluation/CodexAgentEval.js +12 -8
- package/dist/evaluation/KnownAnswerEvaluation.js +281 -0
- package/dist/evm/EvmoleInterfaceProvider.js +2 -1
- package/dist/firmware/FirmwareCommand.js +9 -5
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/firmware/FirmwareProvider.js +4 -4
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +7 -5
- package/dist/ghidra/GhidraClient.js +126 -34
- package/dist/ghidra/GhidraClientStartup.js +0 -2
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraDoctor.js +6 -5
- package/dist/ghidra/GhidraFunctionValues.js +13 -12
- package/dist/ghidra/GhidraInstallation.js +58 -33
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +66 -0
- package/dist/ghidra/GhidraLauncher.js +47 -22
- package/dist/ghidra/GhidraProvider.js +6 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +20 -2
- package/dist/ghidra/GhidraProviderClient.js +36 -15
- package/dist/ghidra/GhidraSessionError.js +13 -7
- package/dist/ghidra/GhidraSessionRoot.js +39 -0
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +17 -10
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +8 -2
- package/dist/hopper/BridgeLauncher.js +65 -56
- package/dist/hopper/HopperAnalysisProfile.js +65 -12
- package/dist/hopper/HopperCleanup.js +63 -22
- package/dist/hopper/HopperClient.js +288 -59
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +197 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +71 -19
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +134 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +133 -49
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -0
- package/dist/ida/IdaConfiguration.js +8 -3
- package/dist/ida/IdaInput.js +1 -7
- package/dist/ida/IdaMcpConnection.js +8 -4
- package/dist/ida/IdaOperationRunner.js +3 -3
- package/dist/ida/IdaProvider.js +8 -12
- package/dist/ida/IdaSessionClient.js +20 -18
- package/dist/ida/IdaWorkspace.js +12 -13
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +9 -4
- package/dist/inspector/V8InspectorProvider.js +82 -36
- package/dist/javascript/recovery/WakaruCommand.js +7 -2
- package/dist/javascript/recovery/WakaruExecution.js +5 -2
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/main/shutdown.js +11 -3
- package/dist/main/startup.js +9 -2
- package/dist/main/transport.js +22 -2
- package/dist/main.js +11 -18
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +48 -22
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +87 -88
- package/dist/native/LldbCallTracer.js +372 -103
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +62 -3
- package/dist/native/NativeMacOSProvider.js +122 -31
- package/dist/native/NativeUiHelperRuntime.js +11 -2
- package/dist/native/NativeUiObservation.js +2 -2
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
- package/dist/native/pwntools/PwntoolsDecoder.js +2 -1
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
- package/dist/process/DarwinProcessRunTokenReader.js +23 -10
- package/dist/process/ExecFileOutput.js +108 -6
- package/dist/process/OwnedCommand.js +7 -2
- package/dist/process/PrivateRuntimeRoot.js +10 -5
- package/dist/process/ProcessOwnership.js +204 -57
- package/dist/process/ProcessOwnershipObservation.js +60 -9
- package/dist/process/ProviderProcess.js +39 -10
- package/dist/process/capture/FilesystemSnapshot.js +50 -13
- package/dist/process/capture/ProcessCaptureError.js +15 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +235 -81
- package/dist/process/capture/ProcessFilesystemEffects.js +33 -3
- package/dist/process/capture/ProcessHarness.js +21 -25
- package/dist/process/capture/ProcessNormalization.js +20 -2
- package/dist/process/capture/ProcessSampling.js +25 -2
- package/dist/process/capture/TerminalRenderer.js +14 -0
- package/dist/process/snapshotEnvironment.js +14 -0
- package/dist/server/EvidenceMcpServer.js +157 -0
- package/dist/server/createServer.js +61 -41
- package/dist/server/mcpClientMetadata.js +12 -5
- package/dist/server/promptCompletion.js +3 -8
- package/dist/server/registerAnalysisViewTool.js +15 -0
- package/dist/server/registerAndroidTools.js +2 -5
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -5
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +4 -5
- package/dist/server/registerApplicationTools/coverage.js +1 -2
- package/dist/server/registerApplicationTools/helpers.js +1 -4
- package/dist/server/registerApplicationTools/obligationLedger.js +4 -5
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -4
- package/dist/server/registerApplicationTools/traceFeature.js +4 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +13 -10
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -5
- package/dist/server/registerBrowserScenarioTool.js +3 -6
- package/dist/server/registerBrowserTools.js +13 -18
- package/dist/server/registerBundleComparisonTool.js +5 -7
- package/dist/server/registerCloseLifecycleTool.js +9 -20
- package/dist/server/registerElectronTools.js +10 -15
- package/dist/server/registerEnhancedTools.js +36 -77
- package/dist/server/registerEvidenceTools.js +3 -6
- package/dist/server/registerEvmTools.js +2 -5
- package/dist/server/registerFirmwareTools.js +2 -5
- package/dist/server/registerFunctionComparisonTool.js +15 -12
- package/dist/server/registerInvestigationTools.js +16 -17
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -5
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -8
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +5 -8
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -7
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +6 -9
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +6 -9
- package/dist/server/registerOfficialTools.js +4 -21
- package/dist/server/registerProcessComparisonTool.js +74 -48
- package/dist/server/registerRecordedCrashTools.js +2 -5
- package/dist/server/registerSessionRecordTools.js +19 -24
- package/dist/server/registerSessionStatusTool.js +19 -6
- package/dist/server/registerSessionTools.js +20 -18
- package/dist/server/registerWebModuleTool.js +2 -5
- package/dist/server/registerWebNetworkCaptureTool.js +2 -5
- package/dist/server/registerWebRuntimeTools.js +4 -9
- package/dist/server/registerWebScriptTool.js +2 -5
- package/dist/server/registerWebSourceLocationTool.js +2 -5
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +0 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +75 -51
- package/dist/server/toolResultEncoding.js +34 -0
- package/dist/windows/WindowsNativeLoader.js +1 -0
- package/dist/windows/WindowsOwnedProcess.js +60 -15
- package/dist/windows/WindowsPrivateRuntime.js +7 -8
- package/install.sh +1 -1
- package/native/windows/README.md +3 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +44 -30
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +3 -6
- package/skills/reverse-engineer-anything/SKILL.md +12 -3
- package/skills/reverse-engineer-anything/references/android-applications.md +6 -3
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +20 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/config.js +0 -1
- package/dist/contracts/browserCaptureToolInputSchema.js +0 -43
- package/dist/contracts/process/processCaptureExample.js +0 -2
- package/dist/contracts/toolOutputSchemas.js +0 -2
- package/dist/ghidra/GhidraDefaults.js +0 -2
- package/dist/main/reload.js +0 -12
- package/dist/main/state.js +0 -3
- package/dist/server/sessionToolPolicies.js +0 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { analysisErrorWithCleanupFailure } from "../application/binary/AnalysisClientCleanup.js";
|
|
1
2
|
import { fileURLToPath } from "node:url";
|
|
2
3
|
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
3
|
-
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisTimeoutError, } from "../domain/analysisErrorCore.js";
|
|
4
|
+
import { AnalysisCancelledError, AnalysisArtifactChangedError, AnalysisAccessDeniedError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisResourceConstraintError, AnalysisTimeoutError, } from "../domain/analysisErrorCore.js";
|
|
4
5
|
import {} from "../domain/analysisErrorBase.js";
|
|
5
6
|
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
6
7
|
import { err, ok } from "../domain/result.js";
|
|
7
8
|
import { GhidraClient } from "./GhidraClient.js";
|
|
8
|
-
import { GHIDRA_STARTUP_TIMEOUT_MS } from "./GhidraDefaults.js";
|
|
9
9
|
import { isGhidraFunctionOperation, parseGhidraFunctionInput, parseGhidraFunctionResult, } from "./GhidraFunctionValues.js";
|
|
10
10
|
import { isGhidraInventoryOperation, parseGhidraInventoryInput, parseGhidraInventoryResult, } from "./GhidraInventoryValues.js";
|
|
11
11
|
import { ghidraInstallationDiagnostics, } from "./GhidraInstallation.js";
|
|
@@ -55,12 +55,12 @@ export const createGhidraProviderClient = (input) => {
|
|
|
55
55
|
]
|
|
56
56
|
: [];
|
|
57
57
|
const client = clientFactory({
|
|
58
|
+
startupTimeoutMs: config.ghidraStartupTimeoutMs,
|
|
58
59
|
platform: installation.platform,
|
|
59
60
|
launcher: new GhidraHeadlessLauncher({
|
|
61
|
+
environment: input.environment,
|
|
60
62
|
analyzeHeadlessPath: prerequisites.value.analyzeHeadlessPath,
|
|
61
|
-
|
|
62
|
-
? {}
|
|
63
|
-
: { javaHome: config.ghidraJavaHome }),
|
|
63
|
+
javaHome: prerequisites.value.javaHome,
|
|
64
64
|
bridgeScriptPath: fileURLToPath(new URL("../../bridge/ghidra/ReaGhidraBridge.java", import.meta.url)),
|
|
65
65
|
...(target.format === "dos-mz" ? { dosMz: true } : {}),
|
|
66
66
|
...(target.format === "dos-com" ? { dosCom: true } : {}),
|
|
@@ -89,8 +89,10 @@ export const createGhidraProviderClient = (input) => {
|
|
|
89
89
|
extensionFailure = ghidraExtensionFailure(extensions, info.analysis_extensions ?? [], operation);
|
|
90
90
|
if (extensionFailure === undefined)
|
|
91
91
|
return undefined;
|
|
92
|
-
await client.close();
|
|
93
|
-
return
|
|
92
|
+
const closed = await client.close();
|
|
93
|
+
return closed.ok
|
|
94
|
+
? extensionFailure
|
|
95
|
+
: analysisErrorWithCleanupFailure(extensionFailure, closed.error, operation);
|
|
94
96
|
};
|
|
95
97
|
const releaseLimitation = unverifiedGhidraBuildLimitation(prerequisites.value.providerVersion);
|
|
96
98
|
const sessionLimitations = [
|
|
@@ -110,7 +112,7 @@ export const createGhidraProviderClient = (input) => {
|
|
|
110
112
|
if (operation === "health") {
|
|
111
113
|
const started = await client.start(options?.signal);
|
|
112
114
|
if (!started.ok)
|
|
113
|
-
return err(projectSessionError(operation, started.error));
|
|
115
|
+
return err(projectSessionError(operation, started.error, config.ghidraStartupTimeoutMs));
|
|
114
116
|
const failed = await checkExtensions(operation, started.value);
|
|
115
117
|
if (failed !== undefined)
|
|
116
118
|
return err(failed);
|
|
@@ -127,14 +129,14 @@ export const createGhidraProviderClient = (input) => {
|
|
|
127
129
|
if (extensions.length > 0) {
|
|
128
130
|
const started = await client.start(options?.signal);
|
|
129
131
|
if (!started.ok)
|
|
130
|
-
return err(projectSessionError(operation, started.error));
|
|
132
|
+
return err(projectSessionError(operation, started.error, config.ghidraStartupTimeoutMs));
|
|
131
133
|
const failed = await checkExtensions(operation, started.value);
|
|
132
134
|
if (failed !== undefined)
|
|
133
135
|
return err(failed);
|
|
134
136
|
}
|
|
135
137
|
const called = await client.callTool(operation, input.value, options?.signal === undefined ? {} : { signal: options.signal });
|
|
136
138
|
if (!called.ok)
|
|
137
|
-
return err(projectSessionError(operation, called.error));
|
|
139
|
+
return err(projectSessionError(operation, called.error, config.ghidraStartupTimeoutMs));
|
|
138
140
|
const result = isGhidraFunctionOperation(operation)
|
|
139
141
|
? parseGhidraFunctionResult(operation, called.value)
|
|
140
142
|
: parseGhidraInventoryResult(operation, called.value);
|
|
@@ -142,7 +144,7 @@ export const createGhidraProviderClient = (input) => {
|
|
|
142
144
|
return result;
|
|
143
145
|
let normalized = result.value;
|
|
144
146
|
if (operation === "inspect_native_load_image") {
|
|
145
|
-
const attested = await attestGhidraNativeLoadImage(target, operation, result.value, client, (failure) => projectSessionError(operation, failure));
|
|
147
|
+
const attested = await attestGhidraNativeLoadImage(target, operation, result.value, client, (failure) => projectSessionError(operation, failure, config.ghidraStartupTimeoutMs));
|
|
146
148
|
if (!attested.ok)
|
|
147
149
|
return attested;
|
|
148
150
|
normalized = attested.value;
|
|
@@ -176,15 +178,26 @@ const ghidraClientPrerequisites = (target, profile, installation) => {
|
|
|
176
178
|
return err(new ProviderAdapterError("ghidra", "health"));
|
|
177
179
|
return ok({
|
|
178
180
|
analyzeHeadlessPath: installation.analyzeHeadlessPath,
|
|
181
|
+
javaHome: installation.javaHome,
|
|
179
182
|
providerVersion: installation.providerVersion,
|
|
180
183
|
profile,
|
|
181
184
|
});
|
|
182
185
|
};
|
|
183
186
|
const unavailableClient = (failure) => ({
|
|
184
187
|
execute: () => Promise.resolve(err(failure)),
|
|
185
|
-
close: () => Promise.resolve(),
|
|
188
|
+
close: () => Promise.resolve(ok(null)),
|
|
186
189
|
});
|
|
187
|
-
const projectSessionError = (operation, failure) => {
|
|
190
|
+
const projectSessionError = (operation, failure, startupTimeoutMs) => {
|
|
191
|
+
const primary = projectPrimarySessionError(operation, failure, startupTimeoutMs);
|
|
192
|
+
return failure.cleanupFailure === undefined
|
|
193
|
+
? primary
|
|
194
|
+
: analysisErrorWithCleanupFailure(primary, failure.cleanupFailure, operation);
|
|
195
|
+
};
|
|
196
|
+
const projectPrimarySessionError = (operation, failure, startupTimeoutMs) => {
|
|
197
|
+
if (failure.cause instanceof AnalysisAccessDeniedError)
|
|
198
|
+
return new AnalysisAccessDeniedError(operation, failure.cause.path, failure.cause.systemCode, { cause: failure });
|
|
199
|
+
if (failure.cause instanceof AnalysisArtifactChangedError)
|
|
200
|
+
return new AnalysisArtifactChangedError(operation, failure.cause.path, failure.cause.reason, { cause: failure });
|
|
188
201
|
if (operation === "annotate_native_function" &&
|
|
189
202
|
failure.kind === "remote" &&
|
|
190
203
|
failure.remoteCode === "invalid_function_name")
|
|
@@ -194,12 +207,20 @@ const projectSessionError = (operation, failure) => {
|
|
|
194
207
|
if (failure.kind === "cancelled")
|
|
195
208
|
return new AnalysisCancelledError(operation);
|
|
196
209
|
if (failure.kind === "timeout" || failure.kind === "analysis_timeout")
|
|
197
|
-
return new AnalysisTimeoutError(operation, failure.timeoutMs ??
|
|
210
|
+
return new AnalysisTimeoutError(operation, failure.timeoutMs ?? startupTimeoutMs);
|
|
198
211
|
if (failure.kind === "remote" && failure.remoteCode === "decompile_cancelled")
|
|
199
212
|
return new AnalysisCancelledError(operation);
|
|
213
|
+
if (failure.kind === "remote" &&
|
|
214
|
+
failure.remoteCode === "regex_stack_exhausted")
|
|
215
|
+
return new AnalysisResourceConstraintError(operation, "memory", failure.message, null, {
|
|
216
|
+
cause: failure,
|
|
217
|
+
remediationAction: "Retry this search in literal mode or simplify the regex. The active analysis session and annotations remain available.",
|
|
218
|
+
});
|
|
200
219
|
if (failure.kind === "remote" &&
|
|
201
220
|
["invalid_request", "not_found", "ambiguous"].includes(failure.remoteCode ?? ""))
|
|
202
|
-
return new AnalysisInputError(operation, { cause: failure }
|
|
221
|
+
return new AnalysisInputError(operation, { cause: failure }, [
|
|
222
|
+
{ path: [], reason: "invalid_value", message: failure.message },
|
|
223
|
+
]);
|
|
203
224
|
if (failure.kind === "remote" && failure.remoteCode === "method_unavailable")
|
|
204
225
|
return new AnalysisCapabilityUnavailableError("ghidra", operation, failure.message);
|
|
205
226
|
return new ProviderAdapterError("ghidra", operation, {
|
|
@@ -4,6 +4,7 @@ export class GhidraSessionError extends Error {
|
|
|
4
4
|
diagnostics;
|
|
5
5
|
timeoutMs;
|
|
6
6
|
remoteCode;
|
|
7
|
+
cleanupFailure;
|
|
7
8
|
constructor(kind, message, diagnostics = {}, options = {}) {
|
|
8
9
|
super(message, options);
|
|
9
10
|
this.kind = kind;
|
|
@@ -11,16 +12,21 @@ export class GhidraSessionError extends Error {
|
|
|
11
12
|
this.diagnostics = structuredClone(diagnostics);
|
|
12
13
|
this.timeoutMs = options.timeoutMs;
|
|
13
14
|
this.remoteCode = options.remoteCode;
|
|
15
|
+
this.cleanupFailure = options.cleanupFailure;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
/** Build a session failure while preserving bounded remote failure metadata. */
|
|
17
|
-
const createGhidraSessionError = (failure) => new GhidraSessionError(failure.kind, failure.message,
|
|
18
|
-
|
|
19
|
-
:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
const createGhidraSessionError = (failure) => new GhidraSessionError(failure.kind, failure.message, {
|
|
20
|
+
...failure.diagnostics,
|
|
21
|
+
failure_kind: failure.kind,
|
|
22
|
+
failure_message: failure.message,
|
|
23
|
+
...(failure.remoteCode === undefined
|
|
24
|
+
? {}
|
|
25
|
+
: {
|
|
26
|
+
remote_code: failure.redact(failure.remoteCode),
|
|
27
|
+
remote_message: failure.message,
|
|
28
|
+
}),
|
|
29
|
+
}, {
|
|
24
30
|
...(failure.cause === undefined ? {} : { cause: failure.cause }),
|
|
25
31
|
...(failure.timeoutMs === undefined
|
|
26
32
|
? {}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { dirname, isAbsolute, resolve, sep } from "node:path";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
/** Session roots may not contain a dot-prefixed path element. */
|
|
4
|
+
const hasDotPrefixElement = (directory) => resolve(directory)
|
|
5
|
+
.split(sep)
|
|
6
|
+
.some((element) => element.startsWith("."));
|
|
7
|
+
/** Nearest ancestor of `directory`, inclusive, that has no dot-prefixed element. */
|
|
8
|
+
const nearestSafeAncestor = (directory) => {
|
|
9
|
+
let current = resolve(directory);
|
|
10
|
+
for (;;) {
|
|
11
|
+
if (!hasDotPrefixElement(current))
|
|
12
|
+
return current;
|
|
13
|
+
const parent = dirname(current);
|
|
14
|
+
if (parent === current)
|
|
15
|
+
return undefined;
|
|
16
|
+
current = parent;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Select a session root usable as the parent of a Ghidra project path.
|
|
21
|
+
*
|
|
22
|
+
* Ghidra validates every project path element with `NamingUtilities.checkName`
|
|
23
|
+
* and aborts the headless analyzer on any element that starts with `.`, so an
|
|
24
|
+
* inherited `TMPDIR` such as `~/.cache/<tool>` fails every Ghidra operation
|
|
25
|
+
* with a generic analysis failure. Prefer the inherited base when it is usable,
|
|
26
|
+
* then a dot-free platform temp directory, then the nearest dot-free ancestor.
|
|
27
|
+
*/
|
|
28
|
+
export const ghidraSessionRoot = (options = {}) => {
|
|
29
|
+
const base = resolve(options.base ?? tmpdir());
|
|
30
|
+
if (!hasDotPrefixElement(base))
|
|
31
|
+
return base;
|
|
32
|
+
const platform = options.platform ?? process.platform;
|
|
33
|
+
const fallback = options.fallback ?? (platform === "win32" ? undefined : "/tmp");
|
|
34
|
+
if (fallback !== undefined &&
|
|
35
|
+
isAbsolute(fallback) &&
|
|
36
|
+
!hasDotPrefixElement(fallback))
|
|
37
|
+
return resolve(fallback);
|
|
38
|
+
return nearestSafeAncestor(base) ?? base;
|
|
39
|
+
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { constants
|
|
3
|
-
import {
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { open, rm } from "node:fs/promises";
|
|
4
4
|
import { extname, join } from "node:path";
|
|
5
|
+
import { Transform } from "node:stream";
|
|
6
|
+
import { pipeline } from "node:stream/promises";
|
|
7
|
+
import { AnalysisArtifactChangedError, AnalysisAccessDeniedError, } from "../domain/analysisErrorCore.js";
|
|
5
8
|
import { windowsPrivateRuntime } from "../windows/WindowsPrivateRuntime.js";
|
|
6
9
|
/** Copy one target and require its bytes to match the parsed target identity. */
|
|
7
10
|
export const createGhidraTargetSnapshot = async (sourcePath, runtimeRoot, expectedSha256, options = {}) => {
|
|
@@ -12,29 +15,61 @@ export const createGhidraTargetSnapshot = async (sourcePath, runtimeRoot, expect
|
|
|
12
15
|
if ((options.platform ?? process.platform) === "win32") {
|
|
13
16
|
const observed = await windowsPrivateRuntime(runtimeRoot).snapshot(sourcePath, `target-${expectedSha256.slice(0, 12)}${suffix}`, options.signal);
|
|
14
17
|
if (observed.sha256 !== expectedSha256)
|
|
15
|
-
throw new
|
|
18
|
+
throw new AnalysisArtifactChangedError("open_binary", sourcePath, `Ghidra target snapshot digest mismatch: expected ${expectedSha256}, observed ${observed.sha256}`);
|
|
16
19
|
return {
|
|
17
20
|
path: snapshotPath,
|
|
18
21
|
sha256: observed.sha256,
|
|
19
22
|
admission: { source: observed.source, snapshot: observed.snapshot },
|
|
20
23
|
};
|
|
21
24
|
}
|
|
25
|
+
let source;
|
|
26
|
+
let destination;
|
|
22
27
|
try {
|
|
23
|
-
await
|
|
24
|
-
await
|
|
28
|
+
source = await openSnapshotSource(sourcePath);
|
|
29
|
+
if (!(await source.stat()).isFile())
|
|
30
|
+
throw new AnalysisArtifactChangedError("open_binary", sourcePath, "The selected Ghidra source is no longer a regular file");
|
|
31
|
+
destination = await open(snapshotPath, "wx", 0o600);
|
|
32
|
+
await destination.chmod(0o600);
|
|
25
33
|
const hash = createHash("sha256");
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
const digest = new Transform({
|
|
35
|
+
transform(chunk, _encoding, done) {
|
|
36
|
+
if (!Buffer.isBuffer(chunk)) {
|
|
37
|
+
done(new TypeError("Ghidra snapshot stream must contain bytes"));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
hash.update(chunk);
|
|
41
|
+
done(null, chunk);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
await pipeline(source.createReadStream(), digest, destination.createWriteStream(), options.signal === undefined ? {} : { signal: options.signal });
|
|
28
45
|
const observedSha256 = hash.digest("hex");
|
|
29
46
|
if (observedSha256 !== expectedSha256)
|
|
30
|
-
throw new
|
|
47
|
+
throw new AnalysisArtifactChangedError("open_binary", sourcePath, `Ghidra target snapshot digest mismatch: expected ${expectedSha256}, observed ${observedSha256}`);
|
|
31
48
|
return { path: snapshotPath, sha256: observedSha256 };
|
|
32
49
|
}
|
|
33
50
|
catch (cause) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
if (destination !== undefined)
|
|
52
|
+
await rm(snapshotPath, { force: true }).catch((cause) => {
|
|
53
|
+
// best-effort cleanup: snapshot removal must not mask the copy failure.
|
|
54
|
+
void cause;
|
|
55
|
+
});
|
|
56
|
+
throw cause;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await Promise.all([source?.close(), destination?.close()]);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const openSnapshotSource = async (path) => {
|
|
63
|
+
try {
|
|
64
|
+
// A path replaced by a FIFO must not block startup before its type is checked.
|
|
65
|
+
return await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
66
|
+
}
|
|
67
|
+
catch (cause) {
|
|
68
|
+
const code = cause instanceof Error && "code" in cause ? cause.code : undefined;
|
|
69
|
+
if (code === "EACCES" || code === "EPERM")
|
|
70
|
+
throw new AnalysisAccessDeniedError("open_binary", path, code, { cause });
|
|
71
|
+
if (code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP")
|
|
72
|
+
throw new AnalysisArtifactChangedError("open_binary", path, `The selected Ghidra source could not be opened (${code})`, { cause });
|
|
38
73
|
throw cause;
|
|
39
74
|
}
|
|
40
75
|
};
|
|
@@ -1,7 +1,27 @@
|
|
|
1
1
|
import { access, open } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
|
|
2
4
|
import { readWindowsPrivateRuntimeFile } from "../windows/WindowsPrivateRuntime.js";
|
|
3
5
|
import { err, ok } from "../domain/result.js";
|
|
4
6
|
import { GhidraSessionError } from "./GhidraSessionError.js";
|
|
7
|
+
/** Allocate an endpoint that fits the host's Unix sockaddr without moving the project. */
|
|
8
|
+
export const createGhidraEndpoint = async (runtimeRoot, transport, platform) => {
|
|
9
|
+
const path = join(runtimeRoot, transport === "unix-socket" ? "bridge.sock" : "bridge-endpoint.json");
|
|
10
|
+
// sockaddr_un includes a terminating NUL: macOS has 104 bytes, Linux 108.
|
|
11
|
+
const maximumPathBytes = platform === "darwin" ? 103 : 107;
|
|
12
|
+
if (transport !== "unix-socket" ||
|
|
13
|
+
Buffer.byteLength(path, "utf8") <= maximumPathBytes)
|
|
14
|
+
return { endpoint: { transport, path } };
|
|
15
|
+
const socketRoot = await PrivateRuntimeRoot.create({
|
|
16
|
+
parent: "/tmp",
|
|
17
|
+
prefix: "rea-ghidra-socket-",
|
|
18
|
+
platform,
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
endpoint: { transport, path: join(socketRoot.path, "s") },
|
|
22
|
+
socketRoot,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
5
25
|
/** Observe a ready endpoint, returning null while its bridge is not listening. */
|
|
6
26
|
export const observeGhidraEndpoint = async (endpoint) => {
|
|
7
27
|
if (endpoint.transport === "unix-socket") {
|
|
@@ -3,7 +3,7 @@ import { constants } from "node:fs";
|
|
|
3
3
|
import { open, realpath, writeFile, mkdir } from "node:fs/promises";
|
|
4
4
|
import { isAbsolute, join } from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { AnalysisCancelledError } from "../../domain/analysisErrorCore.js";
|
|
6
|
+
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisUnsupportedTargetError, } from "../../domain/analysisErrorCore.js";
|
|
7
7
|
import { ProviderAdapterError } from "../../domain/providerAdapterError.js";
|
|
8
8
|
import { jsonObjectSchema } from "../../domain/jsonValue.js";
|
|
9
9
|
import { err, ok } from "../../domain/result.js";
|
|
@@ -11,7 +11,7 @@ import { nativeAotAdapter } from "./nativeaot/NativeAotAdapter.js";
|
|
|
11
11
|
const digest = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
12
12
|
/** Exact executable extension artifact committed before the session starts. */
|
|
13
13
|
export const ghidraExtensionSchema = z.strictObject({
|
|
14
|
-
id: z.string().regex(/^[a-z][a-z0-9
|
|
14
|
+
id: z.string().regex(/^[a-z][a-z0-9\x2d]*$/u),
|
|
15
15
|
path: z.string().refine(isAbsolute, "Extension path must be absolute"),
|
|
16
16
|
configured_path: z
|
|
17
17
|
.string()
|
|
@@ -70,11 +70,9 @@ export const resolveGhidraExtensions = async (config, target, platform, signal)
|
|
|
70
70
|
const configured = adapter.configuredPath(config);
|
|
71
71
|
if (configured === undefined)
|
|
72
72
|
continue;
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
75
|
-
return err(
|
|
76
|
-
diagnostics: { extension: adapter.id, reason, path: configured },
|
|
77
|
-
}));
|
|
73
|
+
const refusal = adapter.unsupportedReason(target, platform);
|
|
74
|
+
if (refusal !== null)
|
|
75
|
+
return err(extensionRefusalError(refusal, target));
|
|
78
76
|
try {
|
|
79
77
|
const path = await realpath(configured);
|
|
80
78
|
const bytes = await readJar(path);
|
|
@@ -115,12 +113,21 @@ export const validateGhidraExtensionProfile = (extensions, config, target, platf
|
|
|
115
113
|
adapter.entryClass !== extension.entry_class ||
|
|
116
114
|
adapter.configuredPath(config) !== extension.configured_path)
|
|
117
115
|
return `Ghidra extension profile lacks matching explicit local configuration: ${extension.id}`;
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
return reason;
|
|
116
|
+
const refusal = adapter.unsupportedReason(target, platform);
|
|
117
|
+
if (refusal !== null)
|
|
118
|
+
return refusal.reason;
|
|
121
119
|
}
|
|
122
120
|
return null;
|
|
123
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* A deliberate host or target refusal is not an execution failure: retrying
|
|
124
|
+
* cannot change it, and its reason already names the remedy.
|
|
125
|
+
*/
|
|
126
|
+
const extensionRefusalError = (refusal, target) => refusal.constraint === "host"
|
|
127
|
+
? new AnalysisCapabilityUnavailableError("ghidra", "resolve_analysis_profile", refusal.reason, { userMessage: refusal.reason })
|
|
128
|
+
: new AnalysisUnsupportedTargetError("resolve_analysis_profile", target.path, refusal.reason,
|
|
129
|
+
// The reason names the workflows that remain available.
|
|
130
|
+
{ remediationAction: refusal.reason });
|
|
124
131
|
/** Snapshot committed extension bytes into the private runtime before Java loads them. */
|
|
125
132
|
export const snapshotGhidraExtensions = async (extensions, runtimeRoot) => {
|
|
126
133
|
if (extensions.length === 0)
|
|
@@ -5,11 +5,17 @@ export const nativeAotAdapter = {
|
|
|
5
5
|
entryClass: "rea.extensions.nativeaot.NativeAotExtension",
|
|
6
6
|
configuredPath: (config) => config.ghidraNativeAotJar,
|
|
7
7
|
unsupportedReason: (target, platform) => platform !== "linux"
|
|
8
|
-
?
|
|
8
|
+
? {
|
|
9
|
+
constraint: "host",
|
|
10
|
+
reason: "NativeAOT recovery is verified on Linux only; omit REA_GHIDRA_NATIVEAOT_JAR for ordinary native analysis.",
|
|
11
|
+
}
|
|
9
12
|
: !["elf", "pe"].includes(target.format) ||
|
|
10
13
|
target.architecture !== "x86_64" ||
|
|
11
14
|
target.managed === true
|
|
12
|
-
?
|
|
15
|
+
? {
|
|
16
|
+
constraint: "target",
|
|
17
|
+
reason: "NativeAOT recovery requires an x86-64 ELF or native PE target on Linux; PE/CLI and ReadyToRun assemblies use inspect_managed_artifact; omit REA_GHIDRA_NATIVEAOT_JAR for ordinary native analysis.",
|
|
18
|
+
}
|
|
13
19
|
: null,
|
|
14
20
|
validate: validateNativeAotReport,
|
|
15
21
|
limitations: [
|
|
@@ -9,8 +9,8 @@ import { execFileOutput } from "../process/ExecFileOutput.js";
|
|
|
9
9
|
import { spawnOwnedProviderProcess, } from "../process/ProviderProcess.js";
|
|
10
10
|
import { waitForAbortableDelay } from "../process/ProviderDeadline.js";
|
|
11
11
|
import { selectLinuxPrivateDisplayStrategy, } from "./LinuxPrivateDisplayProbe.js";
|
|
12
|
-
import
|
|
13
|
-
import { acquireHopperTargetLease } from "./HopperTargetLease.js";
|
|
12
|
+
import { prepareHopperMachOImage, } from "./HopperMachOImage.js";
|
|
13
|
+
import { acquireHopperTargetLease, acquireLinuxHopperApplicationLease, } from "./HopperTargetLease.js";
|
|
14
14
|
const execFileAsync = promisify(execFile);
|
|
15
15
|
const HOPPER_BACKGROUND_STARTUP_MS = 5_000;
|
|
16
16
|
/**
|
|
@@ -35,20 +35,28 @@ export class HopperApplicationLauncher {
|
|
|
35
35
|
this.dependencies = dependencies;
|
|
36
36
|
}
|
|
37
37
|
async launch(session, options = {}) {
|
|
38
|
-
const leaseResult = await this.#
|
|
38
|
+
const leaseResult = await this.#acquireLaunchLease(session.runId);
|
|
39
39
|
if (!leaseResult.ok)
|
|
40
40
|
return leaseResult;
|
|
41
41
|
const lease = leaseResult.value;
|
|
42
42
|
let leaseTransferred = false;
|
|
43
43
|
try {
|
|
44
|
+
let loadedPath = this.options.targetPath;
|
|
45
|
+
if (this.options.preparedImage !== undefined) {
|
|
46
|
+
const prepared = await prepareHopperMachOImage(this.options.targetPath, this.options.preparedImage.sourceSha256, this.options.preparedImage.image, join(session.directory, "image.macho"), options.signal);
|
|
47
|
+
if (!prepared.ok)
|
|
48
|
+
return prepared;
|
|
49
|
+
loadedPath = prepared.value;
|
|
50
|
+
}
|
|
44
51
|
const ownsProcessLifetime = usesLinuxDemo(this.options);
|
|
45
|
-
const bootstrap = await this.#writeBootstrap(session, ownsProcessLifetime);
|
|
52
|
+
const bootstrap = await this.#writeBootstrap(session, ownsProcessLifetime, loadedPath);
|
|
46
53
|
if (!bootstrap.ok)
|
|
47
54
|
return bootstrap;
|
|
48
55
|
const launched = await this.#launchPreparedTarget({
|
|
49
56
|
session,
|
|
50
57
|
signal: options.signal,
|
|
51
58
|
bootstrapPath: bootstrap.value,
|
|
59
|
+
loadedPath,
|
|
52
60
|
ownsProcessLifetime,
|
|
53
61
|
lease,
|
|
54
62
|
});
|
|
@@ -69,7 +77,7 @@ export class HopperApplicationLauncher {
|
|
|
69
77
|
"-Y",
|
|
70
78
|
bootstrapPath,
|
|
71
79
|
action,
|
|
72
|
-
|
|
80
|
+
input.loadedPath,
|
|
73
81
|
];
|
|
74
82
|
try {
|
|
75
83
|
if (signal?.aborted === true)
|
|
@@ -77,7 +85,7 @@ export class HopperApplicationLauncher {
|
|
|
77
85
|
const display = await this.#privateDisplay(signal);
|
|
78
86
|
if (!display.ok)
|
|
79
87
|
return err(display.error);
|
|
80
|
-
const prepared = await prepareHopperApplication(this.options.launcherPath, signal);
|
|
88
|
+
const prepared = await prepareHopperApplication(this.options.launcherPath, this.options.environment, signal);
|
|
81
89
|
if (!prepared)
|
|
82
90
|
return err(new HopperCancelledError());
|
|
83
91
|
const linuxDemo = linuxDemoLaunch(this.options, session, argumentsForTarget, display.strategy);
|
|
@@ -92,62 +100,69 @@ export class HopperApplicationLauncher {
|
|
|
92
100
|
});
|
|
93
101
|
if (started === null)
|
|
94
102
|
return err(new HopperCancelledError());
|
|
95
|
-
const cleanup = () => cleanupOwnedProcessGroup(started.ownership)
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
parent_pid: process.pid,
|
|
101
|
-
launcher: linuxDemo?.command ?? this.options.launcherPath,
|
|
102
|
-
created_at: new Date().toISOString(),
|
|
103
|
-
};
|
|
104
|
-
try {
|
|
105
|
-
await writeFileAtomic(join(session.directory, "ownership.json"), `${JSON.stringify(ownership)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
106
|
-
}
|
|
107
|
-
catch (cause) {
|
|
108
|
-
await cleanupOwnedProcessGroup(started.ownership);
|
|
109
|
-
return err(new HopperStartError({ cause }));
|
|
110
|
-
}
|
|
111
|
-
return ok({
|
|
103
|
+
const cleanup = () => cleanupOwnedProcessGroup(started.ownership);
|
|
104
|
+
const ownedLauncher = {
|
|
105
|
+
...(this.options.preparedImage === undefined
|
|
106
|
+
? {}
|
|
107
|
+
: { preparedImagePath: input.loadedPath }),
|
|
112
108
|
process: started.process,
|
|
113
109
|
ownsProcessLifetime: true,
|
|
114
110
|
ownership: started.ownership,
|
|
115
|
-
shutdownMode: ownsProcessLifetime
|
|
116
|
-
? "process-cleanup"
|
|
117
|
-
: "bridge-request",
|
|
118
111
|
cleanup,
|
|
119
|
-
|
|
112
|
+
launcherCommand: linuxDemo?.command ?? this.options.launcherPath,
|
|
113
|
+
...(lease === undefined ? {} : { releaseLease: () => lease.release() }),
|
|
114
|
+
};
|
|
115
|
+
return ownsProcessLifetime
|
|
116
|
+
? ok({
|
|
117
|
+
...ownedLauncher,
|
|
118
|
+
providerLifetime: "launcher-process",
|
|
119
|
+
shutdownMode: "process-cleanup",
|
|
120
|
+
})
|
|
121
|
+
: ok({
|
|
122
|
+
...ownedLauncher,
|
|
123
|
+
providerLifetime: "external-application",
|
|
124
|
+
shutdownMode: "bridge-request",
|
|
125
|
+
});
|
|
120
126
|
}
|
|
121
127
|
catch (cause) {
|
|
122
128
|
return err(hopperLaunchFailure(cause, signal));
|
|
123
129
|
}
|
|
124
130
|
}
|
|
125
|
-
async #
|
|
126
|
-
|
|
131
|
+
async #acquireLaunchLease(runId) {
|
|
132
|
+
const platform = this.dependencies.platform ?? process.platform;
|
|
133
|
+
const applicationLease = platform === "linux" && usesLinuxDemo(this.options);
|
|
134
|
+
if (!applicationLease && platform !== "darwin")
|
|
127
135
|
return ok(undefined);
|
|
128
136
|
try {
|
|
129
|
-
const acquisition =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
const acquisition = applicationLease
|
|
138
|
+
? await (this.dependencies.acquireApplicationLease ??
|
|
139
|
+
acquireLinuxHopperApplicationLease)({ runId })
|
|
140
|
+
: await (this.dependencies.acquireTargetLease ?? acquireHopperTargetLease)({
|
|
141
|
+
targetPath: this.options.targetPath,
|
|
142
|
+
targetKind: this.options.targetKind,
|
|
143
|
+
loaderArgs: this.options.loaderArgs,
|
|
144
|
+
runId,
|
|
145
|
+
});
|
|
135
146
|
if (!acquisition.acquired)
|
|
136
147
|
return err(new HopperStartError({
|
|
137
148
|
ownerRunId: acquisition.owner.runId,
|
|
138
|
-
userMessage:
|
|
139
|
-
|
|
149
|
+
userMessage: applicationLease
|
|
150
|
+
? `Linux Hopper is already active in REA session ${acquisition.owner.runId}; it cannot open ${this.options.targetPath} in another session. This build forwards new launches to the existing application. Use the owning REA session to switch targets, or close it before retrying.`
|
|
151
|
+
: `This Hopper target is already open in REA session ${acquisition.owner.runId}. ` +
|
|
152
|
+
"Use that REA session or close it before opening this target again.",
|
|
140
153
|
}));
|
|
141
154
|
return ok(acquisition.lease);
|
|
142
155
|
}
|
|
143
156
|
catch (cause) {
|
|
144
|
-
return err(
|
|
157
|
+
return err(cause instanceof HopperStartError
|
|
158
|
+
? cause
|
|
159
|
+
: new HopperStartError({ cause }));
|
|
145
160
|
}
|
|
146
161
|
}
|
|
147
|
-
async #writeBootstrap(session, ownsProcessLifetime) {
|
|
162
|
+
async #writeBootstrap(session, ownsProcessLifetime, loadedPath) {
|
|
148
163
|
const bootstrapPath = `${session.directory}/bootstrap.py`;
|
|
149
164
|
try {
|
|
150
|
-
await writeFile(bootstrapPath, bridgeBootstrapSource(session, this.options, ownsProcessLifetime), { encoding: "utf8", mode: 0o600 });
|
|
165
|
+
await writeFile(bootstrapPath, bridgeBootstrapSource(session, this.options, ownsProcessLifetime, loadedPath), { encoding: "utf8", mode: 0o600 });
|
|
151
166
|
await chmod(bootstrapPath, 0o600);
|
|
152
167
|
return ok(bootstrapPath);
|
|
153
168
|
}
|
|
@@ -161,6 +176,7 @@ export class HopperApplicationLauncher {
|
|
|
161
176
|
const selection = await (this.dependencies.selectPrivateDisplay ??
|
|
162
177
|
selectLinuxPrivateDisplayStrategy)({
|
|
163
178
|
helperPath: this.options.demoHelperPath,
|
|
179
|
+
environment: this.options.environment,
|
|
164
180
|
...(signal === undefined ? {} : { signal }),
|
|
165
181
|
});
|
|
166
182
|
if (signal?.aborted === true)
|
|
@@ -173,11 +189,11 @@ export class HopperApplicationLauncher {
|
|
|
173
189
|
};
|
|
174
190
|
}
|
|
175
191
|
}
|
|
176
|
-
const bridgeBootstrapSource = (session, options, ownsProcessLifetime) => [
|
|
192
|
+
const bridgeBootstrapSource = (session, options, ownsProcessLifetime, loadedPath) => [
|
|
177
193
|
`REA_SOCKET = ${JSON.stringify(session.socketPath)}`,
|
|
178
194
|
`REA_TOKEN = ${JSON.stringify(session.token)}`,
|
|
179
195
|
`REA_RUN_ID = ${JSON.stringify(session.runId)}`,
|
|
180
|
-
`REA_TARGET_PATH = ${JSON.stringify(
|
|
196
|
+
`REA_TARGET_PATH = ${JSON.stringify(loadedPath)}`,
|
|
181
197
|
`REA_OWNS_PROCESS_LIFETIME = ${ownsProcessLifetime ? "True" : "False"}`,
|
|
182
198
|
`exec(compile(open(${JSON.stringify(options.bridgeScriptPath)}, 'rb').read(), ${JSON.stringify(options.bridgeScriptPath)}, 'exec'))`,
|
|
183
199
|
"",
|
|
@@ -189,6 +205,7 @@ const launchHopperProcess = async (input) => {
|
|
|
189
205
|
arguments: arguments_,
|
|
190
206
|
runId: input.session.runId,
|
|
191
207
|
expectedCommand: ownershipCommand,
|
|
208
|
+
hostEnvironment: input.options.environment,
|
|
192
209
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
193
210
|
});
|
|
194
211
|
if (input.linuxDemo !== undefined)
|
|
@@ -197,6 +214,7 @@ const launchHopperProcess = async (input) => {
|
|
|
197
214
|
arguments: input.linuxDemo.args,
|
|
198
215
|
runId: input.session.runId,
|
|
199
216
|
expectedCommand: ownershipCommand,
|
|
217
|
+
hostEnvironment: input.options.environment,
|
|
200
218
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
201
219
|
});
|
|
202
220
|
return spawn(input.argumentsForTarget);
|
|
@@ -242,21 +260,16 @@ const hopperLaunchFailure = (cause, signal) => signal?.aborted === true
|
|
|
242
260
|
: new HopperStartError({ cause });
|
|
243
261
|
/** Select the version-pinned adapter from the caller's explicit launch mode. */
|
|
244
262
|
export const usesLinuxDemo = (options) => options.launchMode === "verified_linux_demo";
|
|
245
|
-
const prepareHopperApplication = async (launcherPath, signal) => {
|
|
263
|
+
const prepareHopperApplication = async (launcherPath, environment, signal) => {
|
|
246
264
|
const appBundle = hopperApplicationBundle(launcherPath);
|
|
247
265
|
if (appBundle === undefined)
|
|
248
266
|
return signal?.aborted !== true;
|
|
249
267
|
const executablePath = join(appBundle, "Contents/MacOS/Hopper Disassembler");
|
|
250
|
-
if (await processIsRunning(executablePath))
|
|
268
|
+
if (await processIsRunning(executablePath, environment))
|
|
251
269
|
return signal?.aborted !== true;
|
|
252
270
|
// This reduces activation when Hopper is cold, but the vendor launcher that
|
|
253
271
|
// follows may still activate its window. See HopperApplicationLauncher.
|
|
254
|
-
await execFileAsync("/usr/bin/open", [
|
|
255
|
-
"--hide",
|
|
256
|
-
"--background",
|
|
257
|
-
"-a",
|
|
258
|
-
appBundle,
|
|
259
|
-
]);
|
|
272
|
+
await execFileAsync("/usr/bin/open", ["--hide", "--background", "-a", appBundle], { env: environment });
|
|
260
273
|
return ((await waitForAbortableDelay(HOPPER_BACKGROUND_STARTUP_MS, signal)) ===
|
|
261
274
|
"elapsed");
|
|
262
275
|
};
|
|
@@ -266,13 +279,9 @@ const hopperApplicationBundle = (launcherPath) => {
|
|
|
266
279
|
const candidate = dirname(dirname(dirname(launcherPath)));
|
|
267
280
|
return extname(candidate) === ".app" ? candidate : undefined;
|
|
268
281
|
};
|
|
269
|
-
const processIsRunning = async (executablePath) => {
|
|
282
|
+
const processIsRunning = async (executablePath, environment) => {
|
|
270
283
|
try {
|
|
271
|
-
const processes = await execFileOutput("/bin/ps", [
|
|
272
|
-
"-ax",
|
|
273
|
-
"-o",
|
|
274
|
-
"command=",
|
|
275
|
-
]);
|
|
284
|
+
const processes = await execFileOutput("/bin/ps", ["-ax", "-o", "command="], { env: environment });
|
|
276
285
|
return processes.stdout
|
|
277
286
|
.split("\n")
|
|
278
287
|
.some((command) => command.trim() === executablePath);
|