refactor(ghidra): give function boundary scans one owner
This commit is contained in:
1 parent
a004061abc
commit
225f26a5f8
1 file changed
+41
-37
@@ -934,7 +934,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
String value = decompiledText(decompile(function));
|
String value = decompiledText(decompile(function));
|
||||||
JsonObject result = functionObservation(
|
JsonObject result = functionObservation(
|
||||||
value == null ? JsonNull.INSTANCE : GSON.toJsonTree(value),
|
value == null ? JsonNull.INSTANCE : GSON.toJsonTree(value),
|
||||||
noReturnCallLimitations(
|
functionBoundaryLimitations(
|
||||||
function,
|
function,
|
||||||
currentProgram.getListing().getInstructions(function.getBody(), true)
|
currentProgram.getListing().getInstructions(function.getBody(), true)
|
||||||
)
|
)
|
||||||
@@ -1027,7 +1027,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
|
InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
|
||||||
return functionObservation(
|
return functionObservation(
|
||||||
GSON.toJsonTree(renderAssembly(scan.instructions)),
|
GSON.toJsonTree(renderAssembly(scan.instructions)),
|
||||||
noReturnCallLimitations(function, scan.instructions)
|
functionBoundaryLimitations(function, scan.instructions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,7 +1046,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
limitations.add(
|
limitations.add(
|
||||||
"The fast path does not invoke the decompiler or scan whole-program names and strings."
|
"The fast path does not invoke the decompiler or scan whole-program names and strings."
|
||||||
);
|
);
|
||||||
List<String> boundaryLimitations = noReturnCallLimitations(function, scan.instructions);
|
List<String> boundaryLimitations = functionBoundaryLimitations(function, scan.instructions);
|
||||||
for (String limitation : boundaryLimitations) limitations.add(limitation);
|
for (String limitation : boundaryLimitations) limitations.add(limitation);
|
||||||
JsonObject result = new JsonObject();
|
JsonObject result = new JsonObject();
|
||||||
result.add("procedure", procedureIdentity(function));
|
result.add("procedure", procedureIdentity(function));
|
||||||
@@ -1069,7 +1069,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
result.add(canonicalAddress(item.getEntryPoint()));
|
result.add(canonicalAddress(item.getEntryPoint()));
|
||||||
}
|
}
|
||||||
if (callers) {
|
if (callers) {
|
||||||
JsonObject observation = functionObservation(result, noReturnCallLimitations(function,
|
JsonObject observation = functionObservation(result, functionBoundaryLimitations(function,
|
||||||
currentProgram.getListing().getInstructions(function.getBody(), true)
|
currentProgram.getListing().getInstructions(function.getBody(), true)
|
||||||
));
|
));
|
||||||
observation.add("relationship_coverage", callRelationshipCoverage(null,
|
observation.add("relationship_coverage", callRelationshipCoverage(null,
|
||||||
@@ -1099,7 +1099,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
result.add("classification", functionClassification(function));
|
result.add("classification", functionClassification(function));
|
||||||
return functionObservation(
|
return functionObservation(
|
||||||
result,
|
result,
|
||||||
noReturnCallLimitations(
|
functionBoundaryLimitations(
|
||||||
function,
|
function,
|
||||||
currentProgram.getListing().getInstructions(function.getBody(), true)
|
currentProgram.getListing().getInstructions(function.getBody(), true)
|
||||||
)
|
)
|
||||||
@@ -1140,7 +1140,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
unresolvedCalls = calls.unresolvedCalls();
|
unresolvedCalls = calls.unresolvedCalls();
|
||||||
limitations = calls.limitations();
|
limitations = calls.limitations();
|
||||||
} else {
|
} else {
|
||||||
limitations = noReturnCallLimitations(
|
limitations = functionBoundaryLimitations(
|
||||||
function,
|
function,
|
||||||
currentProgram.getListing().getInstructions(function.getBody(), true)
|
currentProgram.getListing().getInstructions(function.getBody(), true)
|
||||||
);
|
);
|
||||||
@@ -3441,51 +3441,27 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
return omitted[0];
|
return omitted[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> noReturnCallLimitations(
|
private List<String> functionBoundaryLimitations(
|
||||||
Function function, Iterable<Instruction> instructions)
|
Function function, Iterable<Instruction> instructions)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
List<String> limitations = new ArrayList<>();
|
FunctionBoundaryLimitations boundary = new FunctionBoundaryLimitations(function);
|
||||||
Instruction beforePrevious = null;
|
for (Instruction instruction : instructions) boundary.observe(instruction);
|
||||||
Instruction previous = null;
|
return boundary.values();
|
||||||
for (Instruction instruction : instructions) {
|
|
||||||
monitor.checkCancelled();
|
|
||||||
String limitation = terminalCallLimitation(instruction);
|
|
||||||
if (limitation != null) limitations.add(limitation);
|
|
||||||
if (beforePrevious != null && previous != null) {
|
|
||||||
String seh = borlandSehHandlerLimitation(
|
|
||||||
function, beforePrevious, previous, instruction);
|
|
||||||
if (seh != null) limitations.add(seh);
|
|
||||||
}
|
|
||||||
beforePrevious = previous;
|
|
||||||
previous = instruction;
|
|
||||||
}
|
|
||||||
return limitations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CallBoundaryObservation callBoundaryObservation(
|
private CallBoundaryObservation callBoundaryObservation(
|
||||||
Function function, Iterable<Instruction> instructions, Set<Function> returnedCallees,
|
Function function, Iterable<Instruction> instructions, Set<Function> returnedCallees,
|
||||||
boolean includeUnresolvedSites, List<Reference> observedReferences)
|
boolean includeUnresolvedSites, List<Reference> observedReferences)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
List<String> limitations = new ArrayList<>();
|
FunctionBoundaryLimitations boundary = new FunctionBoundaryLimitations(function);
|
||||||
CallBoundaryReferences calls = new CallBoundaryReferences(returnedCallees, includeUnresolvedSites);
|
CallBoundaryReferences calls = new CallBoundaryReferences(returnedCallees, includeUnresolvedSites);
|
||||||
Instruction beforePrevious = null;
|
|
||||||
Instruction previous = null;
|
|
||||||
if (observedReferences == null) visitReferences(function, "outgoing", calls::observe);
|
if (observedReferences == null) visitReferences(function, "outgoing", calls::observe);
|
||||||
else for (Reference reference : observedReferences) {
|
else for (Reference reference : observedReferences) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
calls.observe(reference);
|
calls.observe(reference);
|
||||||
}
|
}
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
monitor.checkCancelled();
|
boundary.observe(instruction);
|
||||||
String limitation = terminalCallLimitation(instruction);
|
|
||||||
if (limitation != null) limitations.add(limitation);
|
|
||||||
if (beforePrevious != null && previous != null) {
|
|
||||||
String seh = borlandSehHandlerLimitation(
|
|
||||||
function, beforePrevious, previous, instruction);
|
|
||||||
if (seh != null) limitations.add(seh);
|
|
||||||
}
|
|
||||||
beforePrevious = previous;
|
|
||||||
previous = instruction;
|
|
||||||
if (!instruction.getFlowType().isCall()) continue;
|
if (!instruction.getFlowType().isCall()) continue;
|
||||||
boolean destination = false;
|
boolean destination = false;
|
||||||
for (Reference reference : instruction.getReferencesFrom()) {
|
for (Reference reference : instruction.getReferencesFrom()) {
|
||||||
@@ -3499,10 +3475,38 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|||||||
"Instruction decoder identifies a call but ReferenceManager supplies no call destination");
|
"Instruction decoder identifies a call but ReferenceManager supplies no call destination");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new CallBoundaryObservation(List.copyOf(limitations),
|
return new CallBoundaryObservation(boundary.values(),
|
||||||
returnedCallees == null ? null : calls.unrepresented, calls.unresolvedCalls());
|
returnedCallees == null ? null : calls.unrepresented, calls.unresolvedCalls());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class FunctionBoundaryLimitations {
|
||||||
|
private final Function function;
|
||||||
|
private final List<String> limitations = new ArrayList<>();
|
||||||
|
private Instruction beforePrevious;
|
||||||
|
private Instruction previous;
|
||||||
|
|
||||||
|
private FunctionBoundaryLimitations(Function function) {
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void observe(Instruction instruction) throws Exception {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
String limitation = terminalCallLimitation(instruction);
|
||||||
|
if (limitation != null) limitations.add(limitation);
|
||||||
|
if (beforePrevious != null && previous != null) {
|
||||||
|
String seh = borlandSehHandlerLimitation(
|
||||||
|
function, beforePrevious, previous, instruction);
|
||||||
|
if (seh != null) limitations.add(seh);
|
||||||
|
}
|
||||||
|
beforePrevious = previous;
|
||||||
|
previous = instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> values() {
|
||||||
|
return List.copyOf(limitations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String borlandSehHandlerLimitation(
|
private String borlandSehHandlerLimitation(
|
||||||
Function function, Instruction handlerPush, Instruction framePush,
|
Function function, Instruction handlerPush, Instruction framePush,
|
||||||
Instruction frameLink) {
|
Instruction frameLink) {
|
||||||
|
|||||||
Reference in new issue
Block a user