mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GP-5205_ghidra1_ProgramUserDataIssues' into Ghidra_11.3
This commit is contained in:
commit
afe96c0309
4 changed files with 78 additions and 6 deletions
|
@ -583,12 +583,16 @@ public abstract class DomainObjectAdapterDB extends DomainObjectAdapter implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
DomainObjectAdapterDB userData = getUserData();
|
DomainObjectAdapterDB userData = getUserData();
|
||||||
if (userData != null && userData.isChanged() && (getDomainFile() instanceof GhidraFile)) {
|
if (canSave() && userData != null && userData.isChanged() &&
|
||||||
|
(getDomainFile() instanceof GhidraFile)) {
|
||||||
|
// Only save user data if this domain object was open for update and the
|
||||||
|
// user data was modified.
|
||||||
try {
|
try {
|
||||||
userData.prepareToSave();
|
userData.prepareToSave();
|
||||||
userData.save(null, TaskMonitor.DUMMY);
|
userData.save(null, TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
Msg.warn(this, "Failed to save user data for: " + getDomainFile().getName());
|
Msg.warn(this, "Failed to save user data for: " + getDomainFile().getName());
|
||||||
|
|
|
@ -28,6 +28,7 @@ import ghidra.framework.model.ChangeSet;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.framework.store.*;
|
import ghidra.framework.store.*;
|
||||||
import ghidra.framework.store.local.LocalDatabaseItem;
|
import ghidra.framework.store.local.LocalDatabaseItem;
|
||||||
|
import ghidra.program.model.lang.LanguageNotFoundException;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -232,9 +233,25 @@ public class ProgramContentHandler extends DBWithUserDataContentHandler<ProgramD
|
||||||
DBHandle userDbh =
|
DBHandle userDbh =
|
||||||
openAssociatedUserFile(programItem.getFileID(), PROGRAM_CONTENT_TYPE, userfs, monitor);
|
openAssociatedUserFile(programItem.getFileID(), PROGRAM_CONTENT_TYPE, userfs, monitor);
|
||||||
if (userDbh != null) {
|
if (userDbh != null) {
|
||||||
return new ProgramUserDataDB(userDbh, program, monitor);
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
ProgramUserDataDB data = new ProgramUserDataDB(userDbh, program, monitor);
|
||||||
|
success = true;
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
return new ProgramUserDataDB(program);
|
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 null; // will be created by ProgramDB when modified
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recoverChangeSet(ProgramDB program, DBHandle dbh) throws IOException {
|
private void recoverChangeSet(ProgramDB program, DBHandle dbh) throws IOException {
|
||||||
|
|
|
@ -1910,8 +1910,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setChanged(boolean b) {
|
protected void setChanged(boolean state) {
|
||||||
super.setChanged(b);
|
super.setChanged(state);
|
||||||
|
if (!state && !dbh.isChanged()) {
|
||||||
|
// language upgrade has already been completed
|
||||||
|
languageUpgradeTranslator = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setChangeSet(ProgramDBChangeSet changeSet) {
|
void setChangeSet(ProgramDBChangeSet changeSet) {
|
||||||
|
@ -2369,6 +2373,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void close() {
|
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();
|
super.close();
|
||||||
intRangePropertyMap.clear();
|
intRangePropertyMap.clear();
|
||||||
addrSetPropertyMap.clear();
|
addrSetPropertyMap.clear();
|
||||||
|
|
|
@ -119,6 +119,11 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
|
||||||
return program.getName() + "_UserData";
|
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 {
|
public ProgramUserDataDB(ProgramDB program) throws IOException {
|
||||||
super(new DBHandle(), getName(program), 500, program);
|
super(new DBHandle(), getName(program), 500, program);
|
||||||
this.program = 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)
|
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);
|
super(dbh, getName(program), 500, program);
|
||||||
this.program = program;
|
this.program = program;
|
||||||
|
@ -200,6 +219,9 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
|
||||||
upgradeDatabase();
|
upgradeDatabase();
|
||||||
|
|
||||||
if (languageVersionExc != null) {
|
if (languageVersionExc != null) {
|
||||||
|
if (languageUpgradeTranslator == null) {
|
||||||
|
throw new LanguageNotFoundException(languageID + ":" + languageVersion);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
setLanguage(languageUpgradeTranslator, monitor);
|
setLanguage(languageUpgradeTranslator, monitor);
|
||||||
addressMap.memoryMapChanged(program.getMemory());
|
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);
|
endTransaction(id, true);
|
||||||
changed = false;
|
changed = false;
|
||||||
clearUndo(false);
|
clearUndo(false);
|
||||||
|
@ -431,6 +463,10 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
|
||||||
record.setString(VALUE_COL, languageID.getIdAsString());
|
record.setString(VALUE_COL, languageID.getIdAsString());
|
||||||
table.putRecord(record);
|
table.putRecord(record);
|
||||||
|
|
||||||
|
record = SCHEMA.createRecord(new StringField(LANGUAGE_VERSION));
|
||||||
|
record.setString(VALUE_COL, Integer.toString(languageVersion));
|
||||||
|
table.putRecord(record);
|
||||||
|
|
||||||
setChanged(true);
|
setChanged(true);
|
||||||
clearCache(true);
|
clearCache(true);
|
||||||
|
|
||||||
|
@ -451,6 +487,11 @@ class ProgramUserDataDB extends DomainObjectAdapterDB implements ProgramUserData
|
||||||
return dbh.canUpdate();
|
return dbh.canUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setChanged(boolean b) {
|
||||||
|
super.setChanged(b);
|
||||||
|
}
|
||||||
|
|
||||||
private PropertyMap<?> getPropertyMap(String owner, String propertyName, int propertyType,
|
private PropertyMap<?> getPropertyMap(String owner, String propertyName, int propertyType,
|
||||||
Class<?> saveableClass, boolean create) throws PropertyTypeMismatchException {
|
Class<?> saveableClass, boolean create) throws PropertyTypeMismatchException {
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue