mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-1073 updating uses of getSymbols(address) to be more efficient where possible
This commit is contained in:
parent
e2ea7320e1
commit
a8da2b761a
33 changed files with 530 additions and 550 deletions
|
@ -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)) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue