GP-3796 allow non-sourced datatypes to become associated to archive

during commit operation.
This commit is contained in:
ghidra1 2023-08-28 20:15:12 -04:00
parent de43ed0656
commit f7ac7388ba
6 changed files with 92 additions and 99 deletions

View file

@ -69,7 +69,7 @@
<TR valign="top">
<TD><B>User Defined</B></TD>
<TD style="">There are four user defined data types: Structures, Unions, Enums, and
<TD>There are four user defined data types: Structures, Unions, Enums, and
Typedefs. They can be created, modified, and renamed as needed.</TD>
</TR>
@ -328,7 +328,7 @@
Archives</B><BR>
</TD>
<TD style="">Files containing data type definitions, which have ".gdt" as their
<TD>Files containing data type definitions, which have ".gdt" as their
file suffix.</TD>
</TR>
@ -336,7 +336,7 @@
<TD style="width: 160px;"><B>Project Data Type Archives</B><BR>
</TD>
<TD style="">Special files located within the Ghidra project directory structure,
<TD>Special files located within the Ghidra project directory structure,
which also contain data type definitions. These are available in the <A href=
"../FrontEndPlugin/Ghidra_Front_end.htm">Ghidra Project Window</A> and can be saved
as versions in a shared project repository.</TD>
@ -592,9 +592,14 @@
none, a message dialog will appear indicating that no changes were detected.</P>
<P><IMG alt="" src="help/shared/note.png">
The source archive must be editable in order to commit File archives must be <A href=
The source archive must be editable in order to commit. File archives must be <A href=
"data_type_manager_description.htm#open_for_editing">open for editing</A> and project
archives that are under version control must be checked-out.</P>
<P><IMG alt="" src="help/shared/note.png">Any data type dependencies for a comitted
data type, which do not already have a source archive, will become associated to the same
source archive.</P>
</BLOCKQUOTE>
<H3>Reverting Changes in an Archive Back To a Source Archive</H3>

View file

