mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GT-3226 - Symbol Table - Performance improvements - review fixes:
convert SymbolRowObject to Symbol
This commit is contained in:
parent
fc67c6aaeb
commit
9e320c6401
33 changed files with 638 additions and 624 deletions
|
@ -217,7 +217,8 @@ public class CodeSymbol extends SymbolDB {
|
|||
*/
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
return SymbolType.LABEL.isValidParent(symbolMgr.getProgram(), parent, address, isExternal());
|
||||
return SymbolType.LABEL.isValidParent(symbolMgr.getProgram(), parent, address,
|
||||
isExternal());
|
||||
|
||||
// if (isExternal() != parent.isExternal()) {
|
||||
// return false;
|
||||
|
@ -241,15 +242,12 @@ public class CodeSymbol extends SymbolDB {
|
|||
// return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
protected String doGetName() {
|
||||
if (getSource() == SourceType.DEFAULT && isExternal()) {
|
||||
return ExternalManagerDB.getDefaultExternalName(this);
|
||||
}
|
||||
return super.getName();
|
||||
return super.doGetName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,7 +33,6 @@ import ghidra.util.Msg;
|
|||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
/**
|
||||
* Symbol class for functions.
|
||||
|
@ -237,11 +236,8 @@ public class FunctionSymbol extends SymbolDB {
|
|||
isExternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
protected String doGetName() {
|
||||
if (getSource() == SourceType.DEFAULT) {
|
||||
if (isExternal()) {
|
||||
return ExternalManagerDB.getDefaultExternalName(this);
|
||||
|
@ -251,17 +247,17 @@ public class FunctionSymbol extends SymbolDB {
|
|||
Symbol thunkedSymbol = getThunkedSymbol();
|
||||
if (thunkedSymbol instanceof FunctionSymbol) {
|
||||
FunctionSymbol thunkedFuncSym = (FunctionSymbol) thunkedSymbol;
|
||||
String name = thunkedFuncSym.getName();
|
||||
String thunkName = thunkedFuncSym.getName();
|
||||
if (thunkedFuncSym.getSource() == SourceType.DEFAULT &&
|
||||
thunkedFuncSym.getThunkedSymbol() == null) {
|
||||
// if thunking a default non-thunk function
|
||||
name = "thunk_" + name;
|
||||
thunkName = "thunk_" + thunkName;
|
||||
}
|
||||
return name;
|
||||
return thunkName;
|
||||
}
|
||||
return SymbolUtilities.getDefaultFunctionName(address);
|
||||
}
|
||||
return super.getName();
|
||||
return super.doGetName();
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
@ -363,7 +359,7 @@ public class FunctionSymbol extends SymbolDB {
|
|||
checkIsValid();
|
||||
Reference[] refs = super.getReferences(monitor);
|
||||
if (monitor == null) {
|
||||
monitor = TaskMonitorAdapter.DUMMY_MONITOR;
|
||||
monitor = TaskMonitor.DUMMY;
|
||||
}
|
||||
if (monitor.isCancelled()) {
|
||||
return refs;
|
||||
|
|
|
@ -54,7 +54,7 @@ public class GlobalVariableSymbolDB extends VariableSymbolDB {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
protected String doGetName() {
|
||||
if (!checkIsValid()) {
|
||||
// TODO: SCR
|
||||
return "[Invalid VariableSymbol - Deleted!]";
|
||||
|
@ -63,7 +63,7 @@ public class GlobalVariableSymbolDB extends VariableSymbolDB {
|
|||
if (storage == null) {
|
||||
return Function.DEFAULT_LOCAL_PREFIX + "_!BAD!";
|
||||
}
|
||||
return super.getName();
|
||||
return super.doGetName();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,11 +30,13 @@ import ghidra.program.model.listing.CircularDependencyException;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ChangeManager;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.Lock;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.UnknownProgressWrappingTaskMonitor;
|
||||
|
||||
/**
|
||||
* Base class for symbols
|
||||
|
@ -43,10 +45,25 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
private Record record;
|
||||
private boolean isDeleting = false;
|
||||
protected String name;
|
||||
protected Address address;
|
||||
protected SymbolManager symbolMgr;
|
||||
protected Lock lock;
|
||||
|
||||
/**
|
||||
* Creates a Symbol that is just a placeholder for use when trying to find symbols by using
|
||||
* {@link Symbol#getID()}. This is useful for locating symbols in Java collections when
|
||||
* a symbol has been deleted and the only remaining information is that symbol's ID.
|
||||
*
|
||||
* @param manager the manager for the new symbol
|
||||
* @param address the address of the symbol
|
||||
* @param id the id of the symbol
|
||||
* @return the fake symbol
|
||||
*/
|
||||
static SymbolDB createSymbolPlaceholder(SymbolManager manager, Address address, long id) {
|
||||
return new PlaceholderSymbolDB(manager, address, id);
|
||||
}
|
||||
|
||||
SymbolDB(SymbolManager symbolMgr, DBObjectCache<SymbolDB> cache, Address address,
|
||||
Record record) {
|
||||
super(cache, record.getKey());
|
||||
|
@ -65,6 +82,11 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
// prefer cached name for speed; it may be stale; call getName() for current value
|
||||
String temp = name;
|
||||
if (temp != null) {
|
||||
return temp;
|
||||
}
|
||||
return getName();
|
||||
}
|
||||
|
||||
|
@ -75,6 +97,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
@Override
|
||||
protected boolean refresh(Record rec) {
|
||||
name = null;
|
||||
if (record != null) {
|
||||
if (rec == null) {
|
||||
rec = symbolMgr.getSymbolRecord(key);
|
||||
|
@ -145,17 +168,29 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
lock.acquire();
|
||||
try {
|
||||
checkIsValid();
|
||||
if (record != null) {
|
||||
return record.getString(SymbolDatabaseAdapter.SYMBOL_NAME_COL);
|
||||
if (name == null) {
|
||||
name = doGetName();
|
||||
}
|
||||
|
||||
return SymbolUtilities.getDynamicName(symbolMgr.getProgram(), address);
|
||||
return name;
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The code for creating the name content for this symbol. This code will be called
|
||||
* with the symbol's lock.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
protected String doGetName() {
|
||||
if (record != null) {
|
||||
return record.getString(SymbolDatabaseAdapter.SYMBOL_NAME_COL);
|
||||
}
|
||||
return SymbolUtilities.getDynamicName(symbolMgr.getProgram(), address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Program getProgram() {
|
||||
return symbolMgr.getProgram();
|
||||
|
@ -238,7 +273,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
try {
|
||||
checkIsValid();
|
||||
if (monitor == null) {
|
||||
monitor = TaskMonitorAdapter.DUMMY_MONITOR;
|
||||
monitor = TaskMonitor.DUMMY;
|
||||
}
|
||||
|
||||
if (monitor.getMaximum() == 0) {
|
||||
|
@ -275,7 +310,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
@Override
|
||||
public Reference[] getReferences() {
|
||||
return getReferences(TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
return getReferences(TaskMonitor.DUMMY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -470,7 +505,11 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
/**
|
||||
* Allow symbol implementations to validate the source when setting the name of
|
||||
* this symbol.
|
||||
* this symbol
|
||||
*
|
||||
* @param newName the new name
|
||||
* @param source the source type
|
||||
* @return the validated source type
|
||||
*/
|
||||
protected SourceType validateNameSource(String newName, SourceType source) {
|
||||
return source;
|
||||
|
@ -482,6 +521,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
lock.acquire();
|
||||
try {
|
||||
name = null;
|
||||
checkDeleted();
|
||||
checkEditOK();
|
||||
|
||||
|
@ -535,6 +575,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
record.setLongValue(SymbolDatabaseAdapter.SYMBOL_PARENT_COL, newNamespace.getID());
|
||||
record.setString(SymbolDatabaseAdapter.SYMBOL_NAME_COL, newName);
|
||||
name = newName;
|
||||
updateSymbolSource(record, source);
|
||||
updateRecord();
|
||||
|
||||
|
@ -613,10 +654,16 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Symbol s = (Symbol) obj;
|
||||
if (getID() == s.getID()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!getName().equals(s.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getAddress().equals(s.getAddress())) {
|
||||
return false;
|
||||
}
|
||||
|
@ -776,6 +823,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
/**
|
||||
* gets the generic symbol data 2 data.
|
||||
* @return the symbol data
|
||||
*/
|
||||
public int getSymbolData2() {
|
||||
lock.acquire();
|
||||
|
@ -852,10 +900,64 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
|
||||
/**
|
||||
* Change the record and key associated with this symbol
|
||||
* @param the record.
|
||||
* @param record the record
|
||||
*/
|
||||
void setRecord(Record record) {
|
||||
this.record = record;
|
||||
keyChanged(record.getKey());
|
||||
}
|
||||
|
||||
private static class PlaceholderSymbolDB extends SymbolDB {
|
||||
|
||||
PlaceholderSymbolDB(SymbolManager symbolMgr, Address address, long key) {
|
||||
super(symbolMgr, null, address, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ((obj == null) || (!(obj instanceof Symbol))) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// this class is only ever equal if the id matches
|
||||
Symbol s = (Symbol) obj;
|
||||
if (getID() == s.getID()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExternal() {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getObject() {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2274,6 +2274,11 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
return new NamespaceDB(s, namespaceMgr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol createSymbolPlaceholder(Address address, long id) {
|
||||
return SymbolDB.createSymbolPlaceholder(this, address, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a symbol, specifying all information for the record. This method is not on the
|
||||
* public interface and is only intended for program API internal use. The user of this
|
||||
|
@ -2675,5 +2680,4 @@ class SymbolMatcher implements Predicate<Symbol> {
|
|||
SymbolType type = s.getSymbolType();
|
||||
return type == type1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
protected String doGetName() {
|
||||
if (!checkIsValid()) {
|
||||
// TODO: SCR
|
||||
return "[Invalid VariableSymbol - Deleted!]";
|
||||
|
@ -213,7 +213,7 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
if (getSource() == SourceType.DEFAULT) {
|
||||
return getParamName();
|
||||
}
|
||||
String storedName = super.getName();
|
||||
String storedName = super.doGetName();
|
||||
if (SymbolUtilities.isDefaultParameterName(storedName)) {
|
||||
return getParamName();
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
// TODO: we use to check for a default name and regenerate new default name but we should
|
||||
// not need to do this if source remains at default
|
||||
|
||||
return super.getName();
|
||||
return super.doGetName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -543,4 +543,15 @@ public interface SymbolTable {
|
|||
public Namespace createNameSpace(Namespace parent, String name, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException;
|
||||
|
||||
/**
|
||||
* Creates a Symbol that is just a placeholder for use when trying to find symbols by using
|
||||
* {@link Symbol#getID()}. This is useful for locating symbols in Java collections when
|
||||
* a symbol has been deleted and the only remaining information is that symbol's ID.
|
||||
*
|
||||
* @param address the address of the symbol
|
||||
* @param id the id of the symbol
|
||||
* @return the fake symbol
|
||||
*/
|
||||
public Symbol createSymbolPlaceholder(Address address, long id);
|
||||
|
||||
}
|
||||
|
|
|
@ -897,7 +897,11 @@ public class SymbolUtilities {
|
|||
if (symbol.isExternal()) {
|
||||
return "External Function";
|
||||
}
|
||||
|
||||
Function func = (Function) symbol.getObject();
|
||||
if (func == null) {
|
||||
return null; // symbol deleted
|
||||
}
|
||||
if (func.isThunk()) {
|
||||
return "Thunk Function";
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue