GP-1073 updating uses of getSymbols(address) to be more efficient where possible

This commit is contained in:
ghidravore 2021-10-06 16:59:58 -04:00
parent e2ea7320e1
commit a8da2b761a
33 changed files with 530 additions and 550 deletions

View file

@ -401,7 +401,7 @@ public class NamespaceUtils {
return null;
}
Symbol[] symbols = program.getSymbolTable().getSymbols(address);
SymbolIterator symbols = program.getSymbolTable().getSymbolsAsIterator(address);
for (Symbol symbol : symbols) {
if (symbol.getSymbolType() == SymbolType.FUNCTION &&
symbolPath.matchesPathOf(symbol)) {

View file

@ -757,16 +757,14 @@ public class PseudoDisassembler {
for (Address flow : flows) {
// does this reference a valid function?
if (program != null) {
Symbol[] syms = program.getSymbolTable().getSymbols(flow);
for (Symbol sym : syms) {
if (sym.getSymbolType() == SymbolType.FUNCTION) {
didCallValidSubroutine = true;
break;
}
Symbol primary = program.getSymbolTable().getPrimarySymbol(flow);
if (primary.getSymbolType() == SymbolType.FUNCTION) {
didCallValidSubroutine = true;
}
}
// if respecting execute flag on memory, test to make sure we did flow into non-execute memory
if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(flow)) {
if (respectExecuteFlag && !execSet.isEmpty() &&
!execSet.contains(flow)) {
if (!flow.isExternalAddress()) {
MemoryBlock block = memory.getBlock(flow);
// flowing into non-executable, but readable memory is bad
@ -782,7 +780,9 @@ public class PseudoDisassembler {
target = newTarget;
}
}
catch (InsufficientBytesException e) {
catch (
InsufficientBytesException e) {
return false;
}
catch (UnknownInstructionException e) {

View file

@ -270,16 +270,21 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
try {
checkIsValid();
ReferenceManager rm = symbolMgr.getReferenceManager();
ReferenceIterator iter = rm.getReferencesTo(address);
boolean isPrimary = this.isPrimary();
Symbol[] symbols = symbolMgr.getSymbols(address);
if (symbols.length == 1) {
// if there is only one symbol, then all the references to this address count
if (hasExactlyOneSymbolAtAddress(address)) {
return rm.getReferenceCountTo(address);
}
// search through references and see which ones apply specifically to this symbol
ReferenceIterator iter = rm.getReferencesTo(address);
int count = 0;
boolean isPrimary = this.isPrimary();
while (iter.hasNext()) {
Reference ref = iter.next();
long symbolID = ref.getSymbolID();
// references refer to me if it matches my key or I'm primary and it doesn't
// specify a specific symbol id
if (symbolID == key || (isPrimary && symbolID < 0)) {
count++;
}
@ -291,6 +296,15 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
}
}
private boolean hasExactlyOneSymbolAtAddress(Address addr) {
SymbolIterator it = symbolMgr.getSymbolsAsIterator(addr);
if (!it.hasNext()) {
return false;
}
it.next();
return !it.hasNext();
}
@Override
public Reference[] getReferences(TaskMonitor monitor) {
lock.acquire();

View file

@ -600,7 +600,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
if (sym.getSymbolType() == SymbolType.FUNCTION) {
Address addr = sym.getAddress();
Function f = (Function) sym.getObject();
Symbol nextPrimary = getNextPrimarySymbol(this, addr);
Symbol nextPrimary = findFirstNonPrimarySymbol(addr);
String name;
Namespace parentNamespace;
SourceType source;
@ -636,20 +636,14 @@ public class SymbolManager implements SymbolTable, ManagerDB {
}
}
// @Override
// public boolean removeSymbol(Symbol sym) {
// return removeSymbolSpecial(sym);
// }
private Symbol getNextPrimarySymbol(SymbolManager sm, Address addr2) {
Symbol[] symbols = sm.getSymbols(addr2);
Symbol next = null;
for (int i = symbols.length - 1; i >= 0; i--) {
if (!symbols[i].isPrimary()) {
return symbols[i]; // For now return the last non-primary found.
private Symbol findFirstNonPrimarySymbol(Address address) {
SymbolIterator it = getSymbolsAsIterator(address);
for (Symbol symbol : it) {
if (!symbol.isPrimary()) {
return symbol; // return the first non-primary symbol we find
}
}
return next;
return null;
}
void removeChildren(SymbolDB sym) {
@ -804,6 +798,21 @@ public class SymbolManager implements SymbolTable, ManagerDB {
return false;
}
public SymbolIterator getSymbolsAsIterator(Address addr) {
lock.acquire();
try {
RecordIterator iterator = adapter.getSymbols(addr, addr, true);
return new SymbolRecordIterator(iterator, true, true);
}
catch (IOException e) {
program.dbError(e);
}
finally {
lock.release();
}
return new SymbolRecordIterator(new EmptyRecordIterator(), true, true);
}
@Override
public Symbol[] getSymbols(Address addr) {
lock.acquire();
@ -932,14 +941,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
@Override
public Symbol getGlobalSymbol(String name, Address addr) {
Symbol[] symbols = getSymbols(addr);
for (Symbol symbol : symbols) {
// there can be only one global symbol with a name at an address
if (symbol.getName().equals(name) && symbol.isGlobal()) {
return symbol;
}
}
return null;
return getSymbol(name, addr, program.getGlobalNamespace());
}
@Override
@ -1714,9 +1716,9 @@ public class SymbolManager implements SymbolTable, ManagerDB {
private void findNextDynamicSymbol() {
while (addrIt.hasNext()) {
Symbol[] symbols = getSymbols(addrIt.next());
if (symbols.length == 1 && symbols[0].isDynamic()) {
nextDynamicSymbol = symbols[0];
Symbol symbol = getPrimarySymbol(addrIt.next());
if (symbol != null && symbol.isDynamic()) {
nextDynamicSymbol = symbol;
return;
}
}
@ -3062,28 +3064,3 @@ public class SymbolManager implements SymbolTable, ManagerDB {
return getFirstSymbol(name, namespace, s -> s.getSymbolType() == type);
}
}
class SymbolMatcher implements Predicate<Symbol> {
private String name;
private Namespace namespace;
private SymbolType type1;
public SymbolMatcher(String name, Namespace namespace, SymbolType type1) {
this.name = name;
this.namespace = namespace;
this.type1 = type1;
}
@Override
public boolean test(Symbol s) {
if (!name.equals(s.getName())) {
return false;
}
if (!namespace.equals(s.getParentNamespace())) {
return false;
}
SymbolType type = s.getSymbolType();
return type == type1;
}
}

View file

@ -353,11 +353,26 @@ public interface SymbolTable {
* the primary symbol will be returned in array slot 0.
* WARNING! Use of this method with a Variable address is highly discouraged since
* a single Variable address could be used multiple times by many functions.
* Note that unless all the symbols are needed at once, you should consider using
* the {@link #getSymbolsAsIterator(Address)} method instead.
* @param addr the address at which to retrieve all symbols.
* @return a zero-length array when no symbols are defined at address.
* @see #getSymbolsAsIterator(Address)
*/
public Symbol[] getSymbols(Address addr);
/**
* Returns a symbol iterator over all the symbols at the given address. Use this instead of
* {@link #getSymbols(Address)} when you do not need to get all symbols, but rather are
* searching for a particular symbol. This method prevents all symbols at the given address
* from being loaded up front.
*
* @param addr the address at which to retrieve all symbols
* @return an iterator over all the symbols at the given address
* @see #getSymbols(Address)
*/
public SymbolIterator getSymbolsAsIterator(Address addr);
/**
* Returns an array of all user defined symbols at the given address
* @param addr the address at which to retrieve all user defined symbols.

View file

@ -1032,7 +1032,7 @@ public class SymbolUtilities {
if (namespace.isGlobal()) {
// do not add global symbol if same name already exists at address
for (Symbol s : program.getSymbolTable().getSymbols(address)) {
for (Symbol s : program.getSymbolTable().getSymbolsAsIterator(address)) {
if (name.equals(s.getName())) {
return null;
}