@ -12,10 +12,6 @@
</HEAD>
<BODY>
<H1>Data Type Manager Window</H1>
<BLOCKQUOTE>
@ -55,28 +51,28 @@
<TD style="width: 16px;"><IMG alt="" src="images/closedBookBrown.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Built-in archive data types</TD>
<TD>- Built-in archive data types</TD>
</TR>
<TR valign="top">
<TD style="width: 16px;"><IMG alt="" src="images/closedBookRed.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Program data types</TD>
<TD>- Program data types</TD>
</TR>
<TR valign="top">
<TD style="width: 16px;"><IMG alt="" src="images/closedBookBlue.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Project Archive</TD>
<TD>- Project Archive</TD>
</TR>
<TR valign="top">
<TD style="width: 16px;"><IMG alt="" src="images/closedBookGreen.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- File Archive</TD>
<TD>- File Archive</TD>
</TR>
</TBODY>
</TABLE>
@ -91,7 +87,7 @@
<TD style="width: 40px;" align="right" valign="top"><IMG alt="" src=
"images/check.png" style="width: 17px; height: 17px;"></TD>
<TD style="">- Indicates the archive is modifiable by you and possibly by
<TD>- Indicates the archive is modifiable by you and possibly by
others in your shared project</TD>
</TR>
@ -99,14 +95,14 @@
<TD style="width: 40px;" align="right" valign="top"><IMG alt="" src=
"images/checkex.png" style="width: 17px; height: 17px;"></TD>
<TD style="">- Indicates the archive is currently modifiable only by you</TD>
<TD>- Indicates the archive is currently modifiable only by you</TD>
</TR>
<TR valign="top">
<TD style="width: 40px;" align="right" valign="top"><IMG alt="" src=
"images/checkNotLatest.gif" style="width: 16px; height: 16px;"></TD>
<TD style="">- Indicates the archive is out of date (someone has checked
<TD>- Indicates the archive is out of date (someone has checked
changes for this archive into the repository)</TD>
</TR>
@ -114,7 +110,7 @@
<TD style="width: 40px;" align="right" valign="top"><IMG alt="" src=
"images/small_hijack.gif" style="width: 17px; height: 17px;" border="0"></TD>
<TD style="">- Indicates the archive is hijacked (modified without being
<TD>- Indicates the archive is hijacked (modified without being
checked out)</TD>
</TR>
@ -153,7 +149,7 @@
<TD style="width: 40px;" align="right" valign="top"><IMG alt="" src=
"images/doubleArrow.png" style="width: 16px; height: 10px;" border="0"></TD>
<TD style="">- Indicates the archive has datatypes that need updating and
<TD>- Indicates the archive has datatypes that need updating and
datatypes that need to be committed.</TD>
</TR>
</TBODY>
@ -170,63 +166,63 @@
<TD style="width: 25px;"><IMG alt="" src="images/closedFolder.png" style=
"width: 25px; height: 17px;"></TD>
<TD style="">- Category</TD>
<TD>- Category</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/package_development.png"
style="width: 18px; height: 18px;"></TD>
<TD style="">- Built-in data type</TD>
<TD>- Built-in data type</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/cstruct.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Structure</TD>
<TD>- Structure</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/cUnion.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Union</TD>
<TD>- Union</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/typedef.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Typedef</TD>
<TD>- Typedef</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/functionDef.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Function Definition</TD>
<TD>- Function Definition</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/enum.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Enum</TD>
<TD>- Enum</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/fingerPointer.png" style=
"width: 16px; height: 16px;"></TD>
<TD style="">- Pointer</TD>
<TD>- Pointer</TD>
</TR>
<TR valign="top">
<TD style="width: 25px;"><IMG alt="" src="images/emblem-favorite.png" style=
"width: 18px; height: 18px;"></TD>
<TD style="">- Favorite</TD>
<TD>- Favorite</TD>
</TR>
</TBODY>
</TABLE>
@ -241,7 +237,7 @@
<TD style="width: 20px; text-align: center;"><IMG alt="" src=
"images/smallRightArrow.png" style="width: 12px; height: 10px;"></TD>
<TD style="">- Indicates the data type has changes that need to be committed
<TD>- Indicates the data type has changes that need to be committed
to the source archive</TD>
</TR>
@ -249,7 +245,7 @@
<TD style="width: 20px; text-align: center;"><IMG alt="" src=
"images/smallLeftArrow.png" style="width: 12px; height: 10px;"></TD>
<TD style="">- Indicates the data type has been updated in the source archive
<TD>- Indicates the data type has been updated in the source archive
and needs to be updated locally.</TD>
</TR>
@ -257,7 +253,7 @@
<TD style="width: 20px; text-align: center;"><IMG alt="" src=
"images/doubleArrow.png" style="width: 16px; height: 10px;"></TD>
<TD style="">- Indicates the data type has changed both in this archive and
<TD>- Indicates the data type has changed both in this archive and
in the source archive. (conflict)<BR>
</TD>
</TR>
@ -266,7 +262,9 @@
<TD style="width: 20px; text-align: center;"><IMG alt="" src=
"images/redQuestionMark.png"></TD>
<TD style="">- Indicates the data type is missing in the source archive.</TD>
<TD>- Indicates the data type is missing in the source archive. It is important to
note that this determination ibased upon a matching Universal ID and not just
its pathname.</TD>
</TR>
</TBODY>
</TABLE>
@ -409,7 +407,7 @@
Archive...</B><BR>
</TD>
<TD style="">This action will launch a project data type archive chooser that can be
<TD>This action will launch a project data type archive chooser that can be
used to open an existing project archive. Project data type archives live in the
project and can be seen in the <A href=
"../FrontEndPlugin/Ghidra_Front_end.htm">Ghidra Project Window</A>. Project data type
@ -432,7 +430,7 @@
Archive...</B><BR>
</TD>
<TD style="">This action is used to create a new project data type archive. A project
<TD>This action is used to create a new project data type archive. A project
window browser will be launched for choosing a location in the project and a name for
the new project archive.</TD>
</TR>
@ -501,7 +499,7 @@
Paths...</B><BR>
</TD>
<TD style=""><A name="Edit_Archive_Paths"></A>This action will launch a dialog that
<TD><A name="Edit_Archive_Paths"></A>This action will launch a dialog that
can be used to add, remove, or reorder the directories used for searching for a file
archive. Ghidra programs only store the name of the archive. Each directory in the <A
href="data_type_manager_description.htm#file_archive_path">archive path</A> is searched in order, looking for a file

View file

@ -116,6 +116,15 @@ public class DataTypeSynchronizer {
}
public static void commitAssumingTransactionsOpen(DataTypeManager sourceDTM, DataType refDT) {
// Must refresh associations of refDt and its dependencies to ensure that any
// non-sourced datatype is properly associated to the sourceDTM
DataTypeManager refDTM = refDT.getDataTypeManager();
SourceArchive sourceArchive = refDTM.getSourceArchive(sourceDTM.getUniversalID());
refDTM.associateDataTypeWithArchive(refDT, sourceArchive);
// Perform commit of changes by re-resolving and performing additional updates
// not handled by resolve.
long lastChangeTime = refDT.getLastChangeTime();
DataType sourceDT = sourceDTM.resolve(refDT, DataTypeConflictHandler.REPLACE_HANDLER);
if (!namesAreEquivalent(refDT, sourceDT)) {

View file

@ -445,9 +445,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
versionExc = e.combine(versionExc);
}
try {
functionDefAdapter =
FunctionDefinitionDBAdapter.getAdapter(dbHandle, openMode, tablePrefix,
callingConventionAdapter, monitor);
functionDefAdapter = FunctionDefinitionDBAdapter.getAdapter(dbHandle, openMode,
tablePrefix, callingConventionAdapter, monitor);
}
catch (VersionException e) {
versionExc = e.combine(versionExc);
@ -460,9 +459,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
versionExc = e.combine(versionExc);
}
try {
settingsAdapter =
SettingsDBAdapter.getAdapter(tablePrefix + SETTINGS_TABLE_NAME, dbHandle, openMode,
null, monitor);
settingsAdapter = SettingsDBAdapter.getAdapter(tablePrefix + SETTINGS_TABLE_NAME,
dbHandle, openMode, null, monitor);
}
catch (VersionException e) {
versionExc = e.combine(versionExc);
@ -548,9 +546,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
*/
private void initializedParentChildTable() {
buildSortedDataTypeList();
Iterator<DataType> it = sortedDataTypes.iterator();
while (it.hasNext()) {
DataType dt = it.next();
for (DataType dt : sortedDataTypes) {
if (dt instanceof Array) {
((Array) dt).getDataType().addParent(dt);
}
@ -765,9 +761,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
lock.acquire();
try {
Set<String> previouslyUsedSet = previouslyUsedSettingsValuesMap
.computeIfAbsent(settingsDefinition.getStorageKey(),
n -> generateSuggestions(settingsDefinition));
Set<String> previouslyUsedSet = previouslyUsedSettingsValuesMap.computeIfAbsent(
settingsDefinition.getStorageKey(), n -> generateSuggestions(settingsDefinition));
// Last-minute additions are not cached since suggested values may change
Set<String> set = new TreeSet<>(previouslyUsedSet); // copy before updating
settingsDefinition.addPreferredValues(this, set);
@ -1866,8 +1861,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
replacementDt.setLastChangeTime(lastChangeTime);
}
catch (Exception e) {
Msg.error(this, "Unable to set the name to " + existingDt.getName() +
"on " + replacementDt + " while replacing the original datatype", e);
Msg.error(this, "Unable to set the name to " + existingDt.getName() + "on " +
replacementDt + " while replacing the original datatype", e);
}
}
CategoryPath path = existingDt.getCategoryPath();
@ -1878,8 +1873,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
catch (Exception e) {
// not sure what to do here
Msg.error(this, "Unable to set the CatagoryPath to " + path +
"on " + replacementDt + " while replacing the original datatype", e);
Msg.error(this, "Unable to set the CatagoryPath to " + path + "on " +
replacementDt + " while replacing the original datatype", e);
}
}
return replacementDt;
@ -1929,11 +1924,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
else {
buildSortedDataTypeList();
// make copy of sortedDataTypes list before iterating as dt.dataTypeReplaced may
// call back into this class and cause a modification to the sortedDataTypes list.
Iterator<DataType> it = new ArrayList<>(sortedDataTypes).iterator();
while (it.hasNext()) {
DataType dt = it.next();
for (DataType dt : new ArrayList<>(sortedDataTypes)) {
dt.dataTypeReplaced(existingDt, newDt);
}
}
@ -2229,9 +2220,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
deletedIds.addFirst(l);
}
Iterator<Long> it = deletedIds.iterator();
while (it.hasNext()) {
Long l = it.next();
for (Long l : deletedIds) {
deleteDataType(l.longValue());
}
@ -2280,10 +2269,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
throw new IllegalArgumentException(
"The given datatype must exist in this DataTypeManager");
}
if (!datatype.getSourceArchive().equals(getLocalSourceArchive())) {
return;
}
if (datatype.getSourceArchive().equals(archive)) {
SourceArchive currentSource = datatype.getSourceArchive();
if (!currentSource.equals(getLocalSourceArchive()) && !currentSource.equals(archive)) {
return;
}
resolveSourceArchive(archive);
@ -2557,8 +2544,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
@Override
public DataType getDataType(CategoryPath path, String name) {
if (CategoryPath.ROOT.equals(path) &&
name.equals(DataType.DEFAULT.getName())) {
if (CategoryPath.ROOT.equals(path) && name.equals(DataType.DEFAULT.getName())) {
return DataType.DEFAULT;
}
Category category = getCategory(path);
@ -2960,16 +2946,15 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
newDataType = createBuiltIn(builtInDataType, cat);
}
else if (dt instanceof StructureInternal structure) {
newDataType = createStructure(structure, name, cat, sourceArchiveIdValue,
id.getValue());
newDataType =
createStructure(structure, name, cat, sourceArchiveIdValue, id.getValue());
}
else if (dt instanceof TypeDef typedef) {
newDataType =
createTypeDef(typedef, name, cat, sourceArchiveIdValue, id.getValue());
}
else if (dt instanceof UnionInternal union) {
newDataType =
createUnion(union, name, cat, sourceArchiveIdValue, id.getValue());
newDataType = createUnion(union, name, cat, sourceArchiveIdValue, id.getValue());
}
else if (dt instanceof Enum enumm) {
newDataType = createEnum(enumm, name, cat, sourceArchiveIdValue, id.getValue());
@ -2995,8 +2980,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
private Structure createStructure(StructureInternal struct, String name, CategoryDB category,
long sourceArchiveIdValue, long universalIdValue)
throws IOException {
long sourceArchiveIdValue, long universalIdValue) throws IOException {
try {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Data type must have a valid name");
@ -3007,9 +2991,9 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
len = 0;
}
DBRecord record = compositeAdapter.createRecord(name, struct.getDescription(), false,
category.getID(), len, -1, sourceArchiveIdValue,
universalIdValue, struct.getLastChangeTime(),
struct.getStoredPackingValue(), struct.getStoredMinimumAlignment());
category.getID(), len, -1, sourceArchiveIdValue, universalIdValue,
struct.getLastChangeTime(), struct.getStoredPackingValue(),
struct.getStoredMinimumAlignment());
StructureDB structDB =
new StructureDB(this, dtCache, compositeAdapter, componentAdapter, record);
@ -3038,8 +3022,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
private TypeDef createTypeDef(TypeDef typedef, String name, Category cat,
long sourceArchiveIdValue, long universalIdValue)
throws IOException {
long sourceArchiveIdValue, long universalIdValue) throws IOException {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Data type must have a valid name");
}
@ -3067,16 +3050,15 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
private Union createUnion(UnionInternal union, String name, CategoryDB category,
long sourceArchiveIdValue, long universalIdValue)
throws IOException {
long sourceArchiveIdValue, long universalIdValue) throws IOException {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Data type must have a valid name");
}
try {
creatingDataType++;
DBRecord record = compositeAdapter.createRecord(name, null, true, category.getID(), 0,
-1, sourceArchiveIdValue, universalIdValue,
union.getLastChangeTime(), union.getStoredPackingValue(), union.getStoredMinimumAlignment());
-1, sourceArchiveIdValue, universalIdValue, union.getLastChangeTime(),
union.getStoredPackingValue(), union.getStoredMinimumAlignment());
UnionDB unionDB =
new UnionDB(this, dtCache, compositeAdapter, componentAdapter, record);
@ -3110,7 +3092,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
long enumID = record.getKey();
String[] enumNames = enumm.getNames();
for (String enumName : enumNames) {
enumValueAdapter.createRecord(enumID, enumName, enumm.getValue(enumName), enumm.getComment(enumName));
enumValueAdapter.createRecord(enumID, enumName, enumm.getValue(enumName),
enumm.getComment(enumName));
}
EnumDB enumDB = new EnumDB(this, dtCache, enumAdapter, enumValueAdapter, record);
return enumDB;
@ -3318,12 +3301,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
try {
creatingDataType++;
byte callingConventionId =
callingConventionAdapter.getCallingConventionId(funDef.getCallingConventionName(),
cc -> callingConventionNameAdded(cc));
DBRecord record =
functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(),
DEFAULT_DATATYPE_ID, funDef.hasNoReturn(), funDef.hasVarArgs(),
byte callingConventionId = callingConventionAdapter.getCallingConventionId(
funDef.getCallingConventionName(), cc -> callingConventionNameAdded(cc));
DBRecord record = functionDefAdapter.createRecord(name, funDef.getComment(),
cat.getID(), DEFAULT_DATATYPE_ID, funDef.hasNoReturn(), funDef.hasVarArgs(),
callingConventionId, sourceArchiveIdValue, universalIdValue,
funDef.getLastChangeTime());
FunctionDefinitionDB funDefDb =
@ -4192,12 +4173,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
* @param monitor task monitor
* @throws CancelledException if task cancelled
*/
protected void doSourceArchiveUpdates(TaskMonitor monitor)
throws CancelledException {
protected void doSourceArchiveUpdates(TaskMonitor monitor) throws CancelledException {
SourceArchiveUpgradeMap upgradeMap = new SourceArchiveUpgradeMap();
for (SourceArchive sourceArchive : getSourceArchives()) {
SourceArchive mappedSourceArchive =
upgradeMap.getMappedSourceArchive(sourceArchive);
SourceArchive mappedSourceArchive = upgradeMap.getMappedSourceArchive(sourceArchive);
if (mappedSourceArchive != null) {
replaceSourceArchive(sourceArchive, mappedSourceArchive);
}

View file

@ -69,6 +69,7 @@ public final class BuiltInDataTypeManager extends StandAloneDataTypeManager {
initialize();
}
@Override
protected final void setProgramArchitecture(ProgramArchitecture programArchitecture,
VariableStorageManager variableStorageMgr, boolean force, TaskMonitor monitor)
throws IOException, CancelledException {
@ -168,9 +169,8 @@ public final class BuiltInDataTypeManager extends StandAloneDataTypeManager {
if (dataType instanceof BuiltInDataType) {
return DataTypeManager.BUILT_IN_ARCHIVE_UNIVERSAL_ID;
}
throw new IllegalArgumentException(
"Only Built-in data types can be resolved by the " + getClass().getSimpleName() +
" manager.");
throw new IllegalArgumentException("Only Built-in data types can be resolved by the " +
getClass().getSimpleName() + " manager.");
}
@Override

View file

@ -509,7 +509,9 @@ public interface DataTypeManager {
public SourceArchive getLocalSourceArchive();
/**
* Change the given data type so that its source archive is the given archive
* Change the given data type and its dependencies so thier source archive is set to
* given archive. Only those data types not already associated with a source archive
* will be changed.
*
* @param datatype the type
* @param archive the archive