GP-17 updated FunctionSymbol and SymbolDB to get parent namespace of thunked function for thunks.

This commit is contained in:
ghidra1 2021-06-02 18:02:02 -04:00
parent 2398805b5b
commit a200ecf8f0
6 changed files with 170 additions and 45 deletions

View file

@ -260,6 +260,21 @@ public class FunctionSymbol extends SymbolDB {
return super.doGetName();
}
@Override
protected Namespace doGetParentNamespace() {
// Check for default thunk function which should return the
// parent namespace of the thunked-function
if (getSource() == SourceType.DEFAULT) {
Symbol thunkedSymbol = getThunkedSymbol();
if (thunkedSymbol instanceof FunctionSymbol) {
FunctionSymbol thunkedFuncSym = (FunctionSymbol) thunkedSymbol;
return thunkedFuncSym.getParentNamespace();
}
}
return super.doGetParentNamespace();
}
// @Override
// public void setNameAndNamespace(String newName, Namespace newNamespace, SourceType source)
// throws DuplicateNameException, InvalidInputException, CircularDependencyException {

View file

@ -712,6 +712,10 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
@Override
public Namespace getParentNamespace() {
return doGetParentNamespace();
}
protected Namespace doGetParentNamespace() {
Symbol parent = getParentSymbol();
if (parent != null) {
return (Namespace) parent.getObject();

View file

@ -894,14 +894,22 @@ public class SymbolManager implements SymbolTable, ManagerDB {
*/
private Symbol getSymbol(String name, Address addr, long parentID) {
Symbol[] symbols = getSymbols(addr);
for (Symbol element : symbols) {
if (element.getName().equals(name) && parentID == ((SymbolDB) element).getParentID()) {
return element;
for (Symbol sym : symbols) {
if (parentID != ((SymbolDB) sym).getParentID()) {
continue;
}
if (!isDefaultThunk(sym) && sym.getName().equals(name)) {
return sym;
}
}
return null;
}
private static boolean isDefaultThunk(Symbol sym) {
return sym.getSource() == SourceType.DEFAULT && (sym instanceof FunctionSymbol) &&
((FunctionSymbol) sym).isThunk();
}
@Override
public Symbol getSymbol(String name, Namespace namespace) {
List<Symbol> symbols = getSymbols(name, namespace);
@ -991,7 +999,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
// the specified name.
int count = 0;
List<Symbol> list = new ArrayList<>();
SymbolIterator symbols = getSymbols(name);
SymbolIterator symbols = getSymbols(name); // will not include default thunks
for (Symbol s : symbols) {
if (++count == MAX_DUPLICATE_COUNT && !namespace.isGlobal()) {
return searchSymbolsByNamespaceFirst(name, namespace);
@ -1085,7 +1093,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
public SymbolIterator getSymbols(long namespaceID) {
try {
RecordIterator it = adapter.getSymbolsByNamespace(namespaceID);
return new SymbolRecordIterator(it, true);
return new SymbolRecordIterator(it, false, true);
}
catch (IOException e) {
program.dbError(e);
@ -1228,7 +1236,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
program.dbError(e);
it = new EmptyRecordIterator();
}
return new SymbolRecordIterator(it, forward);
return new SymbolRecordIterator(it, true, forward);
}
@Override
@ -1248,7 +1256,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
public SymbolIterator getSymbolIterator(boolean forward) {
try {
RecordIterator it = adapter.getSymbolsByAddress(forward);
return new SymbolRecordIterator(it, forward);
return new SymbolRecordIterator(it, true, forward);
}
catch (IOException e) {
program.dbError(e);
@ -1260,7 +1268,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
public SymbolIterator getSymbolIterator(String searchStr, boolean caseSensitive) {
try {
RecordIterator iter = adapter.getSymbols();
SymbolIterator symbolIterator = new SymbolRecordIterator(iter, true);
SymbolIterator symbolIterator = new SymbolRecordIterator(iter, false, true);
return new SymbolQueryIterator(symbolIterator, searchStr, caseSensitive);
}
catch (IOException e) {
@ -1694,12 +1702,14 @@ public class SymbolManager implements SymbolTable, ManagerDB {
private class SymbolRecordIterator implements SymbolIterator {
private Symbol nextSymbol;
private RecordIterator it;
private boolean forward;
private final RecordIterator it;
private final boolean includeDefaultThunks;
private final boolean forward;
SymbolRecordIterator(RecordIterator it, boolean forward) {
SymbolRecordIterator(RecordIterator it, boolean includeDefaultThunks, boolean forward) {
this.it = it;
this.includeDefaultThunks = includeDefaultThunks;
this.forward = forward;
}
@ -1711,12 +1721,14 @@ public class SymbolManager implements SymbolTable, ManagerDB {
try {
lock.acquire();
boolean hasNext = forward ? it.hasNext() : it.hasPrevious();
if (hasNext) {
while (nextSymbol == null && (forward ? it.hasNext() : it.hasPrevious())) {
DBRecord rec = forward ? it.next() : it.previous();
nextSymbol = getSymbol(rec);
Symbol sym = getSymbol(rec);
if (includeDefaultThunks || !isDefaultThunk(sym)) {
nextSymbol = sym;
}
}
return hasNext;
return nextSymbol != null;
}
catch (IOException e) {
program.dbError(e);
@ -2013,7 +2025,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
program.dbError(e);
it = new EmptyRecordIterator();
}
return new SymbolRecordIterator(it, true);
return new SymbolRecordIterator(it, true, true);
}
@Override
@ -2058,7 +2070,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
program.dbError(e);
it = new EmptyRecordIterator();
}
return new SymbolRecordIterator(it, true);
return new SymbolRecordIterator(it, true, true); // NOTE: thunks do not exist in external space
}
Lock getLock() {
@ -2069,7 +2081,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
public SymbolIterator getChildren(Symbol parentSymbol) {
try {
RecordIterator it = adapter.getSymbolsByNamespace(parentSymbol.getID());
return new SymbolRecordIterator(it, true);
return new SymbolRecordIterator(it, false, true);
}
catch (IOException e) {
dbError(e);

View file

@ -60,11 +60,11 @@ public interface SymbolTable {
* @param name the name of the symbol.
* @param source the source of this symbol
* <br>Some symbol types, such as function symbols, can set the source to Symbol.DEFAULT.
*
* @return new code or function symbol
* @throws InvalidInputException thrown if names contains white space, is zero length, or is
* null. Also thrown if invalid parentNamespace is specified.
* null for non-default source.
* @throws IllegalArgumentException if you try to set the source to DEFAULT for a symbol type
* that doesn't allow it, or an improper addr if specified
* that doesn't allow it, or an improper addr is specified
*/
public Symbol createLabel(Address addr, String name, SourceType source)
throws InvalidInputException;
@ -91,8 +91,10 @@ public interface SymbolTable {
* @param source the source of this symbol
* <br>Some symbol types, such as function symbols, can set the source to Symbol.DEFAULT.
* @return new code or function symbol
* @throws InvalidInputException thrown if names contains white space, is zero length, or is
* null for non-default source. Also thrown if invalid parentNamespace is specified.
* @throws IllegalArgumentException if you try to set the source to DEFAULT for a symbol type
* that doesn't allow it, or an improper addr if specified
* that doesn't allow it, or an improper addr is specified
*/
public Symbol createLabel(Address addr, String name, Namespace namespace, SourceType source)
throws InvalidInputException;
@ -153,10 +155,13 @@ public interface SymbolTable {
* <P>
* Note that for a symbol to be uniquely specified, all these parameters are required. Any method
* that queries for symbols using just one or two of these parameters will return a list of symbols.
* This method will not return a default thunk (i.e., thunk function symbol with default source type)
* since it mirrors the name and parent namespace of the function it thunks.
* </P>
* @param name the name of the symbol to retrieve
* @param addr the address of the symbol to retrieve
* @param namespace the namespace of the symbol to retrieve. May be null which indicates global namespace.
* @return the symbol which matches the specified crieria or null if not found
* @see #getGlobalSymbol(String, Address) for a convenience method if the namespace is the global namespace.
*/
public Symbol getSymbol(String name, Address addr, Namespace namespace);
@ -168,9 +173,13 @@ public interface SymbolTable {
*
* <P>This is just a convenience method for {@link #getSymbol(String, Address, Namespace)} where
* the namespace is the global namespace.</P>
*
* <p>NOTE: This method will not return a default thunk (i.e., thunk function symbol with default source type)
* since it mirrors the name and parent namespace of the function it thunks.</p>
*
* @param name the name of the symbol to retrieve
* @param addr the address of the symbol to retrieve
* @return the symbol which matches the specified crieria in the global namespace or null if not found
* @see #getSymbol(String, Address, Namespace)
*/
public Symbol getGlobalSymbol(String name, Address addr);
@ -179,8 +188,13 @@ public interface SymbolTable {
* Returns the first symbol with the given name found in the given namespace. Ghidra now
* allows multiple symbols with the same name in the same namespace, so using this method
* is likely to produce unintended results. Use {@link #getSymbols(String, Namespace)} instead.
*
* <p>NOTE: This method will not return a default thunk (i.e.,
* thunk function symbol with default source type).</p>
*
* @param name the name of the symbol to retreive
* @param namespace the namespace of the symbol to retrieve (null assumes global namespace)
* @return the first symbol which satisifies specified criteria or null if not found
* @deprecated This method is no longer useful as Ghidra allows duplicate symbol names in
* the same namespace. Use {@link #getSymbols(String, Namespace)} instead.
* Deprecated in version 7.5, will be removed a few versions later.
@ -191,8 +205,12 @@ public interface SymbolTable {
/**
* Returns the first global symbol that it finds with the given name. Now that Ghidra
* allows duplicate symbol names, this method is practically useless.
*
* <p>NOTE: This method will not return a default thunk (i.e.,
* thunk function symbol with default source type).</p>
*
* @param name the name of the symbol to be retrieved.
* @return symbol, or null if no global symbol has that name
* @return first symbol found with specified name or null if no global symbol has that name
* @deprecated Use {@link #getGlobalSymbols(String)} instead. Ghidra now allows
* multiple symbols in any namespace to have the same name. Deprecated in Ghidra 7.5
* Deprecated in version 7.5, will be removed a few versions later.
@ -202,6 +220,10 @@ public interface SymbolTable {
/**
* Returns a list of all global symbols with the given name.
*
* <p>NOTE: This method will not return default thunks (i.e.,
* thunk function symbol with default source type).</p>
*
* @param name the name of the symbols to retrieve.
* @return a list of all global symbols with the given name.
*/
@ -209,6 +231,10 @@ public interface SymbolTable {
/**
* Returns all the label or function symbols that have the given name in the given namespace.
*
* <p>NOTE: This method will not return a default thunk (i.e., thunk function symbol with default source type)
* since it mirrors the name and parent namespace of the function it thunks.</p>
*
* @param name the name of the symbols to search for.
* @param namespace the namespace to search. If null, then the global namespace is assumed.
* @return a list of all the label or function symbols with the given name in the given namespace.
@ -256,9 +282,13 @@ public interface SymbolTable {
/**
* Returns a list of all symbols with the given name in the given namespace.
*
* <p>NOTE: The resulting iterator will not return default thunks (i.e.,
* thunk function symbol with default source type).</p>
*
* @param name the name of the symbols to retrieve.
* @param namespace the namespace to search for symbols.
* @return
* @return all symbols which satisfy specified criteria
*/
public List<Symbol> getSymbols(String name, Namespace namespace);
@ -283,6 +313,10 @@ public interface SymbolTable {
/**
* Returns all the symbols with the given name.
*
* <p>NOTE: The resulting iterator will not return default thunks (i.e.,
* thunk function symbol with default source type).</p>
*
* @param name the name of symbols to search for.
*
* @return array of symbols with the given name
@ -293,12 +327,14 @@ public interface SymbolTable {
* Returns an iterator over all symbols, including Dynamic symbols if
* includeDynamicSymbols is true.
* @param includeDynamicSymbols if true, the iterator will include dynamicSymbols
* @return symbol iterator
*/
public SymbolIterator getAllSymbols(boolean includeDynamicSymbols);
/**
* Returns the symbol that this reference is associated with.
* @param ref the reference to find the associated symbol for.
* @return referenced symbol
*/
public Symbol getSymbol(Reference ref);
@ -325,18 +361,29 @@ public interface SymbolTable {
/**
* Returns an array of all user defined symbols at the given address
* @param addr the address at which to retrieve all user defined symbols.
* @return all symbols at specified address
*/
public Symbol[] getUserSymbols(Address addr);
/**
* Returns an iterator over all the symbols in the given namespace
*
* <p>NOTE: The resulting iterator will not return default thunks (i.e.,
* thunk function symbol with default source type).</p>
*
* @param namespace the namespace to search for symbols.
* @return symbol iterator
*/
public SymbolIterator getSymbols(Namespace namespace);
/**
* Returns an iterator over all the symbols in the given namespace
*
* <p>NOTE: This method will not return a default thunk (i.e.,
* thunk function symbol with default source type).</p>
*
* @param namespaceID the namespace ID to search for symbols.
* @return symbol iterator
*/
public SymbolIterator getSymbols(long namespaceID);
@ -359,10 +406,15 @@ public interface SymbolTable {
/**
* Returns a an iterator over all symbols that match the given search string.
* NOTE: The iterator is in the forward direction only.
*
* <p>NOTE: The iterator is in the forward direction only and will not return default thunk functions.
* The resulting iterator will not return default thunks (i.e.,
* thunk function symbol with default source type).</p>
*
* @param searchStr the string to search for (may contain * to match any sequence
* or ? to match a single char)
* @param caseSensitive flag to determine if the search is case sensitive or not.
* @return symbol iterator
*/
public SymbolIterator getSymbolIterator(String searchStr, boolean caseSensitive);
@ -371,21 +423,25 @@ public interface SymbolTable {
* @param set the address set in which to look for symbols of the given type
* @param type the SymbolType to look for.
* @param forward the direction within the addressSet to search
* @return symbol iterator
*/
public SymbolIterator getSymbols(AddressSetView set, SymbolType type, boolean forward);
/**
* Returns the total number of symbols in the table.
* @return total number of symbols
*/
public int getNumSymbols();
/**
* Get iterator over all label symbols. Labels are defined on memory locations.
* @return symbol iterator
*/
public SymbolIterator getSymbolIterator();
/**
* Returns an iterator over all defined symbols in no particular order.
* @return symbol iterator
*/
public SymbolIterator getDefinedSymbols();
@ -406,12 +462,14 @@ public interface SymbolTable {
/**
* Returns an iterator over all defined external symbols in no particular order.
* @return symbol iterator
*/
public SymbolIterator getExternalSymbols();
/**
* Returns an iterator over all symbols.
* @param forward true means the iterator is in the forward direction
* @return symbol iterator
*/
public SymbolIterator getSymbolIterator(boolean forward);
@ -420,12 +478,14 @@ public interface SymbolTable {
* the specified <code>startAddr</code>
* @param startAddr the address at which to begin the iteration.
* @param forward true means the iterator is in the forward direction
* @return symbol iterator
*/
public SymbolIterator getSymbolIterator(Address startAddr, boolean forward);
/**
* Get iterator over all primary symbols.
* @param forward true means the iterator is in the forward direction
* @return symbol iterator
*/
public SymbolIterator getPrimarySymbolIterator(boolean forward);
@ -434,6 +494,7 @@ public interface SymbolTable {
* the specified <code>startAddr</code>
* @param startAddr the address at which to begin the iteration.
* @param forward true means the iterator is in the forward direction
* @return symbol iterator
*/
public SymbolIterator getPrimarySymbolIterator(Address startAddr, boolean forward);
@ -441,6 +502,7 @@ public interface SymbolTable {
* Get an iterator over symbols at addresses in the given addressSet
* @param asv the set of address over which to iterate symbols.
* @param forward true means the iterator is in the forward direction
* @return symbol iterator
*/
public SymbolIterator getPrimarySymbolIterator(AddressSetView asv, boolean forward);
@ -459,11 +521,13 @@ public interface SymbolTable {
/**
* Returns true if the given address has been set as an external entry point.
* @param addr address to test for external entry point.
* @return true if specified address has been marked as an entry point, else false
*/
public boolean isExternalEntryPoint(Address addr);
/**
* Get forward/back iterator over addresses that are entry points.
* @return entry-point address iterator
*/
public AddressIterator getExternalEntryPointIterator();
@ -477,23 +541,27 @@ public interface SymbolTable {
/**
* Get an iterator over all the label history objects.
* @return label history iterator
*/
public Iterator<LabelHistory> getLabelHistory();
/**
* Return true if there is a history of label changes at the given address.
* @param addr the address to check for symbol history.
* @return true if label history exists for specified address, else false
*/
public boolean hasLabelHistory(Address addr);
/**
* Returns the lowest level Namespace within which the specified address is contained.
* @param addr the address for which to finds its enclosing namespace.
* @return namespace which contains specified address
*/
public Namespace getNamespace(Address addr);
/**
* Returns all Class Namespaces defined within the program.
* @return iterator of {@link GhidraClass}
*/
public Iterator<GhidraClass> getClassNamespaces();
@ -503,7 +571,8 @@ public interface SymbolTable {
* @param name name of the namespace
* @param source the source of this class namespace's symbol
* @return new class namespace
* @throws DuplicateNameException thrown if another non function or label symbol exists with the given name
* @throws DuplicateNameException thrown if another non function or label symbol
* exists with the given name
* @throws InvalidInputException throw if the name has invalid characters or is null
* @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'.
*/
@ -511,8 +580,13 @@ public interface SymbolTable {
throws DuplicateNameException, InvalidInputException;
/**
* Returns an iterator over all symbols that have the given symbol as its parent..
* Returns an iterator over all symbols that have the given symbol as its parent.
*
* <p>NOTE: The resulting iterator will not return default thunks (i.e.,
* thunk function symbol with default source type).</p>
*
* @param parentSymbol the parent symbol
* @return symbol iterator
*/
public SymbolIterator getChildren(Symbol parentSymbol);
@ -521,8 +595,10 @@ public interface SymbolTable {
* @param name the name of the new Library namespace
* @param source the source of this external library's symbol
* @return the new Library namespace.
* @throws InvalidInputException if the name is invalid.
* @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'.
* @throws DuplicateNameException thrown if another non function or label symbol exists with the given name
* @throws DuplicateNameException thrown if another non function or label
* symbol exists with the given name
*/
public Library createExternalLibrary(String name, SourceType source)
throws DuplicateNameException, InvalidInputException;
@ -533,7 +609,8 @@ public interface SymbolTable {
* @param name the name of the new namespace
* @param source the source of this namespace's symbol
* @return the new Namespace object.
* @throws DuplicateNameException thrown if another non function or label symbol exists with the given name
* @throws DuplicateNameException thrown if another non function or label symbol
* exists with the given name
* @throws InvalidInputException if the name is invalid.
* @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'.
*/