GP-1123 Check for name collision when creating placeholder structure

This commit is contained in:
caheckman 2023-02-09 16:36:23 -05:00
parent bb79314d85
commit 51b1b51d89
4 changed files with 54 additions and 24 deletions

View file

@ -253,8 +253,8 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
DBTraceBookmarkType errType = DBTraceBookmarkType errType =
manager.trace.getBookmarkManager().getOrDefineBookmarkType(BookmarkType.ERROR); manager.trace.getBookmarkManager().getOrDefineBookmarkType(BookmarkType.ERROR);
manager.trace.getBookmarkManager() manager.trace.getBookmarkManager()
.addBookmark(getLifespan(), entryPoint, errType, .addBookmark(getLifespan(), entryPoint, errType, "Bad Variables Removed",
"Bad Variables Removed", "Removed " + badns.size() + " bad variables"); "Removed " + badns.size() + " bad variables");
for (AbstractDBTraceVariableSymbol s : badns) { for (AbstractDBTraceVariableSymbol s : badns) {
s.delete(); s.delete();
} }
@ -366,9 +366,9 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
} }
this.callFixup = newCallFixup; this.callFixup = newCallFixup;
update(FIXUP_COLUMN); update(FIXUP_COLUMN);
manager.trace.setChanged( manager.trace
new TraceChangeRecord<>(TraceFunctionChangeType.CHANGED_CALL_FIXUP, getSpace(), .setChanged(new TraceChangeRecord<>(TraceFunctionChangeType.CHANGED_CALL_FIXUP,
this, oldCallFixup, newCallFixup)); getSpace(), this, oldCallFixup, newCallFixup));
} }
} }
@ -498,8 +498,8 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
} }
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
DBTraceParameterSymbol retVar = getReturn(); DBTraceParameterSymbol retVar = getReturn();
sb.append((formalSignature ? retVar.getFormalDataType() sb.append((formalSignature ? retVar.getFormalDataType() : retVar.getDataType())
: retVar.getDataType()).getDisplayName()); .getDisplayName());
sb.append(' '); sb.append(' ');
if (includeCallingConvention && hasExplicitCallingConvention()) { if (includeCallingConvention && hasExplicitCallingConvention()) {
String cc = getCallingConventionName(); String cc = getCallingConventionName();
@ -1626,9 +1626,9 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
else { else {
andFlags(NO_RETURN_CLEAR); andFlags(NO_RETURN_CLEAR);
} }
manager.trace.setChanged( manager.trace
new TraceChangeRecord<>(TraceFunctionChangeType.CHANGED_NORETURN, getSpace(), this, .setChanged(new TraceChangeRecord<>(TraceFunctionChangeType.CHANGED_NORETURN,
!hasNoReturn, hasNoReturn)); getSpace(), this, !hasNoReturn, hasNoReturn));
} }
} }
@ -1833,9 +1833,11 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
// NOTE: Check for existence first, to avoid resolving unnecessarily. // NOTE: Check for existence first, to avoid resolving unnecessarily.
// TODO: If ever struct-class are strongly related, fix that here, too. // TODO: If ever struct-class are strongly related, fix that here, too.
classStruct = VariableUtilities.findOrCreateClassStruct((GhidraClass) parentNS, dtm); classStruct = VariableUtilities.findOrCreateClassStruct((GhidraClass) parentNS, dtm);
if (classStruct != null) {
dtm.resolve(classStruct, null); dtm.resolve(classStruct, null);
} }
} }
}
@Override @Override
public boolean isThunk() { public boolean isThunk() {
@ -1858,8 +1860,7 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
} }
private List<Address> getFunctionThunkAddresses(long functionKey, boolean recursive) { private List<Address> getFunctionThunkAddresses(long functionKey, boolean recursive) {
Collection<DBTraceFunctionSymbol> thunkSymbols = Collection<DBTraceFunctionSymbol> thunkSymbols = manager.functionsByThunked.get(getKey());
manager.functionsByThunked.get(getKey());
if (thunkSymbols == null || thunkSymbols.isEmpty()) { if (thunkSymbols == null || thunkSymbols.isEmpty()) {
return null; return null;
} }
@ -1916,8 +1917,7 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
try (LockHold hold = LockHold.lock(manager.lock.readLock())) { try (LockHold hold = LockHold.lock(manager.lock.readLock())) {
Set<Function> result = new HashSet<>(); Set<Function> result = new HashSet<>();
for (DBTraceReference ref : manager.trace.getReferenceManager() for (DBTraceReference ref : manager.trace.getReferenceManager()
.getReferencesToRange( .getReferencesToRange(lifespan, new AddressRangeImpl(entryPoint, entryPoint))) {
lifespan, new AddressRangeImpl(entryPoint, entryPoint))) {
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
break; break;
} }
@ -1942,8 +1942,7 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
Set<Function> result = new HashSet<>(); Set<Function> result = new HashSet<>();
for (AddressRange rng : getBody()) { for (AddressRange rng : getBody()) {
for (DBTraceReference ref : manager.trace.getReferenceManager() for (DBTraceReference ref : manager.trace.getReferenceManager()
.getReferencesFromRange( .getReferencesFromRange(lifespan, rng)) {
lifespan, rng)) {
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
return result; return result;
} }

View file

@ -516,6 +516,9 @@ public class FillOutStructureCmd extends BackgroundCommand {
return null; return null;
} }
Structure structDT = VariableUtilities.findOrCreateClassStruct(f); Structure structDT = VariableUtilities.findOrCreateClassStruct(f);
if (structDT == null) {
return null;
}
// FIXME: How should an existing packed structure be handled? Growing and offset-based placement does not apply // FIXME: How should an existing packed structure be handled? Growing and offset-based placement does not apply
int len = structDT.isZeroLength() ? 0 : structDT.getLength(); int len = structDT.isZeroLength() ? 0 : structDT.getLength();
if (len < size) { if (len < size) {

View file

@ -209,7 +209,7 @@ public class FunctionDB extends DatabaseObject implements Function {
@Override @Override
public ExternalLocation getExternalLocation() { public ExternalLocation getExternalLocation() {
if (isExternal()) { if (isExternal()) {
ExternalManagerDB extMgr = (ExternalManagerDB) program.getExternalManager(); ExternalManagerDB extMgr = program.getExternalManager();
return extMgr.getExternalLocation(getSymbol()); return extMgr.getExternalLocation(getSymbol());
} }
return null; return null;
@ -993,7 +993,7 @@ public class FunctionDB extends DatabaseObject implements Function {
v.setStorageAndDataType(storage, var.getDataType()); v.setStorageAndDataType(storage, var.getDataType());
} }
else { else {
SymbolManager symbolMgr = (SymbolManager) program.getSymbolTable(); SymbolManager symbolMgr = program.getSymbolTable();
VariableSymbolDB s = symbolMgr.createVariableSymbol(name, this, VariableSymbolDB s = symbolMgr.createVariableSymbol(name, this,
SymbolType.LOCAL_VAR, firstUseOffset, storage, source); SymbolType.LOCAL_VAR, firstUseOffset, storage, source);
s.setStorageAndDataType(storage, var.getDataType()); s.setStorageAndDataType(storage, var.getDataType());
@ -1460,7 +1460,7 @@ public class FunctionDB extends DatabaseObject implements Function {
} }
// Append new parameters if needed // Append new parameters if needed
SymbolManager symbolMgr = (SymbolManager) program.getSymbolTable(); SymbolManager symbolMgr = program.getSymbolTable();
for (int i = newParamIndex; i < newParams.size(); i++) { for (int i = newParamIndex; i < newParams.size(); i++) {
Variable newParam = newParams.get(i); Variable newParam = newParams.get(i);
DataType dt = (newParam instanceof Parameter && !useCustomStorage) DataType dt = (newParam instanceof Parameter && !useCustomStorage)
@ -1683,7 +1683,7 @@ public class FunctionDB extends DatabaseObject implements Function {
} }
} }
} }
SymbolManager symbolMgr = (SymbolManager) program.getSymbolTable(); SymbolManager symbolMgr = program.getSymbolTable();
VariableSymbolDB s = symbolMgr.createVariableSymbol(name, this, VariableSymbolDB s = symbolMgr.createVariableSymbol(name, this,
SymbolType.PARAMETER, ordinal, storage, paramSource); SymbolType.PARAMETER, ordinal, storage, paramSource);
s.setStorageAndDataType(storage, var.getDataType()); s.setStorageAndDataType(storage, var.getDataType());
@ -2671,9 +2671,11 @@ public class FunctionDB extends DatabaseObject implements Function {
// relationship between a class namespace and its structure is needed // relationship between a class namespace and its structure is needed
// so its name and category can track properly. // so its name and category can track properly.
classStruct = VariableUtilities.findOrCreateClassStruct(this); classStruct = VariableUtilities.findOrCreateClassStruct(this);
if (classStruct != null) {
dataTypeManager.resolve(classStruct, null); dataTypeManager.resolve(classStruct, null);
} }
} }
}
void dataTypeChanged(VariableDB var) { void dataTypeChanged(VariableDB var) {
manager.functionChanged(this, manager.functionChanged(this,

View file

@ -750,17 +750,37 @@ public class VariableUtilities {
* Create an empty placeholder class structure whose category is derived from * Create an empty placeholder class structure whose category is derived from
* the function's class namespace. NOTE: The structure will not be added to the data * the function's class namespace. NOTE: The structure will not be added to the data
* type manager. * type manager.
* The structure is created in the program's preferred category, or in the root category
* if a preferred category has not been set. If a colliding data-type matching the class name
* and category already exists, null is returned.
* @param classNamespace class namespace * @param classNamespace class namespace
* @param dataTypeManager data type manager's whose data organization should be applied. * @param dataTypeManager data type manager's whose data organization should be applied.
* @return new class structure * @return new class structure (or null if there is a collision)
*/ */
private static Structure createPlaceholderClassStruct(GhidraClass classNamespace, private static Structure createPlaceholderClassStruct(GhidraClass classNamespace,
DataTypeManager dataTypeManager) { DataTypeManager dataTypeManager) {
Namespace classParentNamespace = classNamespace.getParentNamespace(); Namespace classParentNamespace = classNamespace.getParentNamespace();
CategoryPath prefRoot = null;
if (dataTypeManager instanceof ProgramBasedDataTypeManager) {
prefRoot = ((ProgramBasedDataTypeManager) dataTypeManager).getProgram()
.getPreferredRootNamespaceCategoryPath();
}
if (prefRoot == null) {
prefRoot = CategoryPath.ROOT;
}
CategoryPath category = CategoryPath category =
DataTypeUtilities.getDataTypeCategoryPath(CategoryPath.ROOT, classParentNamespace); DataTypeUtilities.getDataTypeCategoryPath(prefRoot, classParentNamespace);
DataType existingDT = dataTypeManager.getDataType(category, classNamespace.getName());
if (existingDT != null) {
// If a data-type already exists in the parent, try to create in the child
category = DataTypeUtilities.getDataTypeCategoryPath(prefRoot, classNamespace);
existingDT = dataTypeManager.getDataType(category, classNamespace.getName());
if (existingDT != null) { // If this also already exists
return null; // Don't create a placeholder
}
}
StructureDataType structDT = StructureDataType structDT =
new StructureDataType(category, classNamespace.getName(), 0, dataTypeManager); new StructureDataType(category, classNamespace.getName(), 0, dataTypeManager);
structDT.setDescription("PlaceHolder Class Structure"); structDT.setDescription("PlaceHolder Class Structure");
@ -782,6 +802,9 @@ public class VariableUtilities {
* and may refer to a non-existing category path which corresponds to the class-parent's * and may refer to a non-existing category path which corresponds to the class-parent's
* namespace. * namespace.
* *
* If an unrelated data-type already exists matching the class name and category,
* null is returned.
*
* @param classNamespace class namespace * @param classNamespace class namespace
* @param dataTypeManager data type manager which should be searched and whose * @param dataTypeManager data type manager which should be searched and whose
* data organization should be used. * data organization should be used.
@ -811,6 +834,9 @@ public class VariableUtilities {
* and may refer to a non-existing category path which corresponds to the class-parent's * and may refer to a non-existing category path which corresponds to the class-parent's
* namespace. * namespace.
* *
* If the function is not part of a class, or if an unrelated data-type already exists with
* the class's name and category, null is returned.
*
* @param function function's whose class namespace is the basis for the structure * @param function function's whose class namespace is the basis for the structure
* @return new or existing structure whose name matches the function's class namespace or * @return new or existing structure whose name matches the function's class namespace or
* null if function not contained within a class namespace. * null if function not contained within a class namespace.