mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-1692 added recursive form of Function.getFunctionThunkAddresses method
This commit is contained in:
parent
66c0b49b87
commit
c34a26c24b
6 changed files with 74 additions and 22 deletions
|
@ -1847,12 +1847,31 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Address> getFunctionThunkAddresses(long functionKey, boolean recursive) {
|
||||||
|
Collection<DBTraceFunctionSymbol> thunkSymbols =
|
||||||
|
manager.functionsByThunked.get(getKey());
|
||||||
|
if (thunkSymbols == null || thunkSymbols.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Address> result = new ArrayList<>();
|
||||||
|
for (DBTraceFunctionSymbol thunkSymbol : thunkSymbols) {
|
||||||
|
result.add(thunkSymbol.entryPoint);
|
||||||
|
if (recursive) {
|
||||||
|
List<Address> thunkAddrs = getFunctionThunkAddresses(thunkSymbol.getKey(), true);
|
||||||
|
if (thunkAddrs != null) {
|
||||||
|
result.addAll(thunkAddrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address[] getFunctionThunkAddresses() {
|
public Address[] getFunctionThunkAddresses(boolean recursive) {
|
||||||
try (LockHold hold = LockHold.lock(manager.lock.readLock())) {
|
try (LockHold hold = LockHold.lock(manager.lock.readLock())) {
|
||||||
List<Address> result = new ArrayList<>();
|
List<Address> result = getFunctionThunkAddresses(getKey(), recursive);
|
||||||
for (DBTraceFunctionSymbol thunk : manager.functionsByThunked.get(getKey())) {
|
if (result == null) {
|
||||||
result.add(thunk.entryPoint);
|
return null;
|
||||||
}
|
}
|
||||||
return result.toArray(new Address[result.size()]);
|
return result.toArray(new Address[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,7 +555,7 @@ public class UndefinedFunction implements Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address[] getFunctionThunkAddresses() {
|
public Address[] getFunctionThunkAddresses(boolean recursive) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1883,13 +1883,15 @@ public class FunctionDBTest extends AbstractGhidraHeadedIntegrationTest
|
||||||
|
|
||||||
Function f1 = createFunction("foo1", addr(0x100), new AddressSet(addr(0x100), addr(0x200)));
|
Function f1 = createFunction("foo1", addr(0x100), new AddressSet(addr(0x100), addr(0x200)));
|
||||||
assertTrue(!f1.isThunk());
|
assertTrue(!f1.isThunk());
|
||||||
assertNull(f1.getThunkedFunction(false));
|
assertNull(f1.getThunkedFunction(true));
|
||||||
|
assertNull(f1.getFunctionThunkAddresses(true));
|
||||||
|
|
||||||
Function f2 = functionManager.createFunction(null, addr(0x300),
|
Function f2 = functionManager.createFunction(null, addr(0x300),
|
||||||
new AddressSet(addr(0x300), addr(0x400)), SourceType.DEFAULT);
|
new AddressSet(addr(0x300), addr(0x400)), SourceType.DEFAULT);
|
||||||
assertEquals("FUN_00000300", f2.getName());
|
assertEquals("FUN_00000300", f2.getName());
|
||||||
assertTrue(!f2.isThunk());
|
assertTrue(!f2.isThunk());
|
||||||
assertNull(f2.getThunkedFunction(false));
|
assertNull(f2.getThunkedFunction(true));
|
||||||
|
assertNull(f2.getFunctionThunkAddresses(true));
|
||||||
|
|
||||||
f1.setReturn(ByteDataType.dataType, VariableStorage.UNASSIGNED_STORAGE,
|
f1.setReturn(ByteDataType.dataType, VariableStorage.UNASSIGNED_STORAGE,
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
|
@ -1933,7 +1935,11 @@ public class FunctionDBTest extends AbstractGhidraHeadedIntegrationTest
|
||||||
|
|
||||||
assertEquals("foo1", f2.getName());
|
assertEquals("foo1", f2.getName());
|
||||||
assertTrue(f2.isThunk());
|
assertTrue(f2.isThunk());
|
||||||
assertEquals(f1, f2.getThunkedFunction(false));
|
assertEquals(f1, f2.getThunkedFunction(true));
|
||||||
|
|
||||||
|
Address[] thunkAddresses = f1.getFunctionThunkAddresses(true);
|
||||||
|
assertNotNull(thunkAddresses);
|
||||||
|
assertArrayEquals(new Address[] { f2.getEntryPoint() }, thunkAddresses);
|
||||||
|
|
||||||
assertEquals("byte foo1(int p1, int p2)", f1.getPrototypeString(false, false));
|
assertEquals("byte foo1(int p1, int p2)", f1.getPrototypeString(false, false));
|
||||||
assertEquals("byte foo1(int p1, int p2)", f2.getPrototypeString(false, false));// TODO: Not sure what the correct behavior should be?
|
assertEquals("byte foo1(int p1, int p2)", f2.getPrototypeString(false, false));// TODO: Not sure what the correct behavior should be?
|
||||||
|
|
|
@ -165,23 +165,36 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Address> getFunctionThunkAddresses(long functionId, boolean recursive) {
|
||||||
|
List<Long> functionIds = manager.getThunkFunctionIds(functionId);
|
||||||
|
if (functionIds == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SymbolTable symMgr = program.getSymbolTable();
|
||||||
|
List<Address> thunkAddrList = new ArrayList<>();
|
||||||
|
for (long id : functionIds) {
|
||||||
|
Symbol s = symMgr.getSymbol(id);
|
||||||
|
thunkAddrList.add(s.getAddress());
|
||||||
|
if (recursive) {
|
||||||
|
List<Address> thunkAddrs = getFunctionThunkAddresses(id, true);
|
||||||
|
if (thunkAddrs != null) {
|
||||||
|
thunkAddrList.addAll(thunkAddrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return thunkAddrList;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address[] getFunctionThunkAddresses() {
|
public Address[] getFunctionThunkAddresses(boolean recursive) {
|
||||||
manager.lock.acquire();
|
manager.lock.acquire();
|
||||||
try {
|
try {
|
||||||
checkIsValid();
|
checkIsValid();
|
||||||
List<Long> functionIds = manager.getThunkFunctionIds(key);
|
List<Address> thunkAddrList = getFunctionThunkAddresses(key, recursive);
|
||||||
if (functionIds == null) {
|
if (thunkAddrList == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SymbolTable symMgr = program.getSymbolTable();
|
return thunkAddrList.toArray(new Address[thunkAddrList.size()]);
|
||||||
Address[] addresses = new Address[functionIds.size()];
|
|
||||||
int index = 0;
|
|
||||||
for (long functionId : functionIds) {
|
|
||||||
Symbol s = symMgr.getSymbol(functionId);
|
|
||||||
addresses[index++] = s.getAddress();
|
|
||||||
}
|
|
||||||
return addresses;
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
manager.lock.release();
|
manager.lock.release();
|
||||||
|
|
|
@ -661,10 +661,24 @@ public interface Function extends Namespace {
|
||||||
public Function getThunkedFunction(boolean recursive);
|
public Function getThunkedFunction(boolean recursive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this function is "Thunked", an array of Thunk Function entry points is returned
|
* If this function is "Thunked", an array of Thunk Function entry points is returned.
|
||||||
|
* A non-recursive search is performed (i.e., first-hop only).
|
||||||
|
* @return associated thunk function entry points or null if this is not a "Thunked" function.
|
||||||
|
* @deprecated since many use cases will likely want a complete list of thunk functions
|
||||||
|
* a recursive search is generally needed (see {@link #getFunctionThunkAddresses(boolean)}).
|
||||||
|
* This method form may be removed in a future release.
|
||||||
|
*/
|
||||||
|
public default Address[] getFunctionThunkAddresses() {
|
||||||
|
return getFunctionThunkAddresses(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this function is "Thunked", an array of Thunk Function entry points is returned.
|
||||||
|
* @param recursive if true a recursive search is performed returning all effective thunks
|
||||||
|
* of this function, else if false only the first-hop (i.e., direct thunks) are returned.
|
||||||
* @return associated thunk function entry points or null if this is not a "Thunked" function.
|
* @return associated thunk function entry points or null if this is not a "Thunked" function.
|
||||||
*/
|
*/
|
||||||
public Address[] getFunctionThunkAddresses();
|
public Address[] getFunctionThunkAddresses(boolean recursive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the currently Thunked Function or null to convert to a normal function
|
* Set the currently Thunked Function or null to convert to a normal function
|
||||||
|
|
|
@ -407,7 +407,7 @@ public class FunctionTestDouble implements Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address[] getFunctionThunkAddresses() {
|
public Address[] getFunctionThunkAddresses(boolean recursive) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue