fix(ghidra): invalidate synthetic entry reference snapshots (#3728)

fix(ghidra): exclude synthetic entry references
This commit is contained in:
Ysopwnable
2026-10-15 06:14:29 +08:00
committed by GitHub
parent bb49252523
commit 3d2846f237
3 changed files with 36 additions and 30 deletions
+26 -27
View File
@@ -1337,12 +1337,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
result.add("references", references);
if (includeIncoming) {
TreeMap<String, Reference> incoming = new TreeMap<>();
ReferenceIterator incomingIterator = currentProgram.getReferenceManager().getReferencesTo(address);
while (incomingIterator.hasNext()) {
monitor.checkCancelled();
Reference reference = incomingIterator.next();
if (!reference.isEntryPointReference()) addReference(incoming, reference);
}
visitObservedReferencesTo(address, reference -> addReference(incoming, reference));
List<Reference> orderedIncoming = new ArrayList<>(incoming.values());
orderedIncoming.sort(REFERENCE_ORDER);
JsonArray incomingReferences = new JsonArray();
@@ -1394,16 +1389,8 @@ public final class ReaGhidraBridge extends HeadlessScript {
requireKeys(params, Set.of("document", "address"));
requireDocument(params);
Address address = requireAddress(params, "address");
ReferenceIterator references = currentProgram.getReferenceManager().getReferencesTo(address);
Set<Address> sources = new HashSet<>();
while (references.hasNext()) {
monitor.checkCancelled();
Reference reference = references.next();
if (reference.isEntryPointReference()) {
continue;
}
sources.add(reference.getFromAddress());
}
visitObservedReferencesTo(address, reference -> sources.add(reference.getFromAddress()));
List<Address> ordered = new ArrayList<>(sources);
ordered.sort(Address::compareTo);
JsonArray result = new JsonArray();
@@ -3674,24 +3661,36 @@ public final class ReaGhidraBridge extends HeadlessScript {
monitor.checkCancelled();
Address address = addresses.next();
if (outgoing) {
for (Reference reference : currentProgram.getReferenceManager()
.getReferencesFrom(address)) {
monitor.checkCancelled();
if (!reference.isEntryPointReference()) visitor.accept(reference);
}
visitObservedReferencesFrom(address, visitor);
}
else {
ReferenceIterator iterator = currentProgram.getReferenceManager()
.getReferencesTo(address);
while (iterator.hasNext()) {
monitor.checkCancelled();
Reference reference = iterator.next();
if (!reference.isEntryPointReference()) visitor.accept(reference);
}
visitObservedReferencesTo(address, visitor);
}
}
}
private void visitObservedReferencesFrom(Address address, ReferenceVisitor visitor)
throws Exception {
for (Reference reference : currentProgram.getReferenceManager().getReferencesFrom(address)) {
monitor.checkCancelled();
visitObservedReference(reference, visitor);
}
}
private void visitObservedReferencesTo(Address address, ReferenceVisitor visitor)
throws Exception {
ReferenceIterator references = currentProgram.getReferenceManager().getReferencesTo(address);
while (references.hasNext()) {
monitor.checkCancelled();
visitObservedReference(references.next(), visitor);
}
}
private static void visitObservedReference(Reference reference, ReferenceVisitor visitor)
throws Exception {
if (!reference.isEntryPointReference()) visitor.accept(reference);
}
private static void addReference(TreeMap<String, Reference> observed, Reference reference) {
String key = canonicalAddress(reference.getFromAddress()) + "\u0000" +
canonicalAddress(reference.getToAddress()) + "\u0000" +
+4 -2
View File
@@ -42,6 +42,8 @@ import {
} from "../domain/native/nativeAotPe.js";
const callRelationshipCoverage = "function-body-call-coverage-v5";
const instructionReferenceCoverage =
"exact-address-incoming-without-synthetic-entry-v2";
/**
* The processor language REA pins for this target, or undefined when Ghidra may
@@ -136,7 +138,7 @@ export const resolveGhidraAnalysisProfile = async (
procedure_file_offset_resolution:
"address-first-unique-target-source-mapping-v2",
instruction_flow_evidence: "decoded-return-pcode-v1",
instruction_references: "exact-address-incoming-v1",
instruction_references: instructionReferenceCoverage,
function_boundary_observations:
"ghidra-function-boundary-limitations-v3",
no_return_repair:
@@ -236,7 +238,7 @@ export const resolveGhidraAnalysisProfile = async (
procedure_file_offset_resolution:
"address-first-unique-target-source-mapping-v2",
instruction_flow_evidence: "decoded-return-pcode-v1",
instruction_references: "exact-address-incoming-v1",
instruction_references: instructionReferenceCoverage,
function_boundary_observations:
"ghidra-function-boundary-limitations-v3",
no_return_repair:
+6 -1
View File
@@ -192,7 +192,12 @@ describe("Ghidra snapshot profile admission", () => {
it.each([
{
parameter: "instruction_references",
current: "exact-address-incoming-v1",
current: "exact-address-incoming-without-synthetic-entry-v2",
legacy: "exact-address-incoming-v1",
},
{
parameter: "instruction_references",
current: "exact-address-incoming-without-synthetic-entry-v2",
legacy: undefined,
},
{