rea-agents 2.4.0 → 3.0.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 +91 -19
- package/bridge/ghidra/ReaGhidraBridge.java +524 -4
- package/bridge/hopper_bridge.py +313 -28
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/AnalysisContextQueries.js +130 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
- package/dist/application/BinarySession.js +20 -8
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +79 -9
- package/dist/application/BinarySessionStatus.js +31 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +84 -14
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +13 -4
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +71 -127
- package/dist/application/EvidenceLedger.js +45 -16
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +4 -2
- package/dist/application/runtime.js +26 -9
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +259 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +11 -3
- package/dist/cli/artifactCommands.js +44 -3
- package/dist/cli/coreAnalysisCommands.js +78 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +9 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +29 -2
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +35 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +30 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/promptContracts.js +14 -15
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +8 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +34 -25
- package/dist/contracts/toolEffects.js +25 -0
- package/dist/contracts/toolOutputSchemaGroups.js +120 -30
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +9 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/bytecodeProvider.js +179 -0
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +193 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/eventProcessTree.js +214 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +14 -1
- package/dist/domain/inputIssueProjection.js +7 -1
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +13 -16
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +12 -15
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +130 -0
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/protocolCapture.js +243 -0
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +40 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +93 -99
- package/dist/hopper/HopperProvider.js +61 -30
- package/dist/hopper/HopperRequestQueue.js +215 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +63 -20
- package/dist/main/transport.js +24 -27
- package/dist/main.js +14 -6
- package/dist/mcpDoctor.js +27 -4
- package/dist/mcpStartupPolicy.js +14 -0
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/LazyToolCatalog.js +134 -0
- package/dist/server/createServer.js +92 -154
- package/dist/server/hydrateServerTools.js +191 -0
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +28 -7
- package/dist/server/registerEvidenceResources.js +54 -101
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerInvestigationTools.js +1 -2
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
- package/dist/server/registerReconstructionReadinessResource.js +32 -0
- package/dist/server/registerSessionRecordTools.js +82 -12
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +32 -58
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/dist/server/toolRegistrationOptions.js +21 -6
- package/dist/server/toolResult.js +12 -0
- package/package.json +28 -11
- package/scripts/package-runner-bootstrap.mjs +72 -0
- package/scripts/rea.mjs +11 -1
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
|
@@ -55,6 +55,7 @@ import ghidra.program.model.block.CodeBlockIterator;
|
|
|
55
55
|
import ghidra.program.model.block.CodeBlockReference;
|
|
56
56
|
import ghidra.program.model.block.CodeBlockReferenceIterator;
|
|
57
57
|
import ghidra.program.model.data.StringDataInstance;
|
|
58
|
+
import ghidra.program.model.data.DataType;
|
|
58
59
|
import ghidra.program.model.listing.CommentType;
|
|
59
60
|
import ghidra.program.model.listing.Data;
|
|
60
61
|
import ghidra.program.model.listing.DataIterator;
|
|
@@ -70,15 +71,25 @@ import ghidra.program.model.symbol.ReferenceIterator;
|
|
|
70
71
|
import ghidra.program.model.symbol.SourceType;
|
|
71
72
|
import ghidra.program.model.symbol.Symbol;
|
|
72
73
|
import ghidra.program.model.symbol.SymbolIterator;
|
|
74
|
+
import ghidra.program.model.pcode.FunctionPrototype;
|
|
75
|
+
import ghidra.program.model.pcode.HighFunction;
|
|
76
|
+
import ghidra.program.model.pcode.HighSymbol;
|
|
77
|
+
import ghidra.program.model.pcode.JumpTable;
|
|
73
78
|
|
|
74
79
|
public final class ReaGhidraBridge extends HeadlessScript {
|
|
75
|
-
private static final int BRIDGE_VERSION =
|
|
80
|
+
private static final int BRIDGE_VERSION = 6;
|
|
76
81
|
private static final int MAX_DESCRIPTOR_BYTES = 16 * 1024;
|
|
77
82
|
private static final int MAX_REQUEST_CHARACTERS = 256 * 1024;
|
|
78
83
|
private static final int MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
84
|
+
private static final int RESPONSE_ENVELOPE_RESERVE_BYTES = 32 * 1024;
|
|
85
|
+
private static final int MAX_NATIVE_API_RESPONSE_BYTES = 192 * 1024;
|
|
79
86
|
private static final int MAX_INVENTORY_ITEMS = 1_000_000;
|
|
80
87
|
private static final int MAX_FUNCTION_ITEMS = 100_000;
|
|
81
88
|
private static final int MAX_FUNCTION_INSTRUCTIONS = 100_000;
|
|
89
|
+
private static final int MAX_NATIVE_API_PARAMETERS = 64;
|
|
90
|
+
private static final int MAX_NATIVE_API_JUMP_TABLES = 4;
|
|
91
|
+
private static final int MAX_NATIVE_API_LOAD_TABLES = 4;
|
|
92
|
+
private static final int MAX_NATIVE_API_MAPPINGS = 32;
|
|
82
93
|
private static final int DECOMPILE_TIMEOUT_SECONDS = 30;
|
|
83
94
|
private static final int DECOMPILE_PAYLOAD_MBYTES = 8;
|
|
84
95
|
private static final int MAX_LIST_VALUE_CODE_POINTS = 1_024;
|
|
@@ -123,6 +134,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
123
134
|
"procedure_callers",
|
|
124
135
|
"procedure_info",
|
|
125
136
|
"procedure_pseudo_code",
|
|
137
|
+
"read_function_instructions",
|
|
126
138
|
"procedure_references",
|
|
127
139
|
"xrefs"
|
|
128
140
|
};
|
|
@@ -311,6 +323,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
311
323
|
case "procedure_callers" -> procedureCalls(request.params, true);
|
|
312
324
|
case "procedure_info" -> procedureInfo(request.params);
|
|
313
325
|
case "procedure_pseudo_code" -> procedurePseudocode(request.params);
|
|
326
|
+
case "read_function_instructions" -> readFunctionInstructions(request.params);
|
|
314
327
|
case "procedure_references" -> procedureReferences(request.params);
|
|
315
328
|
case "resolve_containing_procedure" -> containingProcedure(request.params);
|
|
316
329
|
case "search_procedures" -> search(request.params, true);
|
|
@@ -375,7 +388,9 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
375
388
|
private JsonElement procedurePseudocode(JsonObject params) throws Exception {
|
|
376
389
|
requireKeys(params, Set.of("document", "procedure"));
|
|
377
390
|
requireDocument(params);
|
|
378
|
-
String value =
|
|
391
|
+
String value = decompiledText(
|
|
392
|
+
decompile(resolveProcedure(requireString(params, "procedure")))
|
|
393
|
+
);
|
|
379
394
|
return value == null ? JsonNull.INSTANCE : GSON.toJsonTree(value);
|
|
380
395
|
}
|
|
381
396
|
|
|
@@ -390,6 +405,51 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
390
405
|
return GSON.toJsonTree(renderAssembly(scan.instructions));
|
|
391
406
|
}
|
|
392
407
|
|
|
408
|
+
private JsonObject readFunctionInstructions(JsonObject params) throws Exception {
|
|
409
|
+
requireKeys(params, Set.of("document", "procedure", "offset", "limit"));
|
|
410
|
+
requireDocument(params);
|
|
411
|
+
Function function = resolveProcedure(requireString(params, "procedure"));
|
|
412
|
+
int offset = requireBoundedInteger(params, "offset", 0, 100_000);
|
|
413
|
+
int limit = requireBoundedInteger(params, "limit", 1, 500);
|
|
414
|
+
InstructionScan scan = scanInstructions(function, offset + limit + 1);
|
|
415
|
+
int start = Math.min(offset, scan.instructions.size());
|
|
416
|
+
int end = Math.min(scan.instructions.size(), start + limit);
|
|
417
|
+
JsonArray items = new JsonArray();
|
|
418
|
+
for (String line : renderAssemblyLines(scan.instructions.subList(start, end))) {
|
|
419
|
+
items.add(line);
|
|
420
|
+
}
|
|
421
|
+
boolean hasMore = scan.truncated || end < scan.instructions.size();
|
|
422
|
+
JsonObject instructions = new JsonObject();
|
|
423
|
+
instructions.add("items", items);
|
|
424
|
+
if (scan.truncated) {
|
|
425
|
+
instructions.add("total", JsonNull.INSTANCE);
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
instructions.addProperty("total", scan.instructions.size());
|
|
429
|
+
}
|
|
430
|
+
instructions.addProperty("returned", items.size());
|
|
431
|
+
instructions.addProperty("truncated", hasMore);
|
|
432
|
+
if (hasMore) {
|
|
433
|
+
instructions.addProperty("next_offset", end);
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
instructions.add("next_offset", JsonNull.INSTANCE);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
JsonArray limitations = new JsonArray();
|
|
440
|
+
limitations.add("Instruction text and ordering are Ghidra-specific representations.");
|
|
441
|
+
limitations.add(
|
|
442
|
+
"The fast path does not invoke the decompiler or scan whole-program names and strings."
|
|
443
|
+
);
|
|
444
|
+
JsonObject result = new JsonObject();
|
|
445
|
+
result.add("procedure", procedureIdentity(function));
|
|
446
|
+
result.add("instructions", instructions);
|
|
447
|
+
result.addProperty("instructions_scanned", scan.instructions.size());
|
|
448
|
+
result.addProperty("instruction_scan_truncated", scan.truncated);
|
|
449
|
+
result.add("limitations", limitations);
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
|
|
393
453
|
private JsonArray procedureCalls(JsonObject params, boolean callers) throws Exception {
|
|
394
454
|
requireKeys(params, Set.of("document", "procedure"));
|
|
395
455
|
requireDocument(params);
|
|
@@ -529,7 +589,8 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
529
589
|
);
|
|
530
590
|
JsonObject offsets = requireCollectionOffsets(params);
|
|
531
591
|
InstructionScan scan = scanInstructions(function, maximumInstructions);
|
|
532
|
-
|
|
592
|
+
DecompileResults decompilation = decompile(function);
|
|
593
|
+
String pseudocode = decompiledText(decompilation);
|
|
533
594
|
if (pseudocode == null) {
|
|
534
595
|
pseudocode = "";
|
|
535
596
|
}
|
|
@@ -615,6 +676,19 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
615
676
|
instructionScan.addProperty("scanned", scan.instructions.size());
|
|
616
677
|
instructionScan.addProperty("truncated", scan.truncated);
|
|
617
678
|
result.add("instruction_scan", instructionScan);
|
|
679
|
+
int nativeApiBudget = Math.min(
|
|
680
|
+
MAX_NATIVE_API_RESPONSE_BYTES,
|
|
681
|
+
Math.max(
|
|
682
|
+
0,
|
|
683
|
+
MAX_RESPONSE_BYTES -
|
|
684
|
+
encodedUtf8Length(result) -
|
|
685
|
+
RESPONSE_ENVELOPE_RESERVE_BYTES
|
|
686
|
+
)
|
|
687
|
+
);
|
|
688
|
+
result.add(
|
|
689
|
+
"native_api",
|
|
690
|
+
nativeApiBoundary(function, decompilation, nativeApiBudget)
|
|
691
|
+
);
|
|
618
692
|
JsonArray limitations = new JsonArray();
|
|
619
693
|
limitations.add(
|
|
620
694
|
"Unresolved computed or indirect flows without target addresses are not represented as reference edges."
|
|
@@ -924,7 +998,446 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
924
998
|
return matches.get(0);
|
|
925
999
|
}
|
|
926
1000
|
|
|
927
|
-
private
|
|
1001
|
+
private JsonObject nativeApiBoundary(
|
|
1002
|
+
Function function,
|
|
1003
|
+
DecompileResults decompilation,
|
|
1004
|
+
int maximumBytes
|
|
1005
|
+
) throws Exception {
|
|
1006
|
+
if (decompilation == null || decompilation.getHighFunction() == null) {
|
|
1007
|
+
return unavailableNativeApiBoundary(
|
|
1008
|
+
"Ghidra has no HighFunction model for an external or bodyless procedure"
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
HighFunction highFunction = decompilation.getHighFunction();
|
|
1013
|
+
FunctionPrototype prototype = highFunction.getFunctionPrototype();
|
|
1014
|
+
String signatureSource = function
|
|
1015
|
+
.getSignatureSource()
|
|
1016
|
+
.name()
|
|
1017
|
+
.toLowerCase(Locale.ROOT);
|
|
1018
|
+
JsonObject result = new JsonObject();
|
|
1019
|
+
result.addProperty("available", true);
|
|
1020
|
+
result.addProperty("provenance", "ghidra-high-function");
|
|
1021
|
+
result.addProperty("signature_source", signatureSource);
|
|
1022
|
+
String callingConvention = prototype.getModelName();
|
|
1023
|
+
result.addProperty(
|
|
1024
|
+
"calling_convention",
|
|
1025
|
+
callingConvention == null || callingConvention.isBlank()
|
|
1026
|
+
? "unknown"
|
|
1027
|
+
: callingConvention
|
|
1028
|
+
);
|
|
1029
|
+
result.add(
|
|
1030
|
+
"return_type",
|
|
1031
|
+
inferredBoundaryType(
|
|
1032
|
+
"return",
|
|
1033
|
+
null,
|
|
1034
|
+
null,
|
|
1035
|
+
prototype.getReturnType(),
|
|
1036
|
+
prototype.getReturnStorage().toString(),
|
|
1037
|
+
false,
|
|
1038
|
+
signatureSource
|
|
1039
|
+
)
|
|
1040
|
+
);
|
|
1041
|
+
|
|
1042
|
+
JsonArray parameters = new JsonArray();
|
|
1043
|
+
result.add("parameters", parameters);
|
|
1044
|
+
result.addProperty("parameters_truncated", false);
|
|
1045
|
+
|
|
1046
|
+
JsonArray jumpTables = new JsonArray();
|
|
1047
|
+
result.add("jump_tables", jumpTables);
|
|
1048
|
+
result.addProperty("jump_tables_truncated", false);
|
|
1049
|
+
|
|
1050
|
+
JsonObject pseudocode = new JsonObject();
|
|
1051
|
+
pseudocode.addProperty("classification", "decompiler-generated-non-source");
|
|
1052
|
+
pseudocode.addProperty("compilable", false);
|
|
1053
|
+
result.add("pseudocode", pseudocode);
|
|
1054
|
+
|
|
1055
|
+
JsonArray artifacts = new JsonArray();
|
|
1056
|
+
artifacts.add("recovered-signature");
|
|
1057
|
+
artifacts.add("register-and-stack-variables");
|
|
1058
|
+
artifacts.add("compiler-generated-control-flow");
|
|
1059
|
+
artifacts.add("pointer-arithmetic");
|
|
1060
|
+
artifacts.add("pseudocode");
|
|
1061
|
+
result.add("decompiler_artifacts", artifacts);
|
|
1062
|
+
|
|
1063
|
+
JsonArray limitations = new JsonArray();
|
|
1064
|
+
limitations.add(
|
|
1065
|
+
"Types and calling conventions are Ghidra decompiler observations, not source declarations."
|
|
1066
|
+
);
|
|
1067
|
+
limitations.add(
|
|
1068
|
+
"Register variables, compiler-generated blocks, and pointer arithmetic remain decompiler artifacts."
|
|
1069
|
+
);
|
|
1070
|
+
limitations.add(
|
|
1071
|
+
"Pseudocode is neither original source nor guaranteed to compile."
|
|
1072
|
+
);
|
|
1073
|
+
result.add("limitations", limitations);
|
|
1074
|
+
if (encodedUtf8Length(result) > maximumBytes) {
|
|
1075
|
+
return unavailableNativeApiBoundary(
|
|
1076
|
+
"The remaining Ghidra response budget cannot contain a structured native API boundary"
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
int parameterCount = Math.min(
|
|
1081
|
+
prototype.getNumParams(),
|
|
1082
|
+
MAX_NATIVE_API_PARAMETERS
|
|
1083
|
+
);
|
|
1084
|
+
for (int index = 0; index < parameterCount; index += 1) {
|
|
1085
|
+
HighSymbol parameter = prototype.getParam(index);
|
|
1086
|
+
if (parameter == null) {
|
|
1087
|
+
continue;
|
|
1088
|
+
}
|
|
1089
|
+
parameters.add(
|
|
1090
|
+
inferredBoundaryType(
|
|
1091
|
+
"parameter",
|
|
1092
|
+
index,
|
|
1093
|
+
parameter.getName(),
|
|
1094
|
+
parameter.getDataType(),
|
|
1095
|
+
parameter.getStorage().toString(),
|
|
1096
|
+
parameter.isTypeLocked(),
|
|
1097
|
+
signatureSource
|
|
1098
|
+
)
|
|
1099
|
+
);
|
|
1100
|
+
if (encodedUtf8Length(result) > maximumBytes) {
|
|
1101
|
+
parameters.remove(parameters.size() - 1);
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
result.addProperty(
|
|
1106
|
+
"parameters_truncated",
|
|
1107
|
+
prototype.getNumParams() > parameters.size()
|
|
1108
|
+
);
|
|
1109
|
+
|
|
1110
|
+
JumpTable[] recoveredJumpTables = highFunction.getJumpTables();
|
|
1111
|
+
int jumpTableCount = Math.min(
|
|
1112
|
+
recoveredJumpTables.length,
|
|
1113
|
+
MAX_NATIVE_API_JUMP_TABLES
|
|
1114
|
+
);
|
|
1115
|
+
for (int index = 0; index < jumpTableCount; index += 1) {
|
|
1116
|
+
jumpTables.add(inferredJumpTable(recoveredJumpTables[index]));
|
|
1117
|
+
if (encodedUtf8Length(result) > maximumBytes) {
|
|
1118
|
+
jumpTables.remove(jumpTables.size() - 1);
|
|
1119
|
+
break;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
result.addProperty(
|
|
1123
|
+
"jump_tables_truncated",
|
|
1124
|
+
recoveredJumpTables.length > jumpTables.size()
|
|
1125
|
+
);
|
|
1126
|
+
return result;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
private static JsonObject unavailableNativeApiBoundary(String reason) {
|
|
1130
|
+
JsonObject unavailable = new JsonObject();
|
|
1131
|
+
unavailable.addProperty("available", false);
|
|
1132
|
+
unavailable.addProperty("reason", reason);
|
|
1133
|
+
JsonArray unknowns = new JsonArray();
|
|
1134
|
+
unknowns.add("Return and parameter boundary types are unavailable.");
|
|
1135
|
+
unknowns.add("Jump-table mappings are unavailable.");
|
|
1136
|
+
unavailable.add("residual_unknowns", unknowns);
|
|
1137
|
+
return unavailable;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
private static int encodedUtf8Length(JsonElement value) {
|
|
1141
|
+
return GSON.toJson(value).getBytes(StandardCharsets.UTF_8).length;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
private static JsonObject inferredBoundaryType(
|
|
1145
|
+
String role,
|
|
1146
|
+
Integer ordinal,
|
|
1147
|
+
String name,
|
|
1148
|
+
DataType dataType,
|
|
1149
|
+
String storage,
|
|
1150
|
+
boolean typeLocked,
|
|
1151
|
+
String signatureSource
|
|
1152
|
+
) {
|
|
1153
|
+
JsonObject result = new JsonObject();
|
|
1154
|
+
result.addProperty("role", role);
|
|
1155
|
+
if (ordinal == null) {
|
|
1156
|
+
result.add("ordinal", JsonNull.INSTANCE);
|
|
1157
|
+
}
|
|
1158
|
+
else {
|
|
1159
|
+
result.addProperty("ordinal", ordinal);
|
|
1160
|
+
}
|
|
1161
|
+
if (name == null || name.isBlank()) {
|
|
1162
|
+
result.add("name", JsonNull.INSTANCE);
|
|
1163
|
+
}
|
|
1164
|
+
else {
|
|
1165
|
+
result.addProperty("name", name);
|
|
1166
|
+
}
|
|
1167
|
+
result.addProperty("data_type", dataType.getDisplayName());
|
|
1168
|
+
int dataTypeLength = dataType.getLength();
|
|
1169
|
+
if (dataTypeLength < 0) {
|
|
1170
|
+
result.add("size_bytes", JsonNull.INSTANCE);
|
|
1171
|
+
}
|
|
1172
|
+
else {
|
|
1173
|
+
result.addProperty("size_bytes", dataTypeLength);
|
|
1174
|
+
}
|
|
1175
|
+
if (storage.isBlank()) {
|
|
1176
|
+
result.add("storage", JsonNull.INSTANCE);
|
|
1177
|
+
}
|
|
1178
|
+
else {
|
|
1179
|
+
result.addProperty("storage", storage);
|
|
1180
|
+
}
|
|
1181
|
+
result.addProperty(
|
|
1182
|
+
"confidence",
|
|
1183
|
+
inferenceConfidence(signatureSource, typeLocked)
|
|
1184
|
+
);
|
|
1185
|
+
|
|
1186
|
+
JsonArray evidence = new JsonArray();
|
|
1187
|
+
evidence.add(
|
|
1188
|
+
inferenceEvidence(
|
|
1189
|
+
"signature-source",
|
|
1190
|
+
"ghidra-function-manager",
|
|
1191
|
+
"Function signature source is " + signatureSource + "."
|
|
1192
|
+
)
|
|
1193
|
+
);
|
|
1194
|
+
evidence.add(
|
|
1195
|
+
inferenceEvidence(
|
|
1196
|
+
"decompiler-type",
|
|
1197
|
+
"ghidra-high-function",
|
|
1198
|
+
"HighFunction recovered data type " + dataType.getDisplayName() + "."
|
|
1199
|
+
)
|
|
1200
|
+
);
|
|
1201
|
+
if (typeLocked) {
|
|
1202
|
+
evidence.add(
|
|
1203
|
+
inferenceEvidence(
|
|
1204
|
+
"type-lock",
|
|
1205
|
+
"ghidra-high-symbol",
|
|
1206
|
+
"The decompiler marks this parameter type as locked."
|
|
1207
|
+
)
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
result.add("evidence", evidence);
|
|
1211
|
+
|
|
1212
|
+
JsonArray artifacts = new JsonArray();
|
|
1213
|
+
artifacts.add("recovered-signature");
|
|
1214
|
+
if (!storage.isBlank()) {
|
|
1215
|
+
artifacts.add("register-or-stack-storage");
|
|
1216
|
+
}
|
|
1217
|
+
if (name != null && (name.startsWith("param_") || name.startsWith("unaff_"))) {
|
|
1218
|
+
artifacts.add("compiler-generated-variable");
|
|
1219
|
+
}
|
|
1220
|
+
result.add("decompiler_artifacts", artifacts);
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
private JsonObject inferredJumpTable(JumpTable jumpTable) throws Exception {
|
|
1225
|
+
JsonObject result = new JsonObject();
|
|
1226
|
+
result.addProperty(
|
|
1227
|
+
"dispatch_address",
|
|
1228
|
+
canonicalAddress(jumpTable.getSwitchAddress())
|
|
1229
|
+
);
|
|
1230
|
+
JumpTable.LoadTable[] loadTables = jumpTable.getLoadTables();
|
|
1231
|
+
List<Address> referencedDataAddresses = loadTables.length == 0
|
|
1232
|
+
? dispatchPathDataReferences(jumpTable)
|
|
1233
|
+
: List.of();
|
|
1234
|
+
JsonArray dataSources = new JsonArray();
|
|
1235
|
+
int loadTableCount = Math.min(
|
|
1236
|
+
loadTables.length,
|
|
1237
|
+
MAX_NATIVE_API_LOAD_TABLES
|
|
1238
|
+
);
|
|
1239
|
+
for (int index = 0; index < loadTableCount; index += 1) {
|
|
1240
|
+
JumpTable.LoadTable loadTable = loadTables[index];
|
|
1241
|
+
JsonObject source = new JsonObject();
|
|
1242
|
+
source.addProperty("address", canonicalAddress(loadTable.getAddress()));
|
|
1243
|
+
source.addProperty("provenance", "ghidra-decompiler-load-table");
|
|
1244
|
+
source.addProperty("entry_size_bytes", loadTable.getSize());
|
|
1245
|
+
source.addProperty("entry_count", loadTable.getNum());
|
|
1246
|
+
source.addProperty("confidence", "high");
|
|
1247
|
+
JsonArray evidence = new JsonArray();
|
|
1248
|
+
evidence.add(
|
|
1249
|
+
inferenceEvidence(
|
|
1250
|
+
"jump-table",
|
|
1251
|
+
"ghidra-high-function",
|
|
1252
|
+
"Decompiler load table starts at " +
|
|
1253
|
+
canonicalAddress(loadTable.getAddress()) +
|
|
1254
|
+
"."
|
|
1255
|
+
)
|
|
1256
|
+
);
|
|
1257
|
+
source.add("evidence", evidence);
|
|
1258
|
+
dataSources.add(source);
|
|
1259
|
+
}
|
|
1260
|
+
int referencedDataCount = Math.min(
|
|
1261
|
+
referencedDataAddresses.size(),
|
|
1262
|
+
MAX_NATIVE_API_LOAD_TABLES - loadTableCount
|
|
1263
|
+
);
|
|
1264
|
+
for (int index = 0; index < referencedDataCount; index += 1) {
|
|
1265
|
+
Address address = referencedDataAddresses.get(index);
|
|
1266
|
+
JsonObject source = new JsonObject();
|
|
1267
|
+
source.addProperty("address", canonicalAddress(address));
|
|
1268
|
+
source.addProperty(
|
|
1269
|
+
"provenance",
|
|
1270
|
+
"ghidra-dispatch-block-data-reference"
|
|
1271
|
+
);
|
|
1272
|
+
source.add("entry_size_bytes", JsonNull.INSTANCE);
|
|
1273
|
+
source.add("entry_count", JsonNull.INSTANCE);
|
|
1274
|
+
source.addProperty("confidence", "medium");
|
|
1275
|
+
JsonArray evidence = new JsonArray();
|
|
1276
|
+
evidence.add(
|
|
1277
|
+
inferenceEvidence(
|
|
1278
|
+
"jump-table",
|
|
1279
|
+
"ghidra-reference-manager",
|
|
1280
|
+
"The dispatch block or an immediate predecessor contains a typed data reference to " +
|
|
1281
|
+
canonicalAddress(address) +
|
|
1282
|
+
"."
|
|
1283
|
+
)
|
|
1284
|
+
);
|
|
1285
|
+
source.add("evidence", evidence);
|
|
1286
|
+
dataSources.add(source);
|
|
1287
|
+
}
|
|
1288
|
+
result.add("data_sources", dataSources);
|
|
1289
|
+
result.addProperty(
|
|
1290
|
+
"data_sources_truncated",
|
|
1291
|
+
loadTables.length > loadTableCount ||
|
|
1292
|
+
referencedDataAddresses.size() > referencedDataCount
|
|
1293
|
+
);
|
|
1294
|
+
|
|
1295
|
+
Address[] targets = jumpTable.getCases();
|
|
1296
|
+
Integer[] labels = jumpTable.getLabelValues();
|
|
1297
|
+
JsonArray mappings = new JsonArray();
|
|
1298
|
+
int mappingCount = Math.min(targets.length, MAX_NATIVE_API_MAPPINGS);
|
|
1299
|
+
for (int index = 0; index < mappingCount; index += 1) {
|
|
1300
|
+
JsonObject mapping = new JsonObject();
|
|
1301
|
+
if (labels == null || index >= labels.length || labels[index] == null) {
|
|
1302
|
+
mapping.add("case_value", JsonNull.INSTANCE);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
mapping.addProperty("case_value", labels[index]);
|
|
1306
|
+
}
|
|
1307
|
+
String targetAddress = canonicalAddress(targets[index]);
|
|
1308
|
+
mapping.addProperty("target_address", targetAddress);
|
|
1309
|
+
JsonArray dataAddresses = new JsonArray();
|
|
1310
|
+
for (int sourceIndex = 0; sourceIndex < loadTableCount; sourceIndex += 1) {
|
|
1311
|
+
dataAddresses.add(
|
|
1312
|
+
canonicalAddress(loadTables[sourceIndex].getAddress())
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
mapping.add("data_addresses", dataAddresses);
|
|
1316
|
+
mapping.addProperty("confidence", "medium");
|
|
1317
|
+
JsonArray evidence = new JsonArray();
|
|
1318
|
+
evidence.add(
|
|
1319
|
+
inferenceEvidence(
|
|
1320
|
+
"jump-table",
|
|
1321
|
+
"ghidra-high-function",
|
|
1322
|
+
"Recovered target " +
|
|
1323
|
+
targetAddress +
|
|
1324
|
+
" from dispatch " +
|
|
1325
|
+
canonicalAddress(jumpTable.getSwitchAddress()) +
|
|
1326
|
+
"."
|
|
1327
|
+
)
|
|
1328
|
+
);
|
|
1329
|
+
mapping.add("evidence", evidence);
|
|
1330
|
+
mappings.add(mapping);
|
|
1331
|
+
}
|
|
1332
|
+
result.add("mappings", mappings);
|
|
1333
|
+
result.addProperty("mappings_truncated", targets.length > mappingCount);
|
|
1334
|
+
|
|
1335
|
+
JsonArray limitations = new JsonArray();
|
|
1336
|
+
if (loadTables.length == 0 && referencedDataAddresses.isEmpty()) {
|
|
1337
|
+
limitations.add(
|
|
1338
|
+
"Ghidra recovered targets but exposed no backing load-table or dispatch-block data address."
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
if (loadTables.length == 0 && !referencedDataAddresses.isEmpty()) {
|
|
1342
|
+
limitations.add(
|
|
1343
|
+
"Load-table metadata was absent; table-level candidate ownership is inferred from typed data references in the dispatch block and its immediate control-flow predecessors, but candidates are not assigned to individual mappings."
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
if (labels == null || labels.length != targets.length) {
|
|
1347
|
+
limitations.add(
|
|
1348
|
+
"Case labels were unavailable or incomplete; null labels are preserved."
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
if (
|
|
1352
|
+
loadTables.length > loadTableCount ||
|
|
1353
|
+
referencedDataAddresses.size() > referencedDataCount ||
|
|
1354
|
+
targets.length > mappingCount
|
|
1355
|
+
) {
|
|
1356
|
+
limitations.add(
|
|
1357
|
+
"Native API jump-table observations reached REA's bounded output limits."
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
result.add("limitations", limitations);
|
|
1361
|
+
return result;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
private List<Address> dispatchPathDataReferences(JumpTable jumpTable)
|
|
1365
|
+
throws Exception {
|
|
1366
|
+
BasicBlockModel model = new BasicBlockModel(currentProgram, false);
|
|
1367
|
+
CodeBlock dispatchBlock = model.getFirstCodeBlockContaining(
|
|
1368
|
+
jumpTable.getSwitchAddress(),
|
|
1369
|
+
monitor
|
|
1370
|
+
);
|
|
1371
|
+
if (dispatchBlock == null) {
|
|
1372
|
+
return List.of();
|
|
1373
|
+
}
|
|
1374
|
+
List<CodeBlock> blocks = new ArrayList<>();
|
|
1375
|
+
blocks.add(dispatchBlock);
|
|
1376
|
+
CodeBlockReferenceIterator sources = dispatchBlock.getSources(monitor);
|
|
1377
|
+
while (sources.hasNext()) {
|
|
1378
|
+
monitor.checkCancelled();
|
|
1379
|
+
CodeBlock sourceBlock = sources.next().getSourceBlock();
|
|
1380
|
+
if (sourceBlock != null) {
|
|
1381
|
+
blocks.add(sourceBlock);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
Set<Address> addresses = new HashSet<>();
|
|
1385
|
+
for (CodeBlock block : blocks) {
|
|
1386
|
+
InstructionIterator instructions = currentProgram
|
|
1387
|
+
.getListing()
|
|
1388
|
+
.getInstructions(block, true);
|
|
1389
|
+
while (instructions.hasNext()) {
|
|
1390
|
+
monitor.checkCancelled();
|
|
1391
|
+
Instruction instruction = instructions.next();
|
|
1392
|
+
for (
|
|
1393
|
+
Reference reference : currentProgram
|
|
1394
|
+
.getReferenceManager()
|
|
1395
|
+
.getReferencesFrom(instruction.getAddress())
|
|
1396
|
+
) {
|
|
1397
|
+
if (
|
|
1398
|
+
reference.getReferenceType().isData() &&
|
|
1399
|
+
currentProgram
|
|
1400
|
+
.getMemory()
|
|
1401
|
+
.getLoadedAndInitializedAddressSet()
|
|
1402
|
+
.contains(reference.getToAddress())
|
|
1403
|
+
) {
|
|
1404
|
+
addresses.add(reference.getToAddress());
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
List<Address> ordered = new ArrayList<>(addresses);
|
|
1410
|
+
ordered.sort(Address::compareTo);
|
|
1411
|
+
return List.copyOf(ordered);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
private static JsonObject inferenceEvidence(
|
|
1415
|
+
String kind,
|
|
1416
|
+
String source,
|
|
1417
|
+
String detail
|
|
1418
|
+
) {
|
|
1419
|
+
JsonObject evidence = new JsonObject();
|
|
1420
|
+
evidence.addProperty("kind", kind);
|
|
1421
|
+
evidence.addProperty("source", source);
|
|
1422
|
+
evidence.addProperty("detail", detail);
|
|
1423
|
+
return evidence;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
private static String inferenceConfidence(
|
|
1427
|
+
String signatureSource,
|
|
1428
|
+
boolean typeLocked
|
|
1429
|
+
) {
|
|
1430
|
+
if (
|
|
1431
|
+
typeLocked ||
|
|
1432
|
+
signatureSource.equals("user_defined") ||
|
|
1433
|
+
signatureSource.equals("imported")
|
|
1434
|
+
) {
|
|
1435
|
+
return "high";
|
|
1436
|
+
}
|
|
1437
|
+
return signatureSource.equals("analysis") ? "medium" : "low";
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
private DecompileResults decompile(Function function) {
|
|
928
1441
|
if (function.isExternal() || function.getBody().isEmpty()) {
|
|
929
1442
|
return null;
|
|
930
1443
|
}
|
|
@@ -948,6 +1461,13 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
948
1461
|
"Ghidra decompilation failed: " + boundedMessage(results.getErrorMessage())
|
|
949
1462
|
);
|
|
950
1463
|
}
|
|
1464
|
+
return results;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
private static String decompiledText(DecompileResults results) {
|
|
1468
|
+
if (results == null) {
|
|
1469
|
+
return null;
|
|
1470
|
+
}
|
|
951
1471
|
DecompiledFunction value = results.getDecompiledFunction();
|
|
952
1472
|
return value == null ? null : value.getC();
|
|
953
1473
|
}
|