Merge remote-tracking branch 'origin/GP-5205_ghidra1_ProgramUserDataIssues' into Ghidra_11.3

This commit is contained in:
Ryan Kurtz 2025-01-22 13:17:46 -05:00
commit afe96c0309
4 changed files with 78 additions and 6 deletions

View file

@ -28,6 +28,7 @@ import ghidra.framework.model.ChangeSet;
import ghidra.framework.model.DomainObject;
import ghidra.framework.store.*;
import ghidra.framework.store.local.LocalDatabaseItem;
import ghidra.program.model.lang.LanguageNotFoundException;
import ghidra.util.InvalidNameException;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
@ -232,9 +233,25 @@ public class ProgramContentHandler extends DBWithUserDataContentHandler<ProgramD
DBHandle userDbh =
openAssociatedUserFile(programItem.getFileID(), PROGRAM_CONTENT_TYPE, userfs, monitor);
if (userDbh != null) {
return new ProgramUserDataDB(userDbh, program, monitor);
boolean success = false;
try {
ProgramUserDataDB data = new ProgramUserDataDB(userDbh, program, monitor);
success = true;
return data;
}
catch (LanguageNotFoundException | IllegalStateException e) {
// Ignore - delete to make way for new one
}
finally {
if (!success) {
userDbh.close();
Msg.debug(this, "Removing incompatible program user data file for " +
programItem.getPathName());
removeUserDataFile(programItem, userfs);
}
}
}
return new ProgramUserDataDB(program);
return null; // will be created by ProgramDB when modified
}
private void recoverChangeSet(ProgramDB program, DBHandle dbh) throws IOException {

View file

@ -1910,8 +1910,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
}
@Override
protected void setChanged(boolean b) {
super.setChanged(b);
protected void setChanged(boolean state) {
super.setChanged(state);
if (!state && !dbh.isChanged()) {
// language upgrade has already been completed
languageUpgradeTranslator = null;
}
}
void setChangeSet(ProgramDBChangeSet changeSet) {
@ -2369,6 +2373,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
@Override
protected void close() {
if (changed && languageUpgradeTranslator != null) {
// Prevent user data from being saved if program and user data
// have gone through a major language upgrade and the program
// was not saved.
programUserData.setChanged(false);
}
super.close();
intRangePropertyMap.clear();
addrSetPropertyMap.clear();

View file

@ -119,6 +119,11 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
return program.getName() + "_UserData";
}
/**
* Create a new program user data store.
* @param program related program
* @throws IOException if an IO error occurs
*/
public ProgramUserDataDB(ProgramDB program) throws IOException {
super(new DBHandle(), getName(program), 500, program);
this.program = program;
@ -157,8 +162,22 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
}
}
/**
* Open existing program user data store.
* If a major language change is detected the instance will automatically attempt to upgrade
* its internal address map.
* @param dbh user data storage DB handle
* @param program related program
* @param monitor task monitor
* @throws IOException if an IO error occurs
* @throws VersionException if a DB version error occurs
* @throws LanguageNotFoundException if language was not found
* @throws CancelledException if instantiation was cancelled
* @throws IllegalStateException if data store is bad or incmopatible with program
*/
public ProgramUserDataDB(DBHandle dbh, ProgramDB program, TaskMonitor monitor)
throws IOException, VersionException, LanguageNotFoundException, CancelledException {
throws IOException, VersionException, LanguageNotFoundException, CancelledException,
IllegalStateException {
super(dbh, getName(program), 500, program);
this.program = program;
@ -200,6 +219,9 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
upgradeDatabase();
if (languageVersionExc != null) {
if (languageUpgradeTranslator == null) {
throw new LanguageNotFoundException(languageID + ":" + languageVersion);
}
try {
setLanguage(languageUpgradeTranslator, monitor);
addressMap.memoryMapChanged(program.getMemory());
@ -212,6 +234,16 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
}
}
if (!program.getLanguageID().equals(languageID)) {
throw new IllegalStateException(
"User data and program have inconsistent language ID");
}
if (program.getLanguage().getVersion() != languageVersion) {
throw new IllegalStateException(
"User data language version does not match program's");
}
endTransaction(id, true);
changed = false;
clearUndo(false);
@ -431,6 +463,10 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
record.setString(VALUE_COL, languageID.getIdAsString());
table.putRecord(record);
record = SCHEMA.createRecord(new StringField(LANGUAGE_VERSION));
record.setString(VALUE_COL, Integer.toString(languageVersion));
table.putRecord(record);
setChanged(true);
clearCache(true);
@ -451,6 +487,11 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
return dbh.canUpdate();
}
@Override
protected void setChanged(boolean b) {
super.setChanged(b);
}
private PropertyMap<?> getPropertyMap(String owner, String propertyName, int propertyType,
Class<?> saveableClass, boolean create) throws PropertyTypeMismatchException {