mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
GP-1618 Improved DataType.getParents to avoid returning duplicates for DB case which is used during change notification processing.
This commit is contained in:
parent
948e4edeb1
commit
87cc46efa2
11 changed files with 91 additions and 47 deletions
|
@ -17,8 +17,7 @@ package ghidra.program.database.data;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.docking.settings.Settings;
|
||||
|
@ -452,10 +451,8 @@ abstract class DataTypeDB extends DatabaseObject implements DataType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataType[] getParents() {
|
||||
List<DataType> parents = dataMgr.getParentDataTypes(key);
|
||||
DataType[] array = new DataType[parents.size()];
|
||||
return parents.toArray(array);
|
||||
public Collection<DataType> getParents() {
|
||||
return dataMgr.getParentDataTypes(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1350,8 +1350,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
|
||||
private void replaceUsesInOtherDataTypes(DataType existingDt, DataType newDt) {
|
||||
if (existingDt instanceof DataTypeDB) {
|
||||
DataType[] dts = existingDt.getParents();
|
||||
for (DataType dt : dts) {
|
||||
for (DataType dt : existingDt.getParents()) {
|
||||
dt.dataTypeReplaced(existingDt, newDt);
|
||||
}
|
||||
}
|
||||
|
@ -3482,12 +3481,14 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
}
|
||||
}
|
||||
|
||||
List<DataType> getParentDataTypes(long childID) {
|
||||
List<DataType> getParentDataTypes(long dataTypeId) {
|
||||
lock.acquire();
|
||||
try {
|
||||
long[] ids = parentChildAdapter.getParentIds(childID);
|
||||
Set<Long> parentIds = parentChildAdapter.getParentIds(dataTypeId);
|
||||
// NOTE: Use of Set for containing datatypes is avoided due to the excessive
|
||||
// overhead of DataType.equals
|
||||
List<DataType> dts = new ArrayList<>();
|
||||
for (long id : ids) {
|
||||
for (long id : parentIds) {
|
||||
DataType dt = getDataType(id);
|
||||
if (dt == null) {
|
||||
// cleanup invalid records for missing parent
|
||||
|
@ -3498,7 +3499,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
}
|
||||
}
|
||||
return dts;
|
||||
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
|
@ -3509,6 +3509,52 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: method use should be avoided since use of a Set for containing
|
||||
* datatypes can cause use of DataType.equals method which should
|
||||
* be avoided for performance reasons.
|
||||
* @param dataTypeId id of datatype whose parents should be found
|
||||
* @return set of known parent datatypes
|
||||
*/
|
||||
@Deprecated
|
||||
Set<DataType> getParentDataTypeSet(long dataTypeId) {
|
||||
lock.acquire();
|
||||
try {
|
||||
Set<Long> parentIds = parentChildAdapter.getParentIds(dataTypeId);
|
||||
Set<DataType> dts = new HashSet<>();
|
||||
for (long id : parentIds) {
|
||||
DataType dt = getDataType(id);
|
||||
if (dt == null) {
|
||||
// cleanup invalid records for missing parent
|
||||
attemptRecordRemovalForParent(id);
|
||||
}
|
||||
else {
|
||||
dts.add(dt);
|
||||
}
|
||||
}
|
||||
return dts;
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<DataType> getDataTypesContaining(DataType dataType) {
|
||||
if (dataType instanceof DataTypeDB) {
|
||||
DataTypeDB dataTypeDb = (DataTypeDB) dataType;
|
||||
if (dataTypeDb.getDataTypeManager() != this) {
|
||||
return Set.of();
|
||||
}
|
||||
return getParentDataTypeSet(dataTypeDb.getKey());
|
||||
}
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
private void attemptRecordRemovalForParent(long parentKey) throws IOException {
|
||||
lock.acquire();
|
||||
try {
|
||||
|
@ -3521,24 +3567,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<DataType> getDataTypesContaining(DataType dataType) {
|
||||
Set<DataType> set = new HashSet<>();
|
||||
if (dataType instanceof DataTypeDB) {
|
||||
long dataTypeID = ((DataTypeDB) dataType).getKey();
|
||||
try {
|
||||
long[] ids = parentChildAdapter.getParentIds(dataTypeID);
|
||||
for (long id : ids) {
|
||||
set.add(getDataType(id));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
dbError(e);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointer getPointer(DataType dt) {
|
||||
return new PointerDataType(dt, -1, this);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import db.DBConstants;
|
||||
import db.DBHandle;
|
||||
|
@ -71,7 +72,15 @@ abstract class ParentChildAdapter {
|
|||
|
||||
abstract void removeRecord(long parentID, long childID) throws IOException;
|
||||
|
||||
abstract long[] getParentIds(long childID) throws IOException;
|
||||
/**
|
||||
* Get the unique set of parent ID associated with the specified childID.
|
||||
* Since composite parents may have duplicate parent-child records, this method
|
||||
* avoids returning the same parent more than once.
|
||||
* @param childID child datatype ID
|
||||
* @return set of parent datatype IDs
|
||||
* @throws IOException if a DB IO error occurs
|
||||
*/
|
||||
abstract Set<Long> getParentIds(long childID) throws IOException;
|
||||
|
||||
abstract void removeAllRecordsForParent(long parentID) throws IOException;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import db.DBHandle;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
@ -43,8 +44,8 @@ class ParentChildDBAdapterNoTable extends ParentChildAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
long[] getParentIds(long childID) throws IOException {
|
||||
return new long[0];
|
||||
Set<Long> getParentIds(long childID) throws IOException {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
package ghidra.program.database.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import db.*;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
@ -73,12 +75,12 @@ class ParentChildDBAdapterV0 extends ParentChildAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
long[] getParentIds(long childID) throws IOException {
|
||||
Set<Long> getParentIds(long childID) throws IOException {
|
||||
Field[] ids = table.findRecords(new LongField(childID), CHILD_COL);
|
||||
long[] parentIds = new long[ids.length];
|
||||
Set<Long> parentIds = new HashSet<>(ids.length);
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
DBRecord rec = table.getRecord(ids[i]);
|
||||
parentIds[i] = rec.getLongValue(PARENT_COL);
|
||||
parentIds.add(rec.getLongValue(PARENT_COL));
|
||||
}
|
||||
return parentIds;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.program.model.data;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
|
@ -170,7 +171,7 @@ public abstract class AbstractDataType implements DataType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataType[] getParents() {
|
||||
public Collection<DataType> getParents() {
|
||||
// not-applicable
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.program.model.data;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
|
@ -484,11 +485,13 @@ public interface DataType {
|
|||
public void dataTypeNameChanged(DataType dt, String oldName);
|
||||
|
||||
/**
|
||||
* Get the parents of this datatype
|
||||
*
|
||||
* @return an array of parents of this datatype
|
||||
* Get the parents of this datatype.
|
||||
*
|
||||
* NOTE: This method is intended to be used on a DB-managed datatype only and is not
|
||||
* fully supported for use with non-DB datatype instances.
|
||||
* @return parents of this datatype
|
||||
*/
|
||||
public DataType[] getParents();
|
||||
public Collection<DataType> getParents();
|
||||
|
||||
/**
|
||||
* Gets the alignment to be used when aligning this datatype within another datatype.
|
||||
|
|
|
@ -120,7 +120,7 @@ public abstract class DataTypeImpl extends AbstractDataType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataType[] getParents() {
|
||||
public Collection<DataType> getParents() {
|
||||
List<DataType> parents = new ArrayList<>();
|
||||
Iterator<WeakReference<DataType>> iterator = parentList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
|
@ -133,8 +133,7 @@ public abstract class DataTypeImpl extends AbstractDataType {
|
|||
parents.add(dataType);
|
||||
}
|
||||
}
|
||||
DataType[] array = new DataType[parents.size()];
|
||||
return parents.toArray(array);
|
||||
return parents;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -530,8 +530,12 @@ public interface DataTypeManager {
|
|||
|
||||
/**
|
||||
* Returns the data types within this data type manager that contain the specified data type.
|
||||
* The specified dataType must belong to this datatype manager. An empty set will be
|
||||
* returned for unsupported datatype instances.
|
||||
* @param dataType the data type
|
||||
* @return a set of data types that contain the specified data type.
|
||||
* @deprecated the method {@link DataType#getParents()} should be used instead.
|
||||
* Use of {@link Set} implementations for containing DataTypes is also inefficient.
|
||||
*/
|
||||
public Set<DataType> getDataTypesContaining(DataType dataType);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.program.model.data;
|
|||
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.docking.settings.SettingsDefinition;
|
||||
|
@ -254,7 +255,7 @@ public class StubDataType implements DataType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataType[] getParents() {
|
||||
public Collection<DataType> getParents() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue