mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-22 06:15:31 +08:00
Merge branch 'GP-6653_ghidra1_CallTreeWithThunks' into patch
This commit is contained in:
+17
-1
@@ -46,6 +46,7 @@ import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||
import ghidra.program.database.symbol.FunctionSymbol;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.ExternalLocation;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
@@ -757,7 +758,22 @@ public class CallTreeProvider extends ComponentProviderAdapter {
|
||||
isFiringNavigationEvent = true;
|
||||
GoToService goToService = tool.getService(GoToService.class);
|
||||
if (goToService != null) {
|
||||
goToService.goTo(location);
|
||||
Address locAddr = location.getAddress();
|
||||
if (locAddr.isExternalAddress()) {
|
||||
// NOTE: The simple form of GoTo(ProgramLocation) will always goto the linkage
|
||||
// point and not the actual external program. We use the special form for
|
||||
// external location to ensure it respects the navigation options.
|
||||
Symbol symbol = currentProgram.getSymbolTable().getPrimarySymbol(locAddr);
|
||||
if (symbol != null) {
|
||||
ExternalLocation externalLocation =
|
||||
currentProgram.getExternalManager().getExternalLocation(symbol);
|
||||
goToService.goToExternalLocation(goToService.getDefaultNavigatable(),
|
||||
externalLocation, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
goToService.goTo(location);
|
||||
}
|
||||
isFiringNavigationEvent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
+54
-14
@@ -89,10 +89,61 @@ public class IncomingCallNode extends CallNode {
|
||||
private void doGenerateChildren(Address address, List<GTreeNode> results, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
|
||||
ReferenceIterator refIter = program.getReferenceManager().getReferencesTo(address);
|
||||
LazyMap<Function, List<GTreeNode>> nodesByFunction =
|
||||
LazyMap.lazyMap(new HashMap<>(), k -> new ArrayList<>());
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
|
||||
Set<Address> thunkAddrSet = Set.of();
|
||||
Function currentFunction = functionManager.getFunctionAt(address);
|
||||
if (currentFunction != null) {
|
||||
|
||||
if (currentFunction.isThunk() && !callTreeOptions.allowsThunks()) {
|
||||
// If this is a thunk and thunks are filtered-out we must force current function
|
||||
// to the real function
|
||||
currentFunction = currentFunction.getThunkedFunction(true);
|
||||
}
|
||||
|
||||
// Check to see if current function is thunked
|
||||
Address[] functionThunkAddresses =
|
||||
currentFunction.getFunctionThunkAddresses(!callTreeOptions.allowsThunks());
|
||||
if (functionThunkAddresses != null) {
|
||||
thunkAddrSet = Set.of(functionThunkAddresses);
|
||||
for (Address thunkAddr : functionThunkAddresses) {
|
||||
if (address.equals(thunkAddr)) {
|
||||
continue; // avoid possible recursive thunk (should not occur)
|
||||
}
|
||||
Function thunkFunction = functionManager.getFunctionAt(thunkAddr);
|
||||
if (callTreeOptions.allowsThunks()) {
|
||||
// include thunk node in tree
|
||||
IncomingCallNode node =
|
||||
new IncomingCallNode(program, thunkFunction, thunkAddr, true,
|
||||
callTreeOptions);
|
||||
addNode(nodesByFunction, node);
|
||||
}
|
||||
else {
|
||||
// Do NOT include thunk in tree but follow references to the thunk
|
||||
collectIncomingByReference(thunkAddr, nodesByFunction, thunkAddrSet,
|
||||
monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectIncomingByReference(address, nodesByFunction, thunkAddrSet, monitor);
|
||||
|
||||
List<GTreeNode> children = nodesByFunction.values()
|
||||
.stream()
|
||||
.flatMap(list -> list.stream())
|
||||
.collect(Collectors.toList());
|
||||
results.addAll(children);
|
||||
}
|
||||
|
||||
private void collectIncomingByReference(Address address,
|
||||
LazyMap<Function, List<GTreeNode>> nodesByFunction,
|
||||
Set<Address> ignoreFromSet, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
ReferenceIterator refIter = program.getReferenceManager().getReferencesTo(address);
|
||||
while (refIter.hasNext()) {
|
||||
monitor.checkCancelled();
|
||||
Reference ref = refIter.next();
|
||||
@@ -102,13 +153,8 @@ public class IncomingCallNode extends CallNode {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we are not showing thunks, then replace each thunk with all calls to that thunk
|
||||
if (caller.isThunk() && !callTreeOptions.allowsThunks()) {
|
||||
Address callerEntry = caller.getEntryPoint();
|
||||
if (!address.equals(callerEntry)) { // recursive reference from thunk to itself
|
||||
doGenerateChildren(callerEntry, results, monitor);
|
||||
}
|
||||
continue;
|
||||
if (ignoreFromSet.contains(caller.getEntryPoint())) {
|
||||
continue; // ignore references for a thunk relationship (e.g., jump, etc.)
|
||||
}
|
||||
|
||||
IncomingCallNode node =
|
||||
@@ -116,12 +162,6 @@ public class IncomingCallNode extends CallNode {
|
||||
callTreeOptions);
|
||||
addNode(nodesByFunction, node);
|
||||
}
|
||||
|
||||
List<GTreeNode> children = nodesByFunction.values()
|
||||
.stream()
|
||||
.flatMap(list -> list.stream())
|
||||
.collect(Collectors.toList());
|
||||
results.addAll(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+43
-27
@@ -87,34 +87,19 @@ public class OutgoingCallNode extends CallNode {
|
||||
Function currentFunction = fm.getFunctionContaining(address);
|
||||
LazyMap<Function, List<GTreeNode>> nodesByFunction =
|
||||
LazyMap.lazyMap(new HashMap<>(), k -> new ArrayList<>());
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
ReferenceManager refManager = program.getReferenceManager();
|
||||
|
||||
AddressRangeIterator rangeIter = currentFunction.getBody().getAddressRanges();
|
||||
while (rangeIter.hasNext()) {
|
||||
AddressRange range = rangeIter.next();
|
||||
ReferenceIterator refIter = refManager.getReferenceIterator(range.getMinAddress());
|
||||
while (refIter.hasNext()) {
|
||||
monitor.checkCancelled();
|
||||
Reference reference = refIter.next();
|
||||
if (!range.contains(reference.getFromAddress())) {
|
||||
break; // go to next AddressRange
|
||||
}
|
||||
Address toAddress = reference.getToAddress();
|
||||
Function calledFunction = functionManager.getFunctionAt(toAddress);
|
||||
if (calledFunction == null) {
|
||||
createNode(nodesByFunction, reference, calledFunction);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we are not showing thunks, then replace the thunk with the thunked function
|
||||
if (calledFunction.isThunk() && !callTreeOptions.allowsThunks()) {
|
||||
Function thunkedFunction = calledFunction.getThunkedFunction(true);
|
||||
createNode(nodesByFunction, reference, thunkedFunction);
|
||||
continue;
|
||||
}
|
||||
|
||||
createNode(nodesByFunction, reference, calledFunction);
|
||||
if (currentFunction.isThunk()) {
|
||||
Function thunkedFunction =
|
||||
currentFunction.getThunkedFunction(!callTreeOptions.allowsThunks());
|
||||
ThunkReference thunkRef = new ThunkReference(currentFunction.getEntryPoint(),
|
||||
thunkedFunction.getEntryPoint());
|
||||
createNode(nodesByFunction, thunkRef, thunkedFunction);
|
||||
}
|
||||
else {
|
||||
AddressRangeIterator rangeIter = currentFunction.getBody().getAddressRanges();
|
||||
while (rangeIter.hasNext()) {
|
||||
AddressRange range = rangeIter.next();
|
||||
collectOutgoingByReference(range, nodesByFunction, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +110,37 @@ public class OutgoingCallNode extends CallNode {
|
||||
results.addAll(children);
|
||||
}
|
||||
|
||||
private void collectOutgoingByReference(AddressRange range,
|
||||
LazyMap<Function, List<GTreeNode>> nodesByFunction,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
ReferenceManager refManager = program.getReferenceManager();
|
||||
ReferenceIterator refIter = refManager.getReferenceIterator(range.getMinAddress());
|
||||
while (refIter.hasNext()) {
|
||||
monitor.checkCancelled();
|
||||
Reference reference = refIter.next();
|
||||
if (!range.contains(reference.getFromAddress())) {
|
||||
break; // go to next AddressRange
|
||||
}
|
||||
Address toAddress = reference.getToAddress();
|
||||
Function calledFunction = functionManager.getFunctionAt(toAddress);
|
||||
if (calledFunction == null) {
|
||||
// Assume analysis has not be run fully
|
||||
createNode(nodesByFunction, reference, calledFunction);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we are not showing thunks, then replace the thunk with the thunked function
|
||||
if (calledFunction.isThunk() && !callTreeOptions.allowsThunks()) {
|
||||
Function thunkedFunction = calledFunction.getThunkedFunction(true);
|
||||
createNode(nodesByFunction, reference, thunkedFunction);
|
||||
continue;
|
||||
}
|
||||
|
||||
createNode(nodesByFunction, reference, calledFunction);
|
||||
}
|
||||
}
|
||||
|
||||
private void createNode(LazyMap<Function, List<GTreeNode>> nodes, Reference reference,
|
||||
Function calledFunction) {
|
||||
Address fromAddress = reference.getFromAddress();
|
||||
|
||||
Reference in New Issue
Block a user