mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
855a607699
23 changed files with 566 additions and 171 deletions
|
@ -21,9 +21,12 @@ import javax.swing.Icon;
|
|||
|
||||
import docking.widgets.tree.GTree;
|
||||
import docking.widgets.tree.GTreeNode;
|
||||
import generic.theme.GColor;
|
||||
import generic.theme.GThemeDefaults.Colors.Messages;
|
||||
import ghidra.app.plugin.core.datamgr.archive.Archive;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.StandAloneDataTypeManager.ArchiveWarning;
|
||||
import ghidra.program.model.data.StandAloneDataTypeManager.ArchiveWarningLevel;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.task.SwingUpdateManager;
|
||||
|
||||
|
@ -63,26 +66,29 @@ public class ArchiveNode extends CategoryNode {
|
|||
buf.append(HTMLUtilities.HTML_SPACE);
|
||||
buf.append(HTMLUtilities.HTML_SPACE);
|
||||
buf.append(HTMLUtilities.escapeHTML(programArchSummary));
|
||||
addArchiveWarnings(dtm, buf);
|
||||
}
|
||||
else {
|
||||
buf.append(DEFAULT_DATA_ORG_DESCRIPTION);
|
||||
}
|
||||
addArchiveWarnings(dtm, buf);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void addArchiveWarnings(DataTypeManager dtm, StringBuilder buf) {
|
||||
if (dtm instanceof StandAloneDataTypeManager archiveDtm) {
|
||||
if (archiveDtm.isProgramArchitectureMissing()) {
|
||||
buf.append(HTMLUtilities.BR);
|
||||
buf.append(
|
||||
"<font color=\"" + Messages.ERROR +
|
||||
"\">** Missing Language/Compiler Specification **</font>");
|
||||
ArchiveWarning warning = archiveDtm.getWarning();
|
||||
if (warning != ArchiveWarning.NONE) {
|
||||
GColor c = Messages.NORMAL;
|
||||
ArchiveWarningLevel level = warning.level();
|
||||
if (level == ArchiveWarningLevel.ERROR) {
|
||||
c = Messages.ERROR;
|
||||
}
|
||||
else if (archiveDtm.isProgramArchitectureUpgradeRequired()) {
|
||||
else if (level == ArchiveWarningLevel.WARN) {
|
||||
c = Messages.WARNING;
|
||||
}
|
||||
String msg = archiveDtm.getWarningMessage(false);
|
||||
buf.append(HTMLUtilities.BR);
|
||||
buf.append("<font color=\"" + Messages.WARNING +
|
||||
"\">** Language Upgrade Required **</font>");
|
||||
buf.append("<font color=\"" + c + "\">** " + msg + " **</font>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1775,10 +1775,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
|||
|
||||
monitor.checkCancelled();
|
||||
|
||||
if (openMode == UPGRADE) {
|
||||
if (oldFunctionMgr != null) {
|
||||
// Upgrade Function Manager
|
||||
if (openMode == UPGRADE && oldFunctionMgr != null) {
|
||||
oldFunctionMgr.upgrade(this, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_MANAGERS; i++) {
|
||||
monitor.checkCancelled();
|
||||
|
|
|
@ -69,7 +69,7 @@ public class ProjectDataTypeManager extends StandAloneDataTypeManager
|
|||
TaskMonitor monitor) throws CancelledException, VersionException, IOException {
|
||||
super(handle, openMode, errHandler, lock, monitor);
|
||||
this.dataTypeArchive = dataTypeArchive;
|
||||
reportWarning();
|
||||
logWarning();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -683,13 +683,11 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
|
|||
}
|
||||
|
||||
/**
|
||||
* Perform any neccessary component adjustments based on
|
||||
* sizes and alignment of components differing from their
|
||||
* specification which may be influenced by the data organization.
|
||||
* If this composite changes parents will not be
|
||||
* notified - handling this is the caller's responsibility.
|
||||
* It is assumed that this method is invoked on composites
|
||||
* in dependency order.
|
||||
* Perform any neccessary component adjustments based on sizes of components differing from
|
||||
* their specification which may be influenced by the data organization. This method
|
||||
* does not consider alignment changes and should be used on non-packed structures only.
|
||||
* If this composite changes parents will not be notified - handling this is the caller's
|
||||
* responsibility. It is assumed that this method is invoked on composites in dependency order.
|
||||
* @throws IOException if database IO error occurs
|
||||
*/
|
||||
protected abstract void fixupComponents() throws IOException;
|
||||
|
|
|
@ -238,16 +238,18 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
/**
|
||||
* Constructor for a data-type manager backed by a packed database file. When
|
||||
* opening for UPDATE an automatic upgrade will be performed if required.
|
||||
* NOTE: default DataOrganization will be used.
|
||||
* NOTE: Default DataOrganization will be used for new archive.
|
||||
*
|
||||
* @param packedDBfile packed datatype archive file (i.e., *.gdt resource).
|
||||
* @param openMode open mode CREATE, READ_ONLY or UPDATE (see
|
||||
* {@link DBConstants}).
|
||||
* @param monitor task monitor
|
||||
* @throws IOException a low-level IO error. This exception may also be thrown
|
||||
* when a version error occurs (cause is VersionException).
|
||||
* @throws CancelledException if task cancelled
|
||||
*/
|
||||
protected DataTypeManagerDB(ResourceFile packedDBfile, int openMode)
|
||||
throws IOException {
|
||||
protected DataTypeManagerDB(ResourceFile packedDBfile, int openMode, TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
|
||||
this.errHandler = new DbErrorHandler();
|
||||
this.lock = new Lock("DataTypeManagerDB");
|
||||
|
@ -268,19 +270,17 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
DataTypeArchiveContentHandler.DATA_TYPE_ARCHIVE_CONTENT_TYPE);
|
||||
}
|
||||
else {
|
||||
pdb = PackedDatabase.getPackedDatabase(packedDBfile, false, TaskMonitor.DUMMY);
|
||||
if (openMode == DBConstants.UPDATE) {
|
||||
dbHandle = pdb.openForUpdate(TaskMonitor.DUMMY);
|
||||
pdb = PackedDatabase.getPackedDatabase(packedDBfile, false, monitor);
|
||||
|
||||
if (openMode == DBConstants.READ_ONLY) {
|
||||
dbHandle = pdb.open(monitor);
|
||||
}
|
||||
else {
|
||||
dbHandle = pdb.open(TaskMonitor.DUMMY);
|
||||
else { // UPDATE mode (allows upgrade use)
|
||||
dbHandle = pdb.openForUpdate(monitor);
|
||||
}
|
||||
}
|
||||
openSuccess = true;
|
||||
}
|
||||
catch (CancelledException e1) {
|
||||
throw new AssertException(e1); // can't happen--dummy monitor
|
||||
}
|
||||
finally {
|
||||
if (!openSuccess && pdb != null) {
|
||||
pdb.dispose(); // dispose on error
|
||||
|
@ -290,21 +290,15 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
// Initialize datatype manager and save new archive on CREATE
|
||||
boolean initSuccess = false;
|
||||
try {
|
||||
|
||||
initPackedDatabase(packedDBfile, openMode); // performs upgrade if needed
|
||||
|
||||
initPackedDatabase(packedDBfile, openMode, monitor); // performs upgrade if needed
|
||||
if (openMode == DBConstants.CREATE) {
|
||||
// preserve UniversalID if it has been established
|
||||
Long uid = universalID != null ? universalID.getValue() : null;
|
||||
((PackedDBHandle) dbHandle).saveAs("Archive", file.getParentFile(),
|
||||
packedDBfile.getName(), uid, TaskMonitor.DUMMY);
|
||||
packedDBfile.getName(), uid, monitor);
|
||||
}
|
||||
|
||||
initSuccess = true;
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
throw new AssertException(e); // can't happen--dummy monitor
|
||||
}
|
||||
finally {
|
||||
if (!initSuccess) {
|
||||
dbHandle.close(); // close on error (packed database will also be disposed)
|
||||
|
@ -312,41 +306,43 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
}
|
||||
}
|
||||
|
||||
private void initPackedDatabase(ResourceFile packedDBfile, int openMode)
|
||||
private void initPackedDatabase(ResourceFile packedDBfile, int openMode, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
int id = startTransaction("");
|
||||
try {
|
||||
init(openMode, TaskMonitor.DUMMY);
|
||||
try (Transaction tx = openTransaction("")) {
|
||||
init(openMode, monitor);
|
||||
|
||||
if (openMode != DBConstants.CREATE && hasDataOrganizationChange()) {
|
||||
// check for data organization change with possible upgrade
|
||||
handleDataOrganizationChange(openMode, monitor);
|
||||
}
|
||||
|
||||
if (openMode == DBConstants.UPGRADE) {
|
||||
migrateOldFlexArrayComponentsIfRequired(monitor);
|
||||
|
||||
Msg.showInfo(this, null, "Archive Upgraded",
|
||||
"Data type archive has been upgraded: " + packedDBfile.getName());
|
||||
}
|
||||
}
|
||||
catch (VersionException e) {
|
||||
if (openMode == DBConstants.UPDATE && e.isUpgradable()) {
|
||||
try {
|
||||
init(DBConstants.UPGRADE, TaskMonitor.DUMMY);
|
||||
migrateOldFlexArrayComponentsIfRequired(TaskMonitor.DUMMY);
|
||||
|
||||
Msg.showInfo(this, null, "Archive Upgraded",
|
||||
"Data type archive schema has been upgraded: " + packedDBfile.getName());
|
||||
}
|
||||
catch (VersionException ve) {
|
||||
throw new IOException(e); // unexpected
|
||||
}
|
||||
initPackedDatabase(packedDBfile, DBConstants.UPGRADE, monitor);
|
||||
}
|
||||
else {
|
||||
// TODO: Unable to handle required upgrade for read-only without API change
|
||||
// Unable to handle required upgrade
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
endTransaction(id, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a database-backed <code>DataTypeManagerDB</code> extension.
|
||||
* NOTE: This does not check for and handle data organization changes which must be
|
||||
* handled later (use {@link #hasDataOrganizationChange()} and
|
||||
* {@link #compilerSpecChanged(TaskMonitor)} to check for and initiate response to changes).
|
||||
*
|
||||
* @param handle database handle
|
||||
* @param addrMap address map (may be null)
|
||||
* @param openMode open mode CREATE, READ_ONLY or UPDATE (see {@link DBConstants}).
|
||||
* @param openMode open mode CREATE, READ_ONLY, UPDATE, UPGRADE (see {@link DBConstants}).
|
||||
* @param tablePrefix DB table prefix to be applied to all associated table names. This
|
||||
* need only be specified when using multiple instances with the same
|
||||
* DB handle (null or empty string for no-prefix).
|
||||
|
@ -528,6 +524,17 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
// do nothing
|
||||
}
|
||||
|
||||
protected void handleDataOrganizationChange(int openMode, TaskMonitor monitor)
|
||||
throws IOException, LanguageVersionException, CancelledException {
|
||||
if (openMode == DBConstants.UPDATE) {
|
||||
throw new LanguageVersionException("Data organization change detected", true);
|
||||
}
|
||||
if (openMode == DBConstants.UPGRADE) {
|
||||
compilerSpecChanged(monitor);
|
||||
}
|
||||
// NOTE: No change for READ_ONLY mode
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Parent/Child table for tracking dataType usage by other dataTypes
|
||||
* (e.g., arrays, pointers, etc.). Only used to populate the ParentChildAdapter
|
||||
|
@ -777,6 +784,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
* true, to reflect any changes in the data organization.
|
||||
* The caller is resposible for ensuring that this setting is done consistent
|
||||
* with the {@link #addrMap} setting used during construction if applicable.
|
||||
* <br>
|
||||
* If not storing caller may need to check for data organization change to communicate
|
||||
* change or to facilitate an upgrade situation.
|
||||
*
|
||||
* @param programArchitecture program architecture details (may be null) in which case
|
||||
* default data organization will be used.
|
||||
* @param variableStorageMgr variable storage manager (within same database) or null
|
||||
|
@ -805,9 +816,14 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
saveDataOrganization();
|
||||
}
|
||||
else if (store) {
|
||||
try {
|
||||
compilerSpecChanged(monitor);
|
||||
updateLastChangeTime();
|
||||
}
|
||||
finally {
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -822,46 +838,52 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
* @throws CancelledException if processing cancelled - data types may not properly reflect
|
||||
* updated compiler specification
|
||||
*/
|
||||
private void compilerSpecChanged(TaskMonitor monitor) throws IOException, CancelledException {
|
||||
protected void compilerSpecChanged(TaskMonitor monitor) throws IOException, CancelledException {
|
||||
|
||||
if (mode == DBConstants.READ_ONLY) {
|
||||
throw new ReadOnlyException();
|
||||
}
|
||||
|
||||
DataOrganization oldDataOrganization = readDataOrganization();
|
||||
boolean hasDataOrgChange = hasDataOrganizationChange();
|
||||
|
||||
try {
|
||||
saveDataOrganization();
|
||||
|
||||
if (oldDataOrganization != null &&
|
||||
!oldDataOrganization.equals(dataOrganization)) {
|
||||
Msg.info(this,
|
||||
"Fixing datatypes to reflect data organization change: " + getPath());
|
||||
if (hasDataOrgChange) {
|
||||
doCompositeFixup(monitor);
|
||||
}
|
||||
|
||||
// FUTURE: may need to handle calling convention and data organization change impact
|
||||
// on function definitions
|
||||
|
||||
}
|
||||
finally {
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
private void saveDataOrganization() throws IOException {
|
||||
if (dataOrganization == null) {
|
||||
return;
|
||||
}
|
||||
DataOrganizationImpl.save(dataOrganization, getDataMap(true), "dataOrg.");
|
||||
protected final boolean hasDataOrganizationChange() throws IOException {
|
||||
// compare DB-stored data organization with the one in affect
|
||||
return !Objects.equals(readDataOrganization(), getDataOrganization());
|
||||
}
|
||||
|
||||
private DataOrganization readDataOrganization() throws IOException {
|
||||
protected void saveDataOrganization() throws IOException {
|
||||
DataOrganizationImpl.save(getDataOrganization(), getDataMap(true), "dataOrg.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the DB-serialized data organization. If one has not been stored a suitable
|
||||
* default will be returned.
|
||||
* @return stored data organization or suitable default.
|
||||
* @throws IOException if DB error orccurs
|
||||
*/
|
||||
protected DataOrganization readDataOrganization() throws IOException {
|
||||
DBStringMapAdapter dataMap = getDataMap(false);
|
||||
if (dataMap == null) {
|
||||
return null;
|
||||
}
|
||||
return DataOrganizationImpl.restore(dataMap, "dataOrg.");
|
||||
|
||||
DataOrganization dataOrg = DataOrganizationImpl.restore(dataMap, "dataOrg.");
|
||||
if (dataOrg == null) {
|
||||
ProgramArchitecture arch = getProgramArchitecture();
|
||||
return DataOrganizationImpl
|
||||
.getDefaultOrganization(arch != null ? arch.getLanguage() : null);
|
||||
}
|
||||
return dataOrg;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4235,7 +4257,12 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
int count = 0;
|
||||
for (CompositeDB c : orderedComposites) {
|
||||
monitor.checkCancelled();
|
||||
if (c.isPackingEnabled()) {
|
||||
c.repack(true, false);
|
||||
}
|
||||
else {
|
||||
c.fixupComponents();
|
||||
}
|
||||
monitor.setProgress(++count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,9 @@ public class ProgramDataTypeManager extends ProgramBasedDataTypeManagerDB
|
|||
try {
|
||||
setProgramArchitecture(p, p.getSymbolTable().getVariableStorageManager(), false,
|
||||
TaskMonitor.DUMMY);
|
||||
// NOTE: Due to late manner in which program architecture is established, any
|
||||
// response to a data organization change must be handled during a language
|
||||
// upgrade and setLanguage
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
throw new AssertException(e); // unexpected - no IO performed
|
||||
|
|
|
@ -19,6 +19,7 @@ import static ghidra.program.model.pcode.AttributeId.*;
|
|||
import static ghidra.program.model.pcode.ElementId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.program.database.DBStringMapAdapter;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
@ -189,4 +190,23 @@ public class BitFieldPackingImpl implements BitFieldPacking {
|
|||
}
|
||||
parser.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(typeAlignmentEnabled, useMSConvention, zeroLengthBoundary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BitFieldPackingImpl other = (BitFieldPackingImpl) obj;
|
||||
return typeAlignmentEnabled == other.typeAlignmentEnabled &&
|
||||
useMSConvention == other.useMSConvention &&
|
||||
zeroLengthBoundary == other.zeroLengthBoundary;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -701,15 +701,26 @@ public class DataOrganizationImpl implements DataOrganization {
|
|||
* Restore a data organization from the specified DB data map.
|
||||
* @param dataMap DB data map
|
||||
* @param keyPrefix key prefix for all map entries
|
||||
* @return data organization
|
||||
* @return stored data organization or null if not stored
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
public static DataOrganizationImpl restore(DBStringMapAdapter dataMap, String keyPrefix)
|
||||
throws IOException {
|
||||
|
||||
boolean containsDataOrgEntries = false;
|
||||
for (String key : dataMap.keySet()) {
|
||||
if (key.startsWith(keyPrefix)) {
|
||||
containsDataOrgEntries = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!containsDataOrgEntries) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DataOrganizationImpl dataOrg = new DataOrganizationImpl();
|
||||
|
||||
dataOrg.bigEndian = dataMap.getBoolean(BIG_ENDIAN_NAME, false);
|
||||
dataOrg.bigEndian = dataMap.getBoolean(keyPrefix + BIG_ENDIAN_NAME, false);
|
||||
|
||||
dataOrg.absoluteMaxAlignment =
|
||||
dataMap.getInt(keyPrefix + ELEM_ABSOLUTE_MAX_ALIGNMENT.name(),
|
||||
|
@ -984,4 +995,35 @@ public class DataOrganizationImpl implements DataOrganization {
|
|||
parser.end();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(absoluteMaxAlignment, bigEndian, bitFieldPacking, charSize,
|
||||
defaultAlignment, defaultPointerAlignment, doubleSize, floatSize, integerSize,
|
||||
isSignedChar, longDoubleSize, longLongSize, longSize, machineAlignment, pointerShift,
|
||||
pointerSize, shortSize, sizeAlignmentMap, wideCharSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DataOrganizationImpl other = (DataOrganizationImpl) obj;
|
||||
return absoluteMaxAlignment == other.absoluteMaxAlignment && bigEndian == other.bigEndian &&
|
||||
Objects.equals(bitFieldPacking, other.bitFieldPacking) && charSize == other.charSize &&
|
||||
defaultAlignment == other.defaultAlignment &&
|
||||
defaultPointerAlignment == other.defaultPointerAlignment &&
|
||||
doubleSize == other.doubleSize && floatSize == other.floatSize &&
|
||||
integerSize == other.integerSize && isSignedChar == other.isSignedChar &&
|
||||
longDoubleSize == other.longDoubleSize && longLongSize == other.longLongSize &&
|
||||
longSize == other.longSize && machineAlignment == other.machineAlignment &&
|
||||
pointerShift == other.pointerShift && pointerSize == other.pointerSize &&
|
||||
shortSize == other.shortSize &&
|
||||
Objects.equals(sizeAlignmentMap, other.sizeAlignmentMap) &&
|
||||
wideCharSize == other.wideCharSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class DataTypeArchiveIdDumper implements GhidraLaunchable {
|
|||
|
||||
FileWriter writer = new FileWriter(outputFile);
|
||||
FileDataTypeManager archive = FileDataTypeManager.openFileArchive(archiveFile, false);
|
||||
archive.reportWarning();
|
||||
archive.logWarning();
|
||||
UniversalID universalID2 = archive.getUniversalID();
|
||||
writer.write("FILE_ID: " + Long.toHexString(universalID2.getValue()));
|
||||
writer.write("\n");
|
||||
|
|
|
@ -61,15 +61,18 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
|
|||
* with a warning condition, architecture-specific data may not be available or up-to-date.
|
||||
*
|
||||
* @param packedDbfile file to load or create based upon openMode
|
||||
* @param openMode one of the DBConstants: CREATE, UPDATE, READ_ONLY, UPGRADE
|
||||
* @param openMode one of the DBConstants: CREATE, READ_ONLY or UPDATE
|
||||
* @param monitor the progress monitor
|
||||
* @throws IOException if an IO error occurs
|
||||
* @throws CancelledException if task cancelled
|
||||
*/
|
||||
private FileDataTypeManager(ResourceFile packedDbfile, int openMode) throws IOException {
|
||||
super(validateFilename(packedDbfile), openMode);
|
||||
private FileDataTypeManager(ResourceFile packedDbfile, int openMode, TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
super(validateFilename(packedDbfile), openMode, monitor);
|
||||
file = packedDbfile;
|
||||
name = getRootName(file.getName());
|
||||
packedDB = ((PackedDBHandle) dbHandle).getPackedDatabase();
|
||||
reportWarning();
|
||||
logWarning();
|
||||
}
|
||||
|
||||
private static ResourceFile validateFilename(ResourceFile packedDbfile) {
|
||||
|
@ -86,7 +89,13 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
|
|||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
public static FileDataTypeManager createFileArchive(File packedDbfile) throws IOException {
|
||||
return new FileDataTypeManager(new ResourceFile(packedDbfile), DBConstants.CREATE);
|
||||
try {
|
||||
return new FileDataTypeManager(new ResourceFile(packedDbfile), DBConstants.CREATE,
|
||||
TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
throw new AssertException(e); // unexpected without task monitor use
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,7 +138,12 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
|
|||
public static FileDataTypeManager openFileArchive(ResourceFile packedDbfile,
|
||||
boolean openForUpdate) throws IOException {
|
||||
int mode = openForUpdate ? DBConstants.UPDATE : DBConstants.READ_ONLY;
|
||||
return new FileDataTypeManager(packedDbfile, mode);
|
||||
try {
|
||||
return new FileDataTypeManager(packedDbfile, mode, TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
throw new AssertException(e); // unexpected without task monitor use
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,11 +59,16 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
|
||||
protected String name;
|
||||
|
||||
public static enum ArchiveWarningLevel {
|
||||
INFO, WARN, ERROR;
|
||||
}
|
||||
|
||||
public static enum ArchiveWarning {
|
||||
|
||||
/**
|
||||
* {@link #NONE} indicates a normal archive condition
|
||||
*/
|
||||
NONE,
|
||||
NONE(ArchiveWarningLevel.INFO),
|
||||
|
||||
/**
|
||||
* {@link #UPGRADED_LANGUAGE_VERSION} indicates an archive which has been open for update
|
||||
|
@ -72,7 +77,7 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
* which involves significant {@link Register} changes. Sharing an upgraded archive
|
||||
* may impact others who do not have access to the updated {@link Language} module.
|
||||
*/
|
||||
UPGRADED_LANGUAGE_VERSION,
|
||||
UPGRADED_LANGUAGE_VERSION(ArchiveWarningLevel.INFO),
|
||||
|
||||
// programArchitectureSummary must be set for the warnings below
|
||||
|
||||
|
@ -82,7 +87,7 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
* a problem being loaded. The {@link FileDataTypeManager#getWarningDetail()} may provide
|
||||
* additional insight to the underlying cause.
|
||||
*/
|
||||
LANGUAGE_NOT_FOUND,
|
||||
LANGUAGE_NOT_FOUND(ArchiveWarningLevel.ERROR),
|
||||
|
||||
/**
|
||||
* {@link #COMPILER_SPEC_NOT_FOUND} indicates the {@link CompilerSpec},
|
||||
|
@ -91,7 +96,7 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
* additional insight to the underlying cause. This condition can only occur if the
|
||||
* required {@link Language} was found.
|
||||
*/
|
||||
COMPILER_SPEC_NOT_FOUND,
|
||||
COMPILER_SPEC_NOT_FOUND(ArchiveWarningLevel.ERROR),
|
||||
|
||||
/**
|
||||
* {@link #LANGUAGE_UPGRADE_REQURED} indicates an archive which has been open read-only
|
||||
|
@ -103,7 +108,27 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
* who do not have access to the updated {@link Language} module and should be
|
||||
* coordinated with others who may be affected.
|
||||
*/
|
||||
LANGUAGE_UPGRADE_REQURED,
|
||||
LANGUAGE_UPGRADE_REQURED(ArchiveWarningLevel.WARN),
|
||||
|
||||
/**
|
||||
* {@link #DATA_ORG_CHANGED} indicates an archive which has been open read-only
|
||||
* requires an upgraded to adjust for changes in the associated data organization.
|
||||
*/
|
||||
DATA_ORG_CHANGED(ArchiveWarningLevel.WARN);
|
||||
|
||||
final ArchiveWarningLevel level;
|
||||
|
||||
ArchiveWarning(ArchiveWarningLevel level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the warning level
|
||||
* @return warning level
|
||||
*/
|
||||
public ArchiveWarningLevel level() {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
private ArchiveWarning warning;
|
||||
|
@ -134,35 +159,37 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
* Constructor for a data-type manager backed by a packed database file.
|
||||
* When opening for UPDATE an automatic upgrade will be performed if required.
|
||||
* <p>
|
||||
* <B>NOTE:</B> {@link #reportWarning()} should be invoked immediately after
|
||||
* <B>NOTE:</B> {@link #logWarning()} should be invoked immediately after
|
||||
* instantiating a {@link StandAloneDataTypeManager} for an existing database after
|
||||
* {@link #getName()} and {@link #getPath()} can be invoked safely. In addition, it
|
||||
* may be appropriate to use {@link #getWarning() check for warnings} prior to use.
|
||||
*
|
||||
* @param packedDbfile packed datatype archive file (i.e., *.gdt resource).
|
||||
* @param openMode open mode CREATE, READ_ONLY or UPDATE (see {@link DBConstants})
|
||||
* @param monitor the progress monitor
|
||||
* @throws IOException a low-level IO error. This exception may also be thrown
|
||||
* when a version error occurs (cause is VersionException).
|
||||
* @throws CancelledException if task cancelled
|
||||
*/
|
||||
protected StandAloneDataTypeManager(ResourceFile packedDbfile, int openMode)
|
||||
throws IOException {
|
||||
super(packedDbfile, openMode);
|
||||
protected StandAloneDataTypeManager(ResourceFile packedDbfile, int openMode,
|
||||
TaskMonitor monitor) throws IOException, CancelledException {
|
||||
super(packedDbfile, openMode, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a data-type manager using a specified DBHandle.
|
||||
* <p>
|
||||
* <B>NOTE:</B> {@link #reportWarning()} should be invoked immediately after
|
||||
* <B>NOTE:</B> {@link #logWarning()} should be invoked immediately after
|
||||
* instantiating a {@link StandAloneDataTypeManager} for an existing database after
|
||||
* {@link #getName()} and {@link #getPath()} can be invoked safely. In addition, it
|
||||
* may be appropriate to use {@link #getWarning() check for warnings} prior to use.
|
||||
*
|
||||
* @param handle open database handle
|
||||
* @param openMode the program open mode
|
||||
* @param openMode open mode CREATE, READ_ONLY or UPDATE (see {@link DBConstants})
|
||||
* @param errHandler the database I/O error handler
|
||||
* @param lock the program synchronization lock
|
||||
* @param monitor the progress monitor
|
||||
* @throws CancelledException if the user cancels an upgrade
|
||||
* @throws CancelledException if task cancelled
|
||||
* @throws VersionException if the database does not match the expected version.
|
||||
* @throws IOException if a database I/O error occurs.
|
||||
*/
|
||||
|
@ -170,6 +197,9 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
Lock lock, TaskMonitor monitor)
|
||||
throws CancelledException, VersionException, IOException {
|
||||
super(handle, null, openMode, null, errHandler, lock, monitor);
|
||||
if (openMode != DBConstants.CREATE && hasDataOrganizationChange()) {
|
||||
handleDataOrganizationChange(openMode, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,41 +223,77 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
}
|
||||
|
||||
/**
|
||||
* Due to the supression of error and warning conditions during instantiation this method should
|
||||
* be invoked at the end of instatiation when {@link #getName()} and {@link #getPath()} are
|
||||
* ready to be invoked safely. Logging will be performed via {@link Msg}.
|
||||
* Get a suitable warning message. See {@link #getWarning()} for type and its severity level
|
||||
* {@link ArchiveWarning#level()}.
|
||||
* @param includeDetails if false simple message returned, otherwise more details are included.
|
||||
* @return warning message or null if {@link #getWarning()} is {@link ArchiveWarning#NONE}.
|
||||
*/
|
||||
protected void reportWarning() {
|
||||
String msg;
|
||||
public String getWarningMessage(boolean includeDetails) {
|
||||
String msg = null;
|
||||
switch (warning) {
|
||||
case NONE:
|
||||
break;
|
||||
case LANGUAGE_NOT_FOUND:
|
||||
msg = "Language not found for Archive '" + getName() + "': " +
|
||||
warningDetail.getMessage();
|
||||
Msg.error(this, msg);
|
||||
msg = "Language not found for Archive";
|
||||
if (includeDetails) {
|
||||
msg += " '" + getName() + "': " + warningDetail.getMessage();
|
||||
}
|
||||
break;
|
||||
case COMPILER_SPEC_NOT_FOUND:
|
||||
msg = "Compiler specification not found for Archive '" + getName() + "': " +
|
||||
warningDetail.getMessage();
|
||||
Msg.error(this, msg);
|
||||
msg = "Compiler specification not found for Archive";
|
||||
if (includeDetails) {
|
||||
msg += " '" + getName() + "': " + warningDetail.getMessage();
|
||||
}
|
||||
break;
|
||||
case LANGUAGE_UPGRADE_REQURED:
|
||||
msg = "Language upgrade required for Archive '" + getName() + "': " +
|
||||
programArchitectureSummary;
|
||||
Msg.warn(this, msg);
|
||||
msg = "Language upgrade required for Archive";
|
||||
if (includeDetails) {
|
||||
msg += " '" + getName() + "': " + programArchitectureSummary;
|
||||
}
|
||||
break;
|
||||
case UPGRADED_LANGUAGE_VERSION:
|
||||
msg = "Upgraded program-architecture for Archive";
|
||||
if (includeDetails) {
|
||||
ProgramArchitecture arch = getProgramArchitecture();
|
||||
LanguageDescription languageDescription =
|
||||
arch.getLanguage().getLanguageDescription();
|
||||
msg =
|
||||
"Upgraded program-architecture for Archive: '" + getName() +
|
||||
msg += " '" + getName() +
|
||||
"'\n Language: " +
|
||||
languageDescription.getLanguageID() + " Version " +
|
||||
languageDescription.getVersion() + ".x" +
|
||||
", CompilerSpec: " + arch.getCompilerSpec().getCompilerSpecID();
|
||||
}
|
||||
break;
|
||||
case DATA_ORG_CHANGED:
|
||||
msg = "Data organization upgrade required for Archive";
|
||||
if (includeDetails) {
|
||||
msg += " '" + getName() + "': " + programArchitectureSummary;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Due to the supression of error and warning conditions during instantiation this method should
|
||||
* be invoked at the end of instatiation when {@link #getName()} and {@link #getPath()} are
|
||||
* ready to be invoked safely. Logging will be performed via {@link Msg}.
|
||||
*/
|
||||
protected void logWarning() {
|
||||
String msg = getWarningMessage(true);
|
||||
if (msg == null) {
|
||||
return;
|
||||
}
|
||||
switch (warning.level) {
|
||||
case ERROR:
|
||||
Msg.error(this, msg);
|
||||
break;
|
||||
case WARN:
|
||||
Msg.warn(this, msg);
|
||||
break;
|
||||
default:
|
||||
Msg.info(this, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -238,6 +304,7 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
|
||||
warning = ArchiveWarning.NONE;
|
||||
if (openMode == DBConstants.CREATE) {
|
||||
saveDataOrganization(); // save default dataOrg
|
||||
return; // optional program architecture is set after initialization is complete
|
||||
}
|
||||
|
||||
|
@ -369,9 +436,18 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB implements Clos
|
|||
if (variableStorageMgr != null) {
|
||||
variableStorageMgr.setProgramArchitecture(getProgramArchitecture());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleDataOrganizationChange(int openMode, TaskMonitor monitor)
|
||||
throws LanguageVersionException, CancelledException, IOException {
|
||||
if (openMode == DBConstants.READ_ONLY) {
|
||||
warning = ArchiveWarning.DATA_ORG_CHANGED;
|
||||
}
|
||||
super.handleDataOrganizationChange(openMode, monitor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the program architecture information which has been associated with this
|
||||
* datatype manager. If {@link #getProgramArchitecture()} returns null this method
|
||||
|
|
|
@ -479,6 +479,7 @@ ADDRI: (imm16) is imm16 { tmp:2 = imm16; export *:2 tmp; }
|
|||
:TSX is op=0xBA
|
||||
{
|
||||
X = S;
|
||||
resultFlags(X);
|
||||
}
|
||||
|
||||
:TXA is op=0x8A
|
||||
|
|
|
@ -6,8 +6,11 @@ data/languages/68000.ldefs||GHIDRA||||END|
|
|||
data/languages/68000.opinion||GHIDRA||||END|
|
||||
data/languages/68000.pspec||GHIDRA||||END|
|
||||
data/languages/68000.sinc||GHIDRA||||END|
|
||||
data/languages/68000_register.cspec||GHIDRA||||END|
|
||||
data/languages/68020.slaspec||GHIDRA||reviewed||END|
|
||||
data/languages/68030.slaspec||GHIDRA||||END|
|
||||
data/languages/68040.slaspec||GHIDRA||||END|
|
||||
data/languages/coldfire.slaspec||GHIDRA||||END|
|
||||
data/manuals/68000.idx||GHIDRA||||END|
|
||||
data/patterns/68000_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/patternconstraints.xml||GHIDRA||||END|
|
||||
|
|
|
@ -22,25 +22,16 @@
|
|||
<entry size="8" alignment="4" />
|
||||
</size_alignment_map>
|
||||
</data_organization>
|
||||
|
||||
<global>
|
||||
<range space="ram"/>
|
||||
</global>
|
||||
|
||||
<stackpointer register="SP" space="ram"/>
|
||||
|
||||
<default_proto>
|
||||
<prototype name="__stdcall" extrapop="4" stackshift="4" strategy="register">
|
||||
<prototype name="__stdcall" extrapop="4" stackshift="4">
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="4" metatype="ptr">
|
||||
<register name="A0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4" metatype="ptr">
|
||||
<register name="A1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="D0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="D1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="500" align="4">
|
||||
<addr offset="4" space="stack"/>
|
||||
</pentry>
|
||||
|
@ -64,6 +55,13 @@
|
|||
<register name="A6"/>
|
||||
<register name="SP"/>
|
||||
</unaffected>
|
||||
<killedbycall>
|
||||
<register name="D0"/>
|
||||
<register name="D1"/>
|
||||
<register name="A0"/>
|
||||
<register name="A1"/>
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
</compiler_spec>
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
id="68000:BE:32:Coldfire">
|
||||
<description>Motorola 32-bit Coldfire</description>
|
||||
<compiler name="default" spec="68000.cspec" id="default"/>
|
||||
<compiler name="register" spec="68000_register.cspec" id="register"/>
|
||||
<external_name tool="IDA-PRO" name="colfire"/>
|
||||
<external_name tool="DWARF.register.mapping.file" name="68000.dwarf"/>
|
||||
</language>
|
||||
|
|
|
@ -1643,7 +1643,7 @@ m2rfl0: { m2rfl1} is mvm15=0 & m2rfl1 { }
|
|||
:movem.w (regan)+,m2rfw0 is opbig=0x4c & op67=2 & mode=3 & regan; m2rfw0 { movemptr = regan; build m2rfw0; regan = movemptr; }
|
||||
:movem.w (d16,regan),m2rfw0 is opbig=0x4c & op67=2 & mode=5 & regan; m2rfw0; d16 { movemptr = regan+d16; build m2rfw0; }
|
||||
:movem.w (extw),m2rfw0 is opbig=0x4c & op67=2 & mode=6 & regan; m2rfw0; extw [ pcmode=0; regtfan=regan; ] { build extw; movemptr = extw; build m2rfw0; }
|
||||
:movem.w (d16,PC),m2rfw0 is opbig=0x4c & op67=2 & mode=7 & regan=2; m2rfw0; d16 & PC { movemptr = inst_start+2+d16; build m2rfw0; }
|
||||
:movem.w (d16,PC),m2rfw0 is opbig=0x4c & op67=2 & mode=7 & regan=2; m2rfw0; d16 & PC { movemptr = inst_start+4+d16; build m2rfw0; }
|
||||
:movem.w (extw),m2rfw0 is opbig=0x4c & op67=2 & mode=7 & regan=3; m2rfw0; extw [ pcmode=1; ] { build extw; movemptr = extw; build m2rfw0; }
|
||||
:movem.w (d16)".w",m2rfw0 is opbig=0x4c & op67=2 & mode=7 & regan=0; m2rfw0; d16 { movemptr = d16; build m2rfw0; }
|
||||
:movem.w (d32)".l",m2rfw0 is opbig=0x4c & op67=2 & mode=7 & regan=1; m2rfw0; d32 { movemptr = d32; build m2rfw0; }
|
||||
|
@ -1651,7 +1651,7 @@ m2rfl0: { m2rfl1} is mvm15=0 & m2rfl1 { }
|
|||
:movem.l (regan)+,m2rfl0 is opbig=0x4c & op67=3 & mode=3 & regan; m2rfl0 { movemptr = regan; build m2rfl0; regan = movemptr; }
|
||||
:movem.l (d16,regan),m2rfl0 is opbig=0x4c & op67=3 & mode=5 & regan; m2rfl0; d16 { movemptr = regan+d16; build m2rfl0; }
|
||||
:movem.l (extw),m2rfl0 is opbig=0x4c & op67=3 & mode=6 & regan; m2rfl0; extw [ pcmode=0; regtfan=regan; ] { build extw; movemptr = extw; build m2rfl0; }
|
||||
:movem.l (d16,PC),m2rfl0 is opbig=0x4c & op67=3 & mode=7 & regan=2; m2rfl0; d16 & PC { movemptr = inst_start+2+d16; build m2rfl0; }
|
||||
:movem.l (d16,PC),m2rfl0 is opbig=0x4c & op67=3 & mode=7 & regan=2; m2rfl0; d16 & PC { movemptr = inst_start+4+d16; build m2rfl0; }
|
||||
:movem.l (extw),m2rfl0 is opbig=0x4c & op67=3 & mode=7 & regan=3; m2rfl0; extw [ pcmode=1; ] { build extw; movemptr = extw; build m2rfl0; }
|
||||
:movem.l (d16)".w",m2rfl0 is opbig=0x4c & op67=3 & mode=7 & regan=0; m2rfl0; d16 { movemptr = d16; build m2rfl0; }
|
||||
:movem.l (d32)".l",m2rfl0 is opbig=0x4c & op67=3 & mode=7 & regan=1; m2rfl0; d32 { movemptr = d32; build m2rfl0; }
|
||||
|
@ -1764,7 +1764,7 @@ macro negResFlags(result) {
|
|||
Txb = result:1;
|
||||
}
|
||||
|
||||
:pea eaptr is (opbig=0x48 & op67=1 & $(CTL_ADDR_MODES))... & eaptr { SP = SP-4; *SP = eaptr; }
|
||||
:pea eaptr is (opbig=0x48 & op67=1 & $(CTL_ADDR_MODES))... & eaptr { value:4 = eaptr; SP = SP-4; *SP = value; }
|
||||
|
||||
@ifdef MC68040
|
||||
|
||||
|
|
118
Ghidra/Processors/68000/data/languages/68000_register.cspec
Normal file
118
Ghidra/Processors/68000/data/languages/68000_register.cspec
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<compiler_spec>
|
||||
<data_organization>
|
||||
<absolute_max_alignment value="0" />
|
||||
<machine_alignment value="8" />
|
||||
<default_alignment value="1" />
|
||||
<default_pointer_alignment value="4" />
|
||||
<pointer_size value="4" />
|
||||
<wchar_size value="4" />
|
||||
<short_size value="2" />
|
||||
<integer_size value="4" />
|
||||
<long_size value="4" />
|
||||
<long_long_size value="8" />
|
||||
<float_size value="4" />
|
||||
<double_size value="8" />
|
||||
<long_double_size value="10" /> <!-- aligned-length=12 -->
|
||||
<size_alignment_map>
|
||||
<entry size="1" alignment="1" />
|
||||
<entry size="2" alignment="2" />
|
||||
<entry size="4" alignment="4" />
|
||||
<entry size="8" alignment="4" />
|
||||
</size_alignment_map>
|
||||
</data_organization>
|
||||
|
||||
<global>
|
||||
<range space="ram"/>
|
||||
</global>
|
||||
|
||||
<stackpointer register="SP" space="ram"/>
|
||||
|
||||
<default_proto>
|
||||
<prototype name="register" extrapop="4" stackshift="4" strategy="register">
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="4" metatype="ptr">
|
||||
<register name="A0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4" metatype="ptr">
|
||||
<register name="A1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4" metatype="float">
|
||||
<register name="FP0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4" metatype="float">
|
||||
<register name="FP1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="D0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="D1"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="500" align="4">
|
||||
<addr offset="4" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="1" maxsize="4" metatype="ptr">
|
||||
<register name="A0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="D0"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="D2"/>
|
||||
<register name="D3"/>
|
||||
<register name="D4"/>
|
||||
<register name="D5"/>
|
||||
<register name="D6"/>
|
||||
<register name="D7"/>
|
||||
<register name="A2"/>
|
||||
<register name="A3"/>
|
||||
<register name="A4"/>
|
||||
<register name="A5"/>
|
||||
<register name="A6"/>
|
||||
<register name="SP"/>
|
||||
</unaffected>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<prototype name="standard" extrapop="4" stackshift="4">
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="500" align="4">
|
||||
<addr offset="4" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="1" maxsize="4" metatype="ptr">
|
||||
<register name="A0"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="D0"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="D2"/>
|
||||
<register name="D3"/>
|
||||
<register name="D4"/>
|
||||
<register name="D5"/>
|
||||
<register name="D6"/>
|
||||
<register name="D7"/>
|
||||
<register name="A2"/>
|
||||
<register name="A3"/>
|
||||
<register name="A4"/>
|
||||
<register name="A5"/>
|
||||
<register name="A6"/>
|
||||
<register name="SP"/>
|
||||
</unaffected>
|
||||
<killedbycall>
|
||||
<register name="D0"/>
|
||||
<register name="D1"/>
|
||||
<register name="A0"/>
|
||||
<register name="A1"/>
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
|
||||
</compiler_spec>
|
41
Ghidra/Processors/68000/data/patterns/68000_patterns.xml
Normal file
41
Ghidra/Processors/68000/data/patterns/68000_patterns.xml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<patternlist>
|
||||
|
||||
<patternpairs totalbits="32" postbits="16">
|
||||
<!-- Higher confidence patterns, after a return and more defined bits -->
|
||||
<prepatterns>
|
||||
<data>0x4e 0x75</data> <!-- ret -->
|
||||
<data>0x4e 0x75 0x4e 0x71 </data> <!-- ret; padding -->
|
||||
<data>0x4e 0x75 0x00 0x00 </data> <!-- ret; padding -->
|
||||
<data>0x4e 0x5e 0x4e 0x75</data> <!-- unlk A6; ret -->
|
||||
<data>0x4e 0x5e 0x4e 0x75 0x4e 0x71 </data> <!-- unlk A6; ret; padding -->
|
||||
<data>0x4e 0x5e 0x4e 0x75 0x00 0x00 </data> <!-- unlk A6; ret; padding -->
|
||||
</prepatterns>
|
||||
<postpatterns>
|
||||
<data>01001111 11101111 1111.... .......0 </data> <!-- lea (-imm,SP),SP) -->
|
||||
<data>0x4e 0x56 0x00 0x00 </data> <!-- link.w A6, 0 -->
|
||||
<data>0x4e 0x56 1111.... .......0 </data> <!-- link.w A6, -imm -->
|
||||
<data>0101...1 10001111 01001000 11010111 ........ ........ </data> <!-- subq.l +imm, SP; movem.l {}, (SP) -->
|
||||
<data>0010...0 0.101111 0000.... .......0 </data> <!-- mov.l (+imm, SP), reg -->
|
||||
<data>0x2f 0x02 </data> <!-- move.l D2,-SP -->
|
||||
<data>0x2f 0x03 </data> <!-- move.l D3,-SP -->
|
||||
<data>0x2f 0x0a </data> <!-- move.l A2,-SP -->
|
||||
<data>0x2f 0x0b </data> <!-- move.l A3,-SP -->
|
||||
<funcstart/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<patternpairs totalbits="32" postbits="16">
|
||||
<!-- pattern after a bra.w, use more solid patterns for function starts -->
|
||||
<prepatterns>
|
||||
<data>0x60 0x00 ........ ........ </data> <!-- bra.w -->
|
||||
</prepatterns>
|
||||
<postpatterns>
|
||||
<data>01001111 11101111 1111.... .......0 </data> <!-- lea (-imm,SP),SP) -->
|
||||
<data>0x4e 0x56 0x00 0x00 </data> <!-- link.w A6, 0 -->
|
||||
<data>0x4e 0x56 1111.... .......0 </data> <!-- link.w A6, -imm -->
|
||||
<funcstart/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
|
||||
</patternlist>
|
|
@ -0,0 +1,5 @@
|
|||
<patternconstraints>
|
||||
<language id="68000:BE:*:*">
|
||||
<patternfile>68000_patterns.xml</patternfile>
|
||||
</language>
|
||||
</patternconstraints>
|
|
@ -24,13 +24,13 @@
|
|||
<symbol name="BANK1_R6" address="INTMEM:1e"/>
|
||||
<symbol name="BANK1_R7" address="INTMEM:1f"/>
|
||||
|
||||
<symbol name="BUS" address="PORT:0"/>
|
||||
<symbol name="P1" address="PORT:1"/>
|
||||
<symbol name="P2" address="PORT:2"/>
|
||||
<symbol name="P4" address="PORT:4"/>
|
||||
<symbol name="P5" address="PORT:5"/>
|
||||
<symbol name="P6" address="PORT:6"/>
|
||||
<symbol name="P7" address="PORT:7"/>
|
||||
<symbol name="BUS" address="PORT:0" volatile="true" />
|
||||
<symbol name="P1" address="PORT:1" volatile="true" />
|
||||
<symbol name="P2" address="PORT:2" volatile="true" />
|
||||
<symbol name="P4" address="PORT:4" volatile="true" />
|
||||
<symbol name="P5" address="PORT:5" volatile="true" />
|
||||
<symbol name="P6" address="PORT:6" volatile="true" />
|
||||
<symbol name="P7" address="PORT:7" volatile="true" />
|
||||
|
||||
<symbol name="RESET" address="CODE:0" entry="true"/>
|
||||
<symbol name="EXTIRQ" address="CODE:3" entry="true"/>
|
||||
|
@ -46,4 +46,14 @@
|
|||
<memory_block name="PORT" start_address="PORT:0" length="0x8" initialized="false"/>
|
||||
</default_memory_blocks>
|
||||
|
||||
<context_data>
|
||||
<context_set space="CODE" first="0x0" last="0x7ff">
|
||||
<set name="DBF" val="0"/>
|
||||
</context_set>
|
||||
|
||||
<context_set space="CODE" first="0x800" last="0xfff">
|
||||
<set name="DBF" val="1"/>
|
||||
</context_set>
|
||||
</context_data>
|
||||
|
||||
</processor_spec>
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
# sleigh specification file for Intel 8048
|
||||
#
|
||||
# The MCS-48 family can only handle a 4kB (12 bits) address space.
|
||||
# However, some applications use a custom method to access multiple
|
||||
# banks of 4kB, such as an IO pin driving extra address lines on an
|
||||
# external ROM IC.
|
||||
#
|
||||
# To be able to parse those non-standard >4kB ROMs, this implementation
|
||||
# keeps track of 16-bit addresses by simply preserving the upper 4 bits
|
||||
# (see Addr8 and Addr12 constructors).
|
||||
#
|
||||
# To redirect the flow to a different 4kB bank, it is necessary to manually
|
||||
# set a flow override (with Fallthrough->Set) on the specific instruction.
|
||||
#
|
||||
# That cannot really be automated at this level because there is no "standard"
|
||||
# mechanism for external bank control.
|
||||
|
||||
|
||||
|
||||
# Do not take BS into account when decompiling
|
||||
|
@ -28,8 +44,12 @@ define register offset=0x00 size=1 [ A SP ];
|
|||
define register offset=0x10 size=1 [ R0 R1 R2 R3 R4 R5 R6 R7 ];
|
||||
@endif
|
||||
define register offset=0x20 size=2 [ PC ];
|
||||
define register offset=0x30 size=1 [ C AC F0 F1 BS DFB ]; # single bit
|
||||
define register offset=0x30 size=1 [ C AC F0 F1 BS ]; # single bit
|
||||
|
||||
define register offset=0x80 size=4 bankreg;
|
||||
define context bankreg
|
||||
DBF=(0,0)
|
||||
;
|
||||
|
||||
################################################################
|
||||
# Tokens
|
||||
|
@ -50,7 +70,7 @@ define token opbyte (8)
|
|||
ppfill = (2,3)
|
||||
abit = (5,7) dec
|
||||
abfill = (4,4)
|
||||
dfb = (4,4)
|
||||
dbf = (4,4)
|
||||
bs = (4,4)
|
||||
;
|
||||
|
||||
|
@ -71,7 +91,9 @@ attach variables ri [ R0 R1 ];
|
|||
attach names rn [ R0 R1 R2 R3 R4 R5 R6 R7 ];
|
||||
attach names ri [ R0 R1 ];
|
||||
@endif
|
||||
attach names dfb [ MB0 MB1 ];
|
||||
|
||||
attach names abit ["0" "1" "2" "3" "4" "5" "6" "7"];
|
||||
attach names dbf [ MB0 MB1 ];
|
||||
attach names bs [ RB0 RB1 ];
|
||||
attach names pp [ BUS P1 P2 _ ];
|
||||
attach names xpp [ P4 P5 P6 P7 ];
|
||||
|
@ -247,13 +269,13 @@ RiX: Rind is Rind {
|
|||
export *[EXTMEM]:1 Rind;
|
||||
}
|
||||
PData: @A is A {
|
||||
local addr:2 = inst_next; addr[0,7] = A; export *[CODE]:1 addr;
|
||||
local addr:2 = inst_next; addr[0,8] = A; export *[CODE]:1 addr;
|
||||
}
|
||||
P3Data: @A is A {
|
||||
local addr:2 = 0x300; addr[0,7] = A; export *[CODE]:1 addr;
|
||||
local addr:2 = 0x300; addr[0,8] = A; export *[CODE]:1 addr;
|
||||
}
|
||||
AddrInd: PData is PData {
|
||||
local addr:2 = inst_next; addr[0,7] = PData; export *[CODE]:1 addr;
|
||||
local addr:2 = inst_next; addr[0,8] = PData; export addr;
|
||||
}
|
||||
Ab: abit is abit {
|
||||
local bit:1 = (A>>abit)&1; export bit;
|
||||
|
@ -264,10 +286,10 @@ Data: "#"^data is data {
|
|||
Imm: Data is oplo=3; Data {
|
||||
export Data;
|
||||
}
|
||||
Addr8: addr is addr8 [ addr = (inst_next $and 0xf00)+addr8; ] {
|
||||
Addr8: addr is addr8 [ addr = (inst_next $and 0xff00)+addr8; ] {
|
||||
export *[CODE]:1 addr;
|
||||
}
|
||||
Addr12: addr is aopaddr & adata [ addr = (DFB*2048)+(aopaddr*256)+adata; ] {
|
||||
Addr12: addr is aopaddr & adata [ addr = (inst_next & 0xf000) + (DBF*0x800) + (aopaddr*256)+adata; ] {
|
||||
export *[CODE]:1 addr;
|
||||
}
|
||||
Bus: "BUS" is epsilon {
|
||||
|
@ -430,7 +452,7 @@ RniI: Imm is Imm {
|
|||
goto Addr12;
|
||||
}
|
||||
:JMPP AddrInd is ophi=11 & oplo=3 & AddrInd {
|
||||
goto AddrInd;
|
||||
goto [AddrInd];
|
||||
}
|
||||
:MOV A,Imm is (ophi=2 & A)... & Imm {
|
||||
A = Imm;
|
||||
|
@ -510,9 +532,9 @@ RniI: Imm is Imm {
|
|||
:RRC A is ophi=6 & oplo=7 & A {
|
||||
rotc(A&1, (A>>1)|(C<<7));
|
||||
}
|
||||
:SEL dfb is (ophi=14 | ophi=15) & oplo=5 & dfb {
|
||||
DFB = dfb;
|
||||
}
|
||||
:SEL dbf is (ophi=14 | ophi=15) & oplo=5 & dbf
|
||||
[ DBF=dbf; globalset(inst_next,DBF); ]
|
||||
{}
|
||||
:SEL bs is (ophi=12 | ophi=13) & oplo=5 & bs {
|
||||
setbank(bs);
|
||||
}
|
||||
|
|
|
@ -2726,13 +2726,13 @@ Rn_VPR128.D.imm_neon_uimm1: Rn_VPR128.D^"["^imm_neon_uimm1^"]" is Rn_VPR128.D &
|
|||
Re_VPR128.H.vIndexHL: Re_VPR128.H^"["^vIndexHL^"]" is Re_VPR128.H & vIndexHL { }
|
||||
|
||||
@if DATA_ENDIAN == "little"
|
||||
Re_VPR128Lo.H.sel: Re_VPR128, val is Re_VPR128 & b_2223=2 & b_2121 & b_1111 [ val = 0x5000 + 32*Re_VPR128 + (b_1111 * 2 + b_2121)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128, val is Re_VPR128 & b_2223=1 & b_2121 & b_1111 & b_2020 [ val = 0x5000 + 32*Re_VPR128 + (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128, val is Re_VPR128 & b_2223=0 & b_2121 & b_1111 & b_2020 [ val = 0x5000 + 32*Re_VPR128 + (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128Lo, val is Re_VPR128Lo & b_2223=2 & b_2121 & b_1111 [ val = 0x5000 + 32*Re_VPR128Lo + (b_1111 * 2 + b_2121)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128Lo, val is Re_VPR128Lo & b_2223=1 & b_2121 & b_1111 & b_2020 [ val = 0x5000 + 32*Re_VPR128Lo + (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128Lo, val is Re_VPR128Lo & b_2223=0 & b_2121 & b_1111 & b_2020 [ val = 0x5000 + 32*Re_VPR128Lo + (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
@else
|
||||
Re_VPR128Lo.H.sel: Re_VPR128, val is Re_VPR128 & b_2223=2 & b_2121 & b_1111 [ val = 0x501e + 32*Re_VPR128 - (b_1111 * 2 + b_2121)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128, val is Re_VPR128 & b_2223=1 & b_2121 & b_1111 & b_2020 [ val = 0x501e + 32*Re_VPR128 - (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128, val is Re_VPR128 & b_2223=0 & b_2121 & b_1111 & b_2020 [ val = 0x501e + 32*Re_VPR128 - (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128Lo, val is Re_VPR128Lo & b_2223=2 & b_2121 & b_1111 [ val = 0x501e + 32*Re_VPR128Lo - (b_1111 * 2 + b_2121)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128Lo, val is Re_VPR128Lo & b_2223=1 & b_2121 & b_1111 & b_2020 [ val = 0x501e + 32*Re_VPR128Lo - (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
Re_VPR128Lo.H.sel: Re_VPR128Lo, val is Re_VPR128Lo & b_2223=0 & b_2121 & b_1111 & b_2020 [ val = 0x501e + 32*Re_VPR128Lo - (b_1111*4 + b_2121*2 + b_2020)*2; ] { export *[register]:2 val; }
|
||||
@endif
|
||||
Re_VPR128Lo.H.vIndexHLM: Re_VPR128Lo.H^"["^vIndexHLM^"]" is Re_VPR128Lo.H & vIndexHLM & Re_VPR128Lo.H.sel { export Re_VPR128Lo.H.sel; }
|
||||
|
||||
|
|
|
@ -48,7 +48,15 @@ re-disassembly of all instructions.</p>
|
|||
a user to make certain transitions between similar language
|
||||
implementations. Such transitions are generally facilitated via a
|
||||
default translator, although certain limitations are imposed based upon
|
||||
address space sizes and register mappings.<br>
|
||||
address space sizes and register mappings.</p>
|
||||
<p>Any changes made to a Data Organization could impact the packing of
|
||||
components within a structure or union. While such changes should be avoided
|
||||
due to the possible fallout, any such change to a
|
||||
<span style="font-style: italic;">*.cspec</span> should be made
|
||||
in conjuction with a version change to all affected languages within
|
||||
the relavent <span style="font-style: italic;">*.ldefs</span> files. The
|
||||
resulting program upgrade will allow affected data types to be updated.
|
||||
<br>
|
||||
</p>
|
||||
<h2><a name="versioning"></a>Language Versioning</h2>
|
||||
<p>A language's version is specified as a<span
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue