GP-1633/GP-2308 Added ProgramArchitecture to datatype managers.

Refactored ProjectDataTypeManager to extend StandaloneDataTypeManager.
Added actions to datatype tree to allow setting archive architecture.
Added use of storage translators when switching architectures.  Allow
FunctionDefinition to accept arbitrary calling convention
names and many other misc changes.
This commit is contained in:
ghidra1 2021-12-27 17:01:32 -05:00
parent 75a185aa9e
commit a4776892bd
248 changed files with 6282 additions and 2935 deletions

View file

@ -345,11 +345,6 @@
<attribute name="extrapop"/>
<attribute name="stackshift"/>
<attribute name="name"/>
<optional>
<attribute name="type">
<ref name="generic_calling_convention_type"/>
</attribute>
</optional>
<optional>
<attribute name="strategy">

View file

@ -23,7 +23,6 @@ import ghidra.framework.Application;
import ghidra.framework.data.DomainObjectAdapterDB;
import ghidra.framework.model.*;
import ghidra.framework.options.Options;
import ghidra.program.database.data.ProjectDataTypeManager;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.listing.DataTypeArchive;
@ -32,7 +31,6 @@ import ghidra.program.util.*;
import ghidra.util.InvalidNameException;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
/**
* Database implementation for Data Type Archive.
@ -493,7 +491,7 @@ public class DataTypeArchiveDB extends DomainObjectAdapterDB
// }
try {
dataTypeManager = new ProjectDataTypeManager(dbh, openMode, this, lock, monitor);
dataTypeManager = new ProjectDataTypeManager(this, dbh, openMode, this, lock, monitor);
}
catch (VersionException e) {
versionExc = e.combine(versionExc);
@ -506,7 +504,6 @@ public class DataTypeArchiveDB extends DomainObjectAdapterDB
private void initManagers(int openMode, TaskMonitor monitor)
throws IOException, CancelledException {
monitor.checkCanceled();
dataTypeManager.setDataTypeArchive(this);
dataTypeManager.archiveReady(openMode, monitor);
}

View file

@ -36,7 +36,6 @@ import ghidra.program.database.code.InstructionDB;
import ghidra.program.database.data.ProgramDataTypeManager;
import ghidra.program.database.external.ExternalManagerDB;
import ghidra.program.database.function.FunctionManagerDB;
import ghidra.program.database.map.AddressMap;
import ghidra.program.database.map.AddressMapDB;
import ghidra.program.database.mem.MemoryMapDB;
import ghidra.program.database.module.TreeManager;
@ -745,13 +744,13 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
/**
* Returns this programs address map.
* NOTE: This method has been dropped from the Program interface to help
* discourage the use of the program's address map since bad assumptions
* NOTE: This method should be dropped from the {@link Program} interface to help
* discourage the its use external to this implementation since bad assumptions
* are frequently made about address keys which may not be ordered or sequential
* across an entire address space.
*/
@Override
public AddressMap getAddressMap() {
public AddressMapDB getAddressMap() {
return addrMap;
}
@ -1678,7 +1677,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
monitor.checkCanceled();
try {
managers[SYMBOL_MGR] = new SymbolManager(dbh, addrMap, openMode, lock, monitor);
managers[SYMBOL_MGR] = new SymbolManager(dbh, addrMap, openMode, this, lock, monitor);
}
catch (VersionException e) {
versionExc = e.combine(versionExc);
@ -2069,6 +2068,9 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
contextMgr.initializeDefaultValues(language, compilerSpec);
}
// Update datatype manager data organization
getDataTypeManager().languageChanged(monitor);
// Force function manager to reconcile calling conventions
managers[FUNCTION_MGR].setProgram(this);
managers[FUNCTION_MGR].programReady(UPDATE, getStoredVersion(), monitor);
@ -2443,6 +2445,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
lock.acquire();
try {
((ProgramCompilerSpec) compilerSpec).installExtensions();
getFunctionManager().invalidateCache(true);
getDataTypeManager().invalidateCache();
}
finally {
lock.release();

View file

@ -13,17 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.data;
package ghidra.program.database;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import javax.help.UnsupportedOperationException;
import db.*;
import db.util.ErrorHandler;
import ghidra.framework.model.DomainFile;
import ghidra.program.database.DataTypeArchiveDB;
import ghidra.framework.store.LockException;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.IncompatibleLanguageException;
import ghidra.program.util.DataTypeArchiveChangeManager;
import ghidra.util.InvalidNameException;
import ghidra.util.Lock;
@ -35,13 +38,23 @@ import ghidra.util.task.TaskMonitor;
* Class for managing data types in a project archive
* NOTE: default data organization is used.
*/
public class ProjectDataTypeManager extends DataTypeManagerDB
public class ProjectDataTypeManager extends StandAloneDataTypeManager
implements ProjectArchiveBasedDataTypeManager {
private DataTypeArchiveDB dataTypeArchive;
private final DataTypeArchiveDB dataTypeArchive;
/**
* Constructor
* Constructor for a data-type manager using a specified DBHandle.
* <p>
* <B>NOTE:</B> If archive has an assigned architecture, issues may arise due to a revised or
* missing {@link Language}/{@link CompilerSpec} which will result in a warning but not
* prevent the archive from being opened. Such a warning condition will ne logged and may
* result in missing or stale information for existing datatypes which have architecture related
* data. In some case it may be appropriate to
* {@link FileDataTypeManager#getWarning() check for warnings} on the returned archive
* object prior to its use.
*
* @param dataTypeArchive associated archive
* @param handle open database handle
* @param openMode the program open mode
* @param errHandler the database I/O error handler
@ -51,17 +64,12 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
* @throws VersionException if the database does not match the expected version.
* @throws IOException if a database I/O error occurs.
*/
public ProjectDataTypeManager(DBHandle handle, int openMode, ErrorHandler errHandler, Lock lock,
ProjectDataTypeManager(DataTypeArchiveDB dataTypeArchive, DBHandle handle, int openMode,
ErrorHandler errHandler, Lock lock,
TaskMonitor monitor) throws CancelledException, VersionException, IOException {
super(handle, null, openMode, errHandler, lock, monitor);
}
/**
* Set the associated Archive
* @param dtArchive associated archive
*/
public void setDataTypeArchive(DataTypeArchiveDB dtArchive) {
this.dataTypeArchive = dtArchive;
super(handle, openMode, errHandler, lock, monitor);
this.dataTypeArchive = dataTypeArchive;
reportWarning();
}
@Override
@ -69,11 +77,6 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
return dataTypeArchive.getDomainFile().getName();
}
@Override
public Pointer getPointer(DataType dt) {
return PointerDataType.getPointer(dt, dataTypeArchive.getDefaultPointerSize());
}
@Override
public void setName(String name) throws InvalidNameException {
if (name == null || name.length() == 0) {
@ -84,6 +87,23 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
categoryRenamed(CategoryPath.ROOT, null);
}
@Override
public void clearProgramArchitecture(TaskMonitor monitor)
throws CancelledException, IOException, LockException {
dataTypeArchive.checkExclusiveAccess();
super.clearProgramArchitecture(monitor);
}
@Override
public void setProgramArchitecture(Language language, CompilerSpecID compilerSpecId,
LanguageUpdateOption updateOption, TaskMonitor monitor)
throws CompilerSpecNotFoundException, LanguageNotFoundException, IOException,
LockException, UnsupportedOperationException, IncompatibleLanguageException,
CancelledException {
dataTypeArchive.checkExclusiveAccess();
super.setProgramArchitecture(language, compilerSpecId, updateOption, monitor);
}
////////////////////
@Override
public void dataTypeChanged(DataType dt, boolean isAutoChange) {
@ -169,21 +189,12 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
///////////////////
@Override
protected void replaceDataTypeIDs(long oldDataTypeID, long newDataTypeID) {
// dataTypeArchive.getCodeManager().replace(oldID, newID, monitor);
// TODO
// do nothing
}
@Override
protected void deleteDataTypeIDs(LinkedList<Long> deletedIds, TaskMonitor monitor)
throws CancelledException {
long[] ids = new long[deletedIds.size()];
Iterator<Long> it = deletedIds.iterator();
int i = 0;
while (it.hasNext()) {
ids[i++] = it.next().longValue();
}
// dataTypeArchive.getCodeManager().clearData(ids, monitor);
// TODO
protected void deleteDataTypeIDs(LinkedList<Long> deletedIds, TaskMonitor monitor) {
// do nothing
}
@Override
@ -191,6 +202,7 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
return dataTypeArchive.openTransaction(description);
}
@SuppressWarnings("sync-override")
@Override
public int startTransaction(String description) {
return dataTypeArchive.startTransaction(description);
@ -201,6 +213,7 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
dataTypeArchive.flushEvents();
}
@SuppressWarnings("sync-override")
@Override
public void endTransaction(int transactionID, boolean commit) {
dataTypeArchive.endTransaction(transactionID, commit);
@ -231,7 +244,7 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
public void archiveReady(int openMode, TaskMonitor monitor)
throws IOException, CancelledException {
if (openMode == DBConstants.UPGRADE) {
doSourceArchiveUpdates(null, monitor);
doSourceArchiveUpdates(monitor);
migrateOldFlexArrayComponentsIfRequired(monitor);
}
}

View file

@ -721,7 +721,7 @@ public class SpecExtension {
PrototypeModel currentModel = function.getCallingConvention();
if (currentModel != null && currentModel.getName().equals(modelName)) {
try {
function.setCallingConvention("unknown");
function.setCallingConvention(Function.UNKNOWN_CALLING_CONVENTION_STRING);
}
catch (InvalidInputException e) {
// shouldn't reach here

View file

@ -47,6 +47,7 @@ class DataDB extends CodeUnitDB implements Data {
protected DataType baseDataType;
protected int level = 0;
protected ProgramDataTypeManager dataMgr;
private Boolean hasMutabilitySetting;

View file

@ -18,6 +18,7 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -33,13 +34,25 @@ abstract class ArrayDBAdapter {
static final int ARRAY_ELEMENT_LENGTH_COL = ArrayDBAdapterV1.V1_ARRAY_ELEMENT_LENGTH_COL;
static final int ARRAY_CAT_COL = ArrayDBAdapterV1.V1_ARRAY_CAT_COL;
static ArrayDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
/**
* Gets an adapter for working with the {@link ArrayDB} database table.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return adapter instance
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is a problem accessing the database.
* @throws CancelledException task cancelled
*/
static ArrayDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new ArrayDBAdapterV1(handle, true);
return new ArrayDBAdapterV1(handle, tablePrefix, true);
}
try {
return new ArrayDBAdapterV1(handle, false);
return new ArrayDBAdapterV1(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -47,33 +60,36 @@ abstract class ArrayDBAdapter {
}
ArrayDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
}
static ArrayDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
private static ArrayDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
return new ArrayDBAdapterV0(handle);
}
static ArrayDBAdapter upgrade(DBHandle handle, ArrayDBAdapter oldAdapter)
throws VersionException, IOException {
private static ArrayDBAdapter upgrade(DBHandle handle, ArrayDBAdapter oldAdapter,
String tablePrefix,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
ArrayDBAdapter tmpAdapter = null;
try {
tmpAdapter = new ArrayDBAdapterV1(tmpHandle, true);
tmpAdapter = new ArrayDBAdapterV1(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec);
}
oldAdapter.deleteTable(handle);
ArrayDBAdapterV1 newAdapter = new ArrayDBAdapterV1(handle, true);
ArrayDBAdapterV1 newAdapter = new ArrayDBAdapterV1(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec);
}

View file

@ -24,13 +24,14 @@ import ghidra.util.exception.VersionException;
*
*/
class ArrayDBAdapterV0 extends ArrayDBAdapter {
private static final int VERSION = 0;
private static final String ARRAY_TABLE_NAME = "Arrays";
private static final int V0_ARRAY_DT_ID_COL = 0;
private static final int V0_ARRAY_DIM_COL = 1;
private static final int V0_ARRAY_ELEMENT_LENGTH_COL = 2; // applies to sizable dynamic types only
private Table table;
// DO NOT REMOVE - this documents the schema used in version 0.
// public static final Schema SCHEMA = new Schema(0, "Array ID",
// new Class[] {LongField.class, IntField.class,
@ -38,9 +39,13 @@ class ArrayDBAdapterV0 extends ArrayDBAdapter {
// new String[] {"Data Type ID", "Dimension",
// "Length"});
private Table table;
/**
* Constructor
*
* Gets a version 0 read-only adapter for the {@link ArrayDB} database table.
* @param handle handle to the database containing the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public ArrayDBAdapterV0(DBHandle handle) throws VersionException {
@ -48,9 +53,8 @@ class ArrayDBAdapterV0 extends ArrayDBAdapter {
if (table == null) {
throw new VersionException("Missing Table: " + ARRAY_TABLE_NAME);
}
else if (table.getSchema().getVersion() != 0) {
throw new VersionException("Expected version 0 for table " + ARRAY_TABLE_NAME +
" but got " + table.getSchema().getVersion());
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException();
}
}

View file

@ -25,40 +25,49 @@ import ghidra.util.exception.VersionException;
* To change the template for this generated type comment go to
* {@literal Window>Preferences>Java>Code Generation>Code and Comments}
*
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class ArrayDBAdapterV1 extends ArrayDBAdapter {
static final int VERSION = 1;
static final String ARRAY_TABLE_NAME = "Arrays";
static final int V1_ARRAY_DT_ID_COL = 0;
static final int V1_ARRAY_DIM_COL = 1;
static final int V1_ARRAY_ELEMENT_LENGTH_COL = 2; // applies to sizable dynamic types only
static final int V1_ARRAY_CAT_COL = 3;
private Table table;
public static final Schema V1_SCHEMA =
new Schema(VERSION, "Array ID",
new Field[] { LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE,
LongField.INSTANCE },
new String[] { "Data Type ID", "Dimension", "Length", "Cat ID" });
/**
* Constructor
*
*/
public ArrayDBAdapterV1(DBHandle handle, boolean create) throws VersionException, IOException {
private Table table;
/**
* Gets a version 1 adapter for the {@link ArrayDB} database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create create table if true else acquire for read-only or update use
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException an IO error occured during table creation
*/
public ArrayDBAdapterV1(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + ARRAY_TABLE_NAME;
if (create) {
table = handle.createTable(ARRAY_TABLE_NAME, V1_SCHEMA, new int[] { V1_ARRAY_CAT_COL });
table = handle.createTable(tableName, V1_SCHEMA, new int[] { V1_ARRAY_CAT_COL });
}
else {
table = handle.getTable(ARRAY_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException("Missing Table: " + ARRAY_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
else if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(VersionException.NEWER_VERSION, false);
int version = table.getSchema().getVersion();
if (version != VERSION) {
throw new VersionException(version < VERSION);
}
}
}
@ -67,11 +76,7 @@ class ArrayDBAdapterV1 extends ArrayDBAdapter {
public DBRecord createRecord(long dataTypeID, int numberOfElements, int length, long catID)
throws IOException {
long tableKey = table.getKey();
// if (tableKey <= DataManager.VOID_DATATYPE_ID) {
// tableKey = DataManager.VOID_DATATYPE_ID +1;
// }
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.ARRAY, tableKey);
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.ARRAY, table.getKey());
DBRecord record = V1_SCHEMA.createRecord(key);
record.setLongValue(V1_ARRAY_DT_ID_COL, dataTypeID);
@ -105,7 +110,7 @@ class ArrayDBAdapterV1 extends ArrayDBAdapter {
@Override
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(ARRAY_TABLE_NAME);
handle.deleteTable(table.getName());
}
@Override

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import db.*;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
* Database adapter for managing built-in data types.
@ -35,14 +34,14 @@ public abstract class BuiltinDBAdapter {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param monitor the monitor to use for displaying status or for canceling.
* @param tablePrefix prefix to be used with default table name
* @return the adapter for accessing the table of built-in data types.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there was a problem accessing the database
*/
static BuiltinDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
static BuiltinDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix)
throws VersionException, IOException {
return new BuiltinDBAdapterV0(handle, openMode == DBConstants.CREATE);
return new BuiltinDBAdapterV0(handle, tablePrefix, openMode == DBConstants.CREATE);
}
/**

View file

@ -24,38 +24,44 @@ import ghidra.util.exception.VersionException;
* Version 0 implementation of the adapter for accessing the built-ins table.
*/
class BuiltinDBAdapterV0 extends BuiltinDBAdapter {
private static final int VERSION = 0;
static final String BUILT_IN_TABLE_NAME = "Built-in datatypes";
static final int V0_BUILT_IN_NAME_COL = 0;
static final int V0_BUILT_IN_CLASSNAME_COL = 1;
static final int V0_BUILT_IN_CAT_COL = 2;
static final Schema V0_SCHEMA = new Schema(0, "Data Type ID",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, LongField.INSTANCE },
new String[] { "Name", "Class Name", "Category ID" });
private Table table;
/**
* Gets a version 0 adapter for the Built-Ins database table.
* @param handle handle to the database containing the table.
* @param create true if this constructor should create the table.
* @param tablePrefix prefix to be used with default table name
* @param create create table if true else acquire for read-only or update use
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if there is trouble accessing the database.
*/
public BuiltinDBAdapterV0(DBHandle handle, boolean create)
public BuiltinDBAdapterV0(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + BUILT_IN_TABLE_NAME;
if (create) {
table = handle.createTable(BUILT_IN_TABLE_NAME, V0_SCHEMA,
table = handle.createTable(tableName, V0_SCHEMA,
new int[] { V0_BUILT_IN_CAT_COL });
}
else {
table = handle.getTable(BUILT_IN_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException("Missing Table: " + BUILT_IN_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
else if (table.getSchema().getVersion() != 0) {
throw new VersionException("Expected version 0 for table " + BUILT_IN_TABLE_NAME +
" but got " + table.getSchema().getVersion());
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
}

View file

@ -0,0 +1,119 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.data;
import java.io.IOException;
import java.util.Set;
import java.util.function.Consumer;
import db.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
* Adapter to access the Function Calling Conventions tables.
*/
abstract class CallingConventionDBAdapter {
static final byte UNKNOWN_CALLING_CONVENTION_ID = (byte) 0;
static final byte DEFAULT_CALLING_CONVENTION_ID = (byte) 1;
static final byte FIRST_CALLING_CONVENTION_ID = (byte) 2;
static final String CALLING_CONVENTION_TABLE_NAME = "Calling Conventions";
static final Schema CALLING_CONVENTION_SCHEMA =
CallingConventionDBAdapterV0.V0_CALLING_CONVENTION_SCHEMA;
// Calling Convention Columns
static final int CALLING_CONVENTION_NAME_COL =
CallingConventionDBAdapterV0.V0_CALLING_CONVENTION_NAME_COL;
/**
* Gets an adapter for working with the calling convention database table.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return adapter instance
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is a problem accessing the database.
* @throws CancelledException if task is cancelled
*/
static CallingConventionDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new CallingConventionDBAdapterV0(handle, tablePrefix, true);
}
try {
return new CallingConventionDBAdapterV0(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
throw e;
}
CallingConventionDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
}
private static CallingConventionDBAdapter findReadOnlyAdapter(DBHandle handle) {
return new CallingConventionDBAdapterNoTable();
}
private static CallingConventionDBAdapter upgrade(DBHandle handle,
CallingConventionDBAdapter oldAdapter, String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException {
return new CallingConventionDBAdapterV0(handle, tablePrefix, true);
}
/**
* Get (and assign if needed thus requiring open transaction) the ID associated with the
* specified calling convention name. If name is a new convention and the number of stored
* convention names exceeds 127 the returned ID will correspond to the unknown calling
* convention.
* @param name calling convention name or null if unknown
* @param conventionAdded callback when new calling convention is added
* @return calling convention ID
* @throws IOException if an IO error occurs
*/
abstract byte getCallingConventionId(String name, Consumer<String> conventionAdded)
throws IOException;
/**
* Get calling convention name which corresponds to the specified id.
* @param id calling convention storage ID
* @return calling convention name or null if unknown call convention
* @throws IOException if IO error occurs
*/
abstract String getCallingConventionName(byte id) throws IOException;
/**
* Clear calling convention cached lookup maps
*/
abstract void invalidateCache();
/**
* Get all stored calling convention names. The "default" and "unknown"
* names are excluded from this set.
* @return set of all stored calling convention names
* @throws IOException if an IO error occurs
*/
abstract Set<String> getCallingConventionNames() throws IOException;
}

View file

@ -0,0 +1,56 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.data;
import java.io.IOException;
import java.util.Set;
import java.util.function.Consumer;
import javax.help.UnsupportedOperationException;
/**
* Adapter when no Calling Convention table exists.
*/
class CallingConventionDBAdapterNoTable extends CallingConventionDBAdapter {
/**
* Gets a no-table adapter for the calling convention database table.
*/
CallingConventionDBAdapterNoTable() {
// no table - do nothing
}
@Override
byte getCallingConventionId(String name, Consumer<String> conventionAdded) throws IOException {
throw new UnsupportedOperationException();
}
@Override
String getCallingConventionName(byte id) throws IOException {
return null;
}
@Override
void invalidateCache() {
// do nothing
}
@Override
Set<String> getCallingConventionNames() throws IOException {
return Set.of();
}
}

View file

@ -0,0 +1,187 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.data;
import java.io.IOException;
import java.util.*;
import java.util.function.Consumer;
import com.google.common.collect.Range;
import com.google.common.collect.TreeRangeSet;
import db.*;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.listing.Function;
import ghidra.util.Msg;
import ghidra.util.exception.VersionException;
/**
* Version 0 implementation for the calling conventions tables adapter.
*
*/
class CallingConventionDBAdapterV0 extends CallingConventionDBAdapter {
private static final int VERSION = 0;
// Calling Convention Columns
// Key field is the Calling convention ID, which is a Byte field.
static final int V0_CALLING_CONVENTION_NAME_COL = 0;
static final Schema V0_CALLING_CONVENTION_SCHEMA = new Schema(0, ByteField.INSTANCE, "ID",
new Field[] { StringField.INSTANCE }, new String[] { "Name" });
private Table callingConventionTable;
private Map<String, Byte> callingConventionNameToIDMap;
private Map<Byte, String> callingConventionIDToNameMap;
// There is currently no method for removing an allocated calling convention name/ID,
// therefor we can assume key consumption will be sequential until the ability
// to delete is added. Use of freeKeySet can be eliminated if delete ability never added.
private TreeRangeSet<Byte> freeKeySet; // closed-ranges only
/**
* Gets a version 0 adapter for the calling convention database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO error occurs
*/
CallingConventionDBAdapterV0(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + CALLING_CONVENTION_TABLE_NAME;
if (create) {
// No additional indexed fields.
callingConventionTable = handle.createTable(tableName,
V0_CALLING_CONVENTION_SCHEMA, new int[] {});
}
else {
callingConventionTable = handle.getTable(tableName);
if (callingConventionTable == null) {
throw new VersionException(true);
}
if (callingConventionTable.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
}
/**
* Remove next available free key value from freeKeySet.
* @return the next available key. A negative value indicates that all allowed IDs have
* been used.
*/
private byte removeFirstAvailableKey() {
Iterator<Range<Byte>> it = freeKeySet.asRanges().iterator();
if (!it.hasNext()) {
return -1;
}
Range<Byte> r = it.next();
it.remove();
byte nextId = r.lowerEndpoint();
byte lastId = r.upperEndpoint();
if (nextId != lastId) {
freeKeySet.add(Range.closed((byte) (nextId + 1), lastId));
}
return nextId;
}
@Override
void invalidateCache() {
callingConventionNameToIDMap = null;
callingConventionIDToNameMap = null;
freeKeySet = null;
}
private void populateCache() throws IOException {
if (callingConventionNameToIDMap != null) {
return;
}
callingConventionNameToIDMap = new HashMap<>();
callingConventionIDToNameMap = new HashMap<>();
freeKeySet = TreeRangeSet.create();
int nextKey = FIRST_CALLING_CONVENTION_ID;
RecordIterator iterator = callingConventionTable.iterator();
while (iterator.hasNext()) {
DBRecord rec = iterator.next();
byte id = (byte) rec.getKey();
String name = rec.getString(V0_CALLING_CONVENTION_NAME_COL);
callingConventionIDToNameMap.put(id, name);
callingConventionNameToIDMap.put(name, id);
if (nextKey != id) {
freeKeySet.add(Range.closed((byte) nextKey, (byte) (id - 1)));
}
nextKey = id + 1;
}
if (nextKey <= Byte.MAX_VALUE) {
freeKeySet.add(Range.closed((byte) nextKey, Byte.MAX_VALUE));
}
}
@Override
byte getCallingConventionId(String name, Consumer<String> conventionAdded) throws IOException {
if (name == null || name.equals(CompilerSpec.CALLING_CONVENTION_unknown)) {
return UNKNOWN_CALLING_CONVENTION_ID;
}
else if (name.equals(CompilerSpec.CALLING_CONVENTION_default)) {
return DEFAULT_CALLING_CONVENTION_ID;
}
populateCache();
Byte id = callingConventionNameToIDMap.get(name);
if (id != null) {
return id;
}
byte newId = removeFirstAvailableKey();
if (newId < 0) {
Msg.error(this, "Unable to assign calling convention `" + name +
"` - allocation capacity exceeded");
return UNKNOWN_CALLING_CONVENTION_ID;
}
DBRecord record = V0_CALLING_CONVENTION_SCHEMA.createRecord(new ByteField(newId));
record.setString(V0_CALLING_CONVENTION_NAME_COL, name);
callingConventionTable.putRecord(record);
callingConventionIDToNameMap.put(newId, name);
callingConventionNameToIDMap.put(name, newId);
conventionAdded.accept(name);
return newId;
}
@Override
String getCallingConventionName(byte id) throws IOException {
if (id == DEFAULT_CALLING_CONVENTION_ID) {
return Function.DEFAULT_CALLING_CONVENTION_STRING;
}
else if (id == UNKNOWN_CALLING_CONVENTION_ID) {
return null;
}
populateCache();
return callingConventionIDToNameMap.get(id);
}
@Override
Set<String> getCallingConventionNames() throws IOException {
populateCache();
return callingConventionNameToIDMap.keySet();
}
}

View file

@ -18,16 +18,25 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.program.model.data.Category;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
abstract class CategoryDBAdapter {
static final int CATEGORY_NAME_COL = CategoryDBAdapterV0.V0_CATEGORY_NAME_COL;
static final int CATEGORY_PARENT_COL = CategoryDBAdapterV0.V0_CATEGORY_PARENT_COL;
static CategoryDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
/**
* Gets an adapter for working with the {@link Category} database table.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @return adapter instance
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is a problem accessing the database.
*/
static CategoryDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix)
throws VersionException, IOException {
return new CategoryDBAdapterV0(handle, openMode);
return new CategoryDBAdapterV0(handle, tablePrefix, openMode == DBConstants.CREATE);
}
/**
@ -81,7 +90,16 @@ abstract class CategoryDBAdapter {
*/
abstract DBRecord getRootRecord() throws IOException;
/**
* Update record in database
* @param record category record
* @throws IOException if IO error occurs
*/
abstract void putRecord(DBRecord record) throws IOException;
/**
* Get the total number of category records
* @return category record count
*/
abstract int getRecordCount();
}

View file

@ -21,9 +21,13 @@ import db.*;
import ghidra.util.exception.VersionException;
class CategoryDBAdapterV0 extends CategoryDBAdapter {
private static final int VERSION = 0;
static final String CATEGORY_TABLE_NAME = "Categories";
static final int V0_CATEGORY_NAME_COL = 0;
static final int V0_CATEGORY_PARENT_COL = 1;
static final Schema V0_SCHEMA =
new Schema(0, "Category ID", new Field[] { StringField.INSTANCE, LongField.INSTANCE },
new String[] { "Name", "Parent ID" });
@ -31,34 +35,38 @@ class CategoryDBAdapterV0 extends CategoryDBAdapter {
private Table table;
/**
* Constructor
*
* Gets a version 0 adapter for the Category database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO error occurs
*/
public CategoryDBAdapterV0(DBHandle handle, int openMode) throws VersionException, IOException {
if (openMode == DBConstants.CREATE) {
table = handle.createTable(CATEGORY_TABLE_NAME, V0_SCHEMA,
new int[] { V0_CATEGORY_PARENT_COL });
CategoryDBAdapterV0(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + CATEGORY_TABLE_NAME;
if (create) {
table = handle.createTable(tableName, V0_SCHEMA, new int[] { V0_CATEGORY_PARENT_COL });
}
else {
table = handle.getTable(CATEGORY_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException("Missing Table: " + CATEGORY_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
else if (table.getSchema().getVersion() != 0) {
throw new VersionException("Expected version 0 for table " + CATEGORY_TABLE_NAME +
" but got " + table.getSchema().getVersion());
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
}
@Override
public DBRecord getRecord(long categoryID) throws IOException {
DBRecord getRecord(long categoryID) throws IOException {
return table.getRecord(categoryID);
}
@Override
public Field[] getRecordIdsWithParent(long categoryID) throws IOException {
Field[] getRecordIdsWithParent(long categoryID) throws IOException {
return table.findRecords(new LongField(categoryID), V0_CATEGORY_PARENT_COL);
}
@ -76,7 +84,7 @@ class CategoryDBAdapterV0 extends CategoryDBAdapter {
}
@Override
public DBRecord createCategory(String name, long parentID) throws IOException {
DBRecord createCategory(String name, long parentID) throws IOException {
long key = table.getKey();
if (key == 0) {
key = 1;
@ -90,12 +98,12 @@ class CategoryDBAdapterV0 extends CategoryDBAdapter {
}
@Override
public boolean removeCategory(long categoryID) throws IOException {
boolean removeCategory(long categoryID) throws IOException {
return table.deleteRecord(categoryID);
}
@Override
public DBRecord getRootRecord() throws IOException {
DBRecord getRootRecord() throws IOException {
Field[] keys = table.findRecords(new LongField(-1), V0_CATEGORY_PARENT_COL);
if (keys.length != 1) {
throw new IOException("Found " + keys.length + " entries for root category");

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import db.*;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
* Adapter to access the Component database table.
@ -43,14 +42,14 @@ abstract class ComponentDBAdapter {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param monitor the monitor to use for displaying status or for canceling.
* @param tablePrefix prefix to be used with default table name
* @return the adapter for accessing the table of component data types.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is a problem accessing the database.
*/
static ComponentDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
static ComponentDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix)
throws VersionException, IOException {
return new ComponentDBAdapterV0(handle, openMode == DBConstants.CREATE);
return new ComponentDBAdapterV0(handle, tablePrefix, openMode == DBConstants.CREATE);
}
/**

View file

@ -40,48 +40,41 @@ class ComponentDBAdapterV0 extends ComponentDBAdapter {
StringField.INSTANCE, StringField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE },
new String[] { "Parent", "Offset", "Data Type ID", "Field Name", "Comment",
"Component Size", "Ordinal" });
private Table componentTable;
/**
* Gets a version 0 adapter for the Component database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO error occurs
*/
public ComponentDBAdapterV0(DBHandle handle, boolean create)
ComponentDBAdapterV0(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + COMPONENT_TABLE_NAME;
if (create) {
componentTable = handle.createTable(COMPONENT_TABLE_NAME, V0_COMPONENT_SCHEMA,
componentTable = handle.createTable(tableName, V0_COMPONENT_SCHEMA,
new int[] { V0_COMPONENT_PARENT_ID_COL });
}
else {
componentTable = handle.getTable(COMPONENT_TABLE_NAME);
componentTable = handle.getTable(tableName);
if (componentTable == null) {
throw new VersionException("Missing Table: " + COMPONENT_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
int version = componentTable.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + COMPONENT_TABLE_NAME +
" but got " + componentTable.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
if (componentTable.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
}
@Override
public DBRecord createRecord(long dataTypeID, long parentID, int length, int ordinal, int offset,
DBRecord createRecord(long dataTypeID, long parentID, int length, int ordinal, int offset,
String name, String comment) throws IOException {
long tableKey = componentTable.getKey();
// if (tableKey <= DataManager.VOID_DATATYPE_ID) {
// tableKey = DataManager.VOID_DATATYPE_ID +1;
// }
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.COMPONENT, tableKey);
long key =
DataTypeManagerDB.createKey(DataTypeManagerDB.COMPONENT, componentTable.getKey());
DBRecord record = ComponentDBAdapter.COMPONENT_SCHEMA.createRecord(key);
record.setLongValue(ComponentDBAdapter.COMPONENT_PARENT_ID_COL, parentID);
record.setLongValue(ComponentDBAdapter.COMPONENT_OFFSET_COL, offset);
@ -95,22 +88,22 @@ class ComponentDBAdapterV0 extends ComponentDBAdapter {
}
@Override
public DBRecord getRecord(long componentID) throws IOException {
DBRecord getRecord(long componentID) throws IOException {
return componentTable.getRecord(componentID);
}
@Override
public void updateRecord(DBRecord record) throws IOException {
void updateRecord(DBRecord record) throws IOException {
componentTable.putRecord(record);
}
@Override
public boolean removeRecord(long componentID) throws IOException {
boolean removeRecord(long componentID) throws IOException {
return componentTable.deleteRecord(componentID);
}
@Override
public Field[] getComponentIdsInComposite(long compositeID) throws IOException {
Field[] getComponentIdsInComposite(long compositeID) throws IOException {
return componentTable.findRecords(new LongField(compositeID),
ComponentDBAdapter.COMPONENT_PARENT_ID_COL);
}

View file

@ -60,8 +60,8 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
protected abstract void initialize();
/**
* Get the preferred length for a new component. For Unions and internally
* aligned structures the preferred component length for a fixed-length dataType
* Get the preferred length for a new component. For Unions and packed
* structures the preferred component length for a fixed-length dataType
* will be the length of that dataType. Otherwise the length returned will be no
* larger than the specified length.
*

View file

@ -18,6 +18,7 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.program.database.util.DBRecordAdapter;
import ghidra.program.model.data.CompositeInternal;
import ghidra.util.UniversalID;
import ghidra.util.exception.CancelledException;
@ -27,7 +28,7 @@ import ghidra.util.task.TaskMonitor;
/**
* Adapter to access the Composite database table.
*/
abstract class CompositeDBAdapter {
abstract class CompositeDBAdapter implements DBRecordAdapter {
static final String COMPOSITE_TABLE_NAME = "Composite Data Types";
static final Schema COMPOSITE_SCHEMA = CompositeDBAdapterV5V6.V5V6_COMPOSITE_SCHEMA;
@ -73,24 +74,25 @@ abstract class CompositeDBAdapter {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of composite data types.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException task cancelled
*/
static CompositeDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
static CompositeDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
try {
return new CompositeDBAdapterV5V6(handle, openMode);
return new CompositeDBAdapterV5V6(handle, openMode, tablePrefix);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
throw e;
}
CompositeDBAdapter adapter = findReadOnlyAdapter(handle);
CompositeDBAdapter adapter = findReadOnlyAdapter(handle, tablePrefix);
if (openMode == DBConstants.UPGRADE) {
return upgrade(handle, adapter, monitor);
return upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
@ -99,14 +101,15 @@ abstract class CompositeDBAdapter {
/**
* Tries to get a read only adapter for the database whose handle is passed to this method.
* @param handle handle to prior version of the database.
* @param tablePrefix prefix to be used with default table name
* @return the read only Composite data type table adapter
* @throws VersionException if a read only adapter can't be obtained for the database handle's version.
* @throws IOException if IO error occurs
*/
static CompositeDBAdapter findReadOnlyAdapter(DBHandle handle)
private static CompositeDBAdapter findReadOnlyAdapter(DBHandle handle, String tablePrefix)
throws VersionException, IOException {
try {
return new CompositeDBAdapterV5V6(handle, DBConstants.READ_ONLY);
return new CompositeDBAdapterV5V6(handle, DBConstants.READ_ONLY, tablePrefix);
}
catch (VersionException e) {
// ignore
@ -130,6 +133,7 @@ abstract class CompositeDBAdapter {
* Upgrades the Composite data type table from the oldAdapter's version to the current version.
* @param handle handle to the database whose table is to be upgraded to a newer version.
* @param oldAdapter the adapter for the existing table to be upgraded.
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return the adapter for the new upgraded version of the table.
* @throws VersionException if the the table's version does not match the expected version
@ -137,14 +141,15 @@ abstract class CompositeDBAdapter {
* @throws IOException if the database can't be read or written.
* @throws CancelledException user cancelled upgrade
*/
static CompositeDBAdapter upgrade(DBHandle handle, CompositeDBAdapter oldAdapter,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
private static CompositeDBAdapter upgrade(DBHandle handle, CompositeDBAdapter oldAdapter,
String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
CompositeDBAdapter tmpAdapter = null;
try {
tmpAdapter = new CompositeDBAdapterV5V6(tmpHandle, DBConstants.CREATE);
tmpAdapter = new CompositeDBAdapterV5V6(tmpHandle, DBConstants.CREATE, tablePrefix);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
@ -152,7 +157,8 @@ abstract class CompositeDBAdapter {
tmpAdapter.updateRecord(rec, false);
}
oldAdapter.deleteTable(handle);
CompositeDBAdapter newAdapter = new CompositeDBAdapterV5V6(handle, DBConstants.CREATE);
CompositeDBAdapter newAdapter =
new CompositeDBAdapterV5V6(handle, DBConstants.CREATE, tablePrefix);
if (oldAdapter.getVersion() < FLEX_ARRAY_ELIMINATION_SCHEMA_VERSION) {
newAdapter.flexArrayMigrationRequired = true;
}
@ -211,7 +217,7 @@ abstract class CompositeDBAdapter {
* @return the composite data type record iterator.
* @throws IOException if the database can't be accessed.
*/
abstract RecordIterator getRecords() throws IOException;
public abstract RecordIterator getRecords() throws IOException;
/**
* Updates the composite data type table with the provided record.
@ -269,6 +275,6 @@ abstract class CompositeDBAdapter {
* Get the number of composite records
* @return total number of composite records
*/
abstract int getRecordCount();
public abstract int getRecordCount();
}

View file

@ -35,11 +35,12 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato
static final int V0_COMPOSITE_LENGTH_COL = 4;
static final int V0_COMPOSITE_NUM_COMPONENTS_COL = 5;
static final Schema V0_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE,
LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE },
new String[] { "Name", "Comment", "Is Union", "Category ID", "Length",
"Number Of Components" });
// DO NOT REMOVE - this documents the schema used in version 0.
// static final Schema V0_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID",
// new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE,
// LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE },
// new String[] { "Name", "Comment", "Is Union", "Category ID", "Length",
// "Number Of Components" });
private Table compositeTable;
@ -49,20 +50,14 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public CompositeDBAdapterV0(DBHandle handle) throws VersionException {
CompositeDBAdapterV0(DBHandle handle) throws VersionException {
compositeTable = handle.getTable(COMPOSITE_TABLE_NAME);
if (compositeTable == null) {
throw new VersionException("Missing Table: " + COMPOSITE_TABLE_NAME);
}
int version = compositeTable.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + COMPOSITE_TABLE_NAME +
" but got " + compositeTable.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
if (compositeTable.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
@ -71,12 +66,12 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato
}
@Override
int getRecordCount() {
public int getRecordCount() {
return compositeTable.getRecordCount();
}
@Override
public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID,
long lastChangeTime, int packValue, int minAlignment) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
@ -84,7 +79,7 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato
}
@Override
public DBRecord getRecord(long dataTypeID) throws IOException {
DBRecord getRecord(long dataTypeID) throws IOException {
return translateRecord(compositeTable.getRecord(dataTypeID));
}
@ -94,18 +89,18 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean removeRecord(long compositeID) throws IOException {
boolean removeRecord(long compositeID) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
" of " + COMPOSITE_TABLE_NAME + " table.");
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return compositeTable.findRecords(new LongField(categoryID),
CompositeDBAdapter.COMPOSITE_CAT_COL);
}

View file

@ -38,6 +38,7 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
static final int V1_COMPOSITE_SOURCE_SYNC_TIME_COL = 8;
static final int V1_COMPOSITE_LAST_CHANGE_TIME_COL = 9;
// DO NOT REMOVE - this documents the schema used in version 1.
// static final Schema V1_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID",
// new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE,
// LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, LongField.INSTANCE,
@ -54,7 +55,7 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public CompositeDBAdapterV1(DBHandle handle) throws VersionException {
CompositeDBAdapterV1(DBHandle handle) throws VersionException {
compositeTable = handle.getTable(COMPOSITE_TABLE_NAME);
if (compositeTable == null) {
@ -62,12 +63,7 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
}
int version = compositeTable.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + COMPOSITE_TABLE_NAME +
" but got " + compositeTable.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}
@ -76,12 +72,12 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
}
@Override
int getRecordCount() {
public int getRecordCount() {
return compositeTable.getRecordCount();
}
@Override
public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID,
long lastChangeTime, int packValue, int minAlignment) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
@ -89,7 +85,7 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
}
@Override
public DBRecord getRecord(long dataTypeID) throws IOException {
DBRecord getRecord(long dataTypeID) throws IOException {
return translateRecord(compositeTable.getRecord(dataTypeID));
}
@ -99,12 +95,12 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean removeRecord(long compositeID) throws IOException {
boolean removeRecord(long compositeID) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
" of " + COMPOSITE_TABLE_NAME + " table.");
}
@ -115,7 +111,7 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return compositeTable.findRecords(new LongField(categoryID),
CompositeDBAdapter.COMPOSITE_CAT_COL);
}
@ -126,9 +122,6 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato
V1_COMPOSITE_SOURCE_ARCHIVE_ID_COL);
}
/* (non-Javadoc)
* @see db.RecordTranslator#translateRecord(db.Record)
*/
@Override
public DBRecord translateRecord(DBRecord oldRec) {
if (oldRec == null) {

View file

@ -51,14 +51,15 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
static final int V2V4_COMPOSITE_PACK_COL = 10; // renamed from Internal Alignment
static final int V2V4_COMPOSITE_MIN_ALIGN_COL = 11; // renamed from External Alignment
static final Schema V2V4_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE,
LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, LongField.INSTANCE,
LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, IntField.INSTANCE,
IntField.INSTANCE },
new String[] { "Name", "Comment", "Is Union", "Category ID", "Length",
"Number Of Components", "Source Archive ID", "Source Data Type ID", "Source Sync Time",
"Last Change Time", "Pack", "MinAlign" });
// DO NOT REMOVE - this documents the schema used in versions 2 thru 4.
// static final Schema V2V4_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID",
// new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE,
// LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, LongField.INSTANCE,
// LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, IntField.INSTANCE,
// IntField.INSTANCE },
// new String[] { "Name", "Comment", "Is Union", "Category ID", "Length",
// "Number Of Components", "Source Archive ID", "Source Data Type ID", "Source Sync Time",
// "Last Change Time", "Pack", "MinAlign" });
private Table compositeTable;
@ -68,7 +69,7 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public CompositeDBAdapterV2V4(DBHandle handle) throws VersionException {
CompositeDBAdapterV2V4(DBHandle handle) throws VersionException {
compositeTable = handle.getTable(COMPOSITE_TABLE_NAME);
if (compositeTable == null) {
throw new VersionException("Missing Table: " + COMPOSITE_TABLE_NAME);
@ -90,12 +91,12 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
}
@Override
int getRecordCount() {
public int getRecordCount() {
return compositeTable.getRecordCount();
}
@Override
public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID,
long lastChangeTime, int packValue, int minAlignment) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
@ -103,7 +104,7 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
}
@Override
public DBRecord getRecord(long dataTypeID) throws IOException {
DBRecord getRecord(long dataTypeID) throws IOException {
return translateRecord(compositeTable.getRecord(dataTypeID));
}
@ -113,12 +114,12 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean removeRecord(long compositeID) throws IOException {
boolean removeRecord(long compositeID) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
" of " + COMPOSITE_TABLE_NAME + " table.");
}
@ -129,7 +130,7 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return compositeTable.findRecords(new LongField(categoryID),
CompositeDBAdapter.COMPOSITE_CAT_COL);
}
@ -140,9 +141,6 @@ class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTransla
V2V4_COMPOSITE_SOURCE_ARCHIVE_ID_COL);
}
/* (non-Javadoc)
* @see db.RecordTranslator#translateRecord(db.Record)
*/
@Override
public DBRecord translateRecord(DBRecord oldRec) {
if (oldRec == null) {

View file

@ -32,6 +32,8 @@ import ghidra.util.exception.VersionException;
* Version 6 did not change the schema but corresponds to the elimination
* of Structure flex-arrays which are supported in read-only mode under
* the older version 5 adapter version.
*
* NOTE: Use of tablePrefix introduced with adapter V6.
*/
class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
@ -66,33 +68,30 @@ class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
/**
* Gets an adapter for the Composite database table.
* @param handle handle to the database containing the table.
* @param openMode
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if IO error occurs
*/
public CompositeDBAdapterV5V6(DBHandle handle, int openMode)
CompositeDBAdapterV5V6(DBHandle handle, int openMode, String tablePrefix)
throws VersionException, IOException {
String tableName = tablePrefix + COMPOSITE_TABLE_NAME;
if (openMode == DBConstants.CREATE) {
compositeTable = handle.createTable(COMPOSITE_TABLE_NAME, V5V6_COMPOSITE_SCHEMA,
compositeTable = handle.createTable(tableName, V5V6_COMPOSITE_SCHEMA,
new int[] { V5V6_COMPOSITE_CAT_COL, V5V6_COMPOSITE_UNIVERSAL_DT_ID_COL });
}
else {
compositeTable = handle.getTable(COMPOSITE_TABLE_NAME);
compositeTable = handle.getTable(tableName);
if (compositeTable == null) {
throw new VersionException("Missing Table: " + COMPOSITE_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
int version = compositeTable.getSchema().getVersion();
if (version == V5_VERSION && openMode == DBConstants.READ_ONLY) {
return; // StructureDB handles read-only flex-array migration
}
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + COMPOSITE_TABLE_NAME +
" but got " + version;
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
if (version == V5_VERSION && openMode == DBConstants.READ_ONLY) {
return; // StructureDB handles read-only flex-array migration
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}
}
@ -102,12 +101,12 @@ class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
}
@Override
int getRecordCount() {
public int getRecordCount() {
return compositeTable.getRecordCount();
}
@Override
public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID,
int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID,
long lastChangeTime, int packValue, int minAlignment) throws IOException {
if (compositeTable.getSchema().getVersion() == V5_VERSION) {
@ -141,7 +140,7 @@ class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
}
@Override
public DBRecord getRecord(long dataTypeID) throws IOException {
DBRecord getRecord(long dataTypeID) throws IOException {
return compositeTable.getRecord(dataTypeID);
}
@ -151,7 +150,7 @@ class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
if (compositeTable.getSchema().getVersion() == V5_VERSION) {
throw new UnsupportedOperationException();
}
@ -163,7 +162,7 @@ class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
}
@Override
public boolean removeRecord(long compositeID) throws IOException {
boolean removeRecord(long compositeID) throws IOException {
if (compositeTable.getSchema().getVersion() == V5_VERSION) {
throw new UnsupportedOperationException();
}
@ -172,11 +171,11 @@ class CompositeDBAdapterV5V6 extends CompositeDBAdapter {
@Override
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(COMPOSITE_TABLE_NAME);
handle.deleteTable(compositeTable.getName());
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return compositeTable.findRecords(new LongField(categoryID),
CompositeDBAdapter.COMPOSITE_CAT_COL);
}

View file

@ -37,6 +37,7 @@ import ghidra.framework.ApplicationConfiguration;
import ghidra.program.model.data.*;
import ghidra.program.model.data.Composite;
import ghidra.program.model.data.Enum;
import ghidra.program.model.data.StandAloneDataTypeManager.ArchiveWarning;
import ghidra.util.*;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.exception.*;
@ -63,8 +64,27 @@ public class DataTypeArchiveTransformer implements GhidraLaunchable {
FileDataTypeManager newFileArchive = null;
try {
monitor.initialize(100);
oldFileArchive = FileDataTypeManager.openFileArchive(oldFile, false);
ArchiveWarning warning = oldFileArchive.getWarning();
if (warning == ArchiveWarning.LANGUAGE_UPGRADE_REQURED) {
throw new IOException("Archive requires language upgrade: " + oldFile);
}
if (warning != ArchiveWarning.NONE) {
throw new IOException("Archive language error occured: " + oldFile,
oldFileArchive.getWarningDetail());
}
newFileArchive = FileDataTypeManager.openFileArchive(newFile, true);
warning = newFileArchive.getWarning();
if (warning == ArchiveWarning.LANGUAGE_UPGRADE_REQURED) {
throw new IOException("Archive requires language upgrade: " + newFile);
}
if (warning != ArchiveWarning.NONE) {
throw new IOException("Archive language error occured: " + newFile,
newFileArchive.getWarningDetail());
}
UniversalID oldUniversalID = oldFileArchive.getUniversalID();
UniversalID newUniversalID = newFileArchive.getUniversalID();
Msg.info(DataTypeArchiveTransformer.class, "Old file ID = " + oldUniversalID);
@ -739,12 +759,10 @@ public class DataTypeArchiveTransformer implements GhidraLaunchable {
FileDataTypeManager destinationFileArchive =
FileDataTypeManager.openFileArchive(destinationFile, false);
if (destinationFileArchive != null) {
UniversalID destinationUniversalID = destinationFileArchive.getUniversalID();
destinationFileArchive.close();
Msg.info(DataTypeArchiveTransformer.class,
"Resulting file ID = " + destinationUniversalID.getValue());
}
UniversalID destinationUniversalID = destinationFileArchive.getUniversalID();
destinationFileArchive.close();
Msg.info(DataTypeArchiveTransformer.class,
"Resulting file ID = " + destinationUniversalID.getValue());
}
static File myOldFile = null;

View file

@ -305,10 +305,10 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
return false;
}
DataType myParent = getParent();
boolean aligned =
boolean isPacked =
(myParent instanceof Composite) ? ((Composite) myParent).isPackingEnabled() : false;
// Components don't need to have matching offset when they are aligned
if ((!aligned && (offset != dtc.getOffset())) ||
// Components don't need to have matching offset when structure has packing enabled
if ((!isPacked && (offset != dtc.getOffset())) ||
!SystemUtilities.isEqual(getFieldName(), dtc.getFieldName()) ||
!SystemUtilities.isEqual(getComment(), dtc.getComment())) {
return false;

View file

@ -518,9 +518,6 @@ abstract class DataTypeDB extends DatabaseObject implements DataType {
@Override
public SourceArchive getSourceArchive() {
if (dataMgr == null) {
return null;
}
return dataMgr.getSourceArchive(getSourceArchiveID());
}

View file

@ -23,6 +23,7 @@ import ghidra.GhidraLaunchable;
import ghidra.framework.Application;
import ghidra.framework.ApplicationConfiguration;
import ghidra.program.model.data.*;
import ghidra.program.model.data.StandAloneDataTypeManager.ArchiveWarning;
import ghidra.util.NumericUtilities;
import ghidra.util.UniversalID;
import ghidra.util.datastruct.LongLongHashtable;
@ -90,6 +91,10 @@ public class DataTypeIDConverter implements GhidraLaunchable {
FileDataTypeManager oldFileArchive = null;
try {
oldFileArchive = FileDataTypeManager.openFileArchive(inFile, false);
if (oldFileArchive.getWarning() != ArchiveWarning.NONE) {
System.out.println("Archive ID Conversion aborted");
return;
}
UniversalID oldFileUID = oldFileArchive.getUniversalID();
long newID = idMap.get(oldFileUID.getValue());

View file

@ -19,6 +19,7 @@ import java.io.IOException;
import db.*;
import ghidra.util.UniversalID;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -45,26 +46,26 @@ abstract class EnumDBAdapter {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of enumeration data types.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task cancelled
*/
static EnumDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
static EnumDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new EnumDBAdapterV1(handle, true);
return new EnumDBAdapterV1(handle, tablePrefix, true);
}
try {
return new EnumDBAdapterV1(handle, false);
return new EnumDBAdapterV1(handle, tablePrefix, false);
}
catch (VersionException e) {
// if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
// throw e;
// }
EnumDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
@ -76,7 +77,7 @@ abstract class EnumDBAdapter {
* @return the read only Enumeration data type table adapter
* @throws VersionException if a read only adapter can't be obtained for the database handle's version.
*/
static EnumDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
private static EnumDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
try {
return new EnumDBAdapterV0(handle);
}
@ -93,28 +94,35 @@ abstract class EnumDBAdapter {
* Upgrades the Enumeration data type table from the oldAdapter's version to the current version.
* @param handle handle to the database whose table is to be upgraded to a newer version.
* @param oldAdapter the adapter for the existing table to be upgraded.
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return the adapter for the new upgraded version of the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if the database can't be read or written.
* @throws CancelledException if task cancelled
*/
static EnumDBAdapter upgrade(DBHandle handle, EnumDBAdapter oldAdapter)
throws VersionException, IOException {
private static EnumDBAdapter upgrade(DBHandle handle, EnumDBAdapter oldAdapter,
String tablePrefix,
TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
EnumDBAdapter tmpAdapter = null;
try {
tmpAdapter = new EnumDBAdapterV1(tmpHandle, true);
tmpAdapter = new EnumDBAdapterV1(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec, false);
}
oldAdapter.deleteTable(handle);
EnumDBAdapterV1 newAdapter = new EnumDBAdapterV1(handle, true);
EnumDBAdapterV1 newAdapter = new EnumDBAdapterV1(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec, false);
}

View file

@ -28,6 +28,7 @@ import ghidra.util.exception.VersionException;
* Version 0 implementation for accessing the Enumeration database table.
*/
class EnumDBAdapterV0 extends EnumDBAdapter implements RecordTranslator {
static final int VERSION = 0;
// Enum Columns
@ -36,10 +37,11 @@ class EnumDBAdapterV0 extends EnumDBAdapter implements RecordTranslator {
static final int V0_ENUM_CAT_COL = 2;
static final int V0_ENUM_SIZE_COL = 3;
static final Schema V0_ENUM_SCHEMA = new Schema(
VERSION, "Enum ID", new Field[] { StringField.INSTANCE, StringField.INSTANCE,
LongField.INSTANCE, ByteField.INSTANCE },
new String[] { "Name", "Comment", "Category ID", "Size" });
// DO NOT REMOVE - this documents the schema used in version 0.
// static final Schema V0_ENUM_SCHEMA = new Schema(
// VERSION, "Enum ID", new Field[] { StringField.INSTANCE, StringField.INSTANCE,
// LongField.INSTANCE, ByteField.INSTANCE },
// new String[] { "Name", "Comment", "Category ID", "Size" });
private Table enumTable;
@ -53,16 +55,11 @@ class EnumDBAdapterV0 extends EnumDBAdapter implements RecordTranslator {
enumTable = handle.getTable(ENUM_TABLE_NAME);
if (enumTable == null) {
throw new VersionException("Missing Table: " + ENUM_TABLE_NAME);
throw new VersionException(true);
}
int version = enumTable.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + ENUM_TABLE_NAME +
" but got " + enumTable.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(false);
}
}

View file

@ -24,6 +24,8 @@ import ghidra.util.exception.VersionException;
/**
* Version 1 implementation for accessing the Enumeration database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class EnumDBAdapterV1 extends EnumDBAdapter {
static final int VERSION = 1;
@ -50,29 +52,27 @@ class EnumDBAdapterV1 extends EnumDBAdapter {
/**
* Gets a version 1 adapter for the Enumeration database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException an IO error occured during table creation
*/
public EnumDBAdapterV1(DBHandle handle, boolean create) throws VersionException, IOException {
public EnumDBAdapterV1(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + ENUM_TABLE_NAME;
if (create) {
enumTable = handle.createTable(ENUM_TABLE_NAME, V1_ENUM_SCHEMA,
enumTable = handle.createTable(tableName, V1_ENUM_SCHEMA,
new int[] { V1_ENUM_CAT_COL, V1_ENUM_UNIVERSAL_DT_ID_COL });
}
else {
enumTable = handle.getTable(ENUM_TABLE_NAME);
enumTable = handle.getTable(tableName);
if (enumTable == null) {
throw new VersionException("Missing Table: " + ENUM_TABLE_NAME);
throw new VersionException(true);
}
int version = enumTable.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + ENUM_TABLE_NAME +
" but got " + enumTable.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}
}
@ -121,7 +121,7 @@ class EnumDBAdapterV1 extends EnumDBAdapter {
@Override
protected void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(ENUM_TABLE_NAME);
handle.deleteTable(enumTable.getName());
}
@Override

View file

@ -24,6 +24,7 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -46,18 +47,20 @@ abstract class EnumValueDBAdapter implements RecordTranslator {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of enumeration data type values.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task is cancelled
*/
static EnumValueDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
static EnumValueDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new EnumValueDBAdapterV1(handle, true);
return new EnumValueDBAdapterV1(handle, tablePrefix, true);
}
try {
return new EnumValueDBAdapterV1(handle, false);
return new EnumValueDBAdapterV1(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -65,13 +68,13 @@ abstract class EnumValueDBAdapter implements RecordTranslator {
}
EnumValueDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
}
static EnumValueDBAdapter findReadOnlyAdapter(DBHandle handle) {
private static EnumValueDBAdapter findReadOnlyAdapter(DBHandle handle) {
try {
return new EnumValueDBAdapterV0(handle);
}
@ -85,28 +88,34 @@ abstract class EnumValueDBAdapter implements RecordTranslator {
* version.
* @param handle handle to the database whose table is to be upgraded to a newer version.
* @param oldAdapter the adapter for the existing table to be upgraded.
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return the adapter for the new upgraded version of the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if the database can't be read or written.
* @throws CancelledException if task is cancelled
*/
static EnumValueDBAdapter upgrade(DBHandle handle, EnumValueDBAdapter oldAdapter)
throws VersionException, IOException {
private static EnumValueDBAdapter upgrade(DBHandle handle, EnumValueDBAdapter oldAdapter,
String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
EnumValueDBAdapter tmpAdapter = null;
try {
tmpAdapter = new EnumValueDBAdapterV1(tmpHandle, true);
tmpAdapter = new EnumValueDBAdapterV1(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec);
}
oldAdapter.deleteTable(handle);
EnumValueDBAdapter newAdapter = new EnumValueDBAdapterV1(handle, true);
EnumValueDBAdapter newAdapter = new EnumValueDBAdapterV1(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec);
}
@ -149,9 +158,7 @@ abstract class EnumValueDBAdapter implements RecordTranslator {
* @param handle the handle used to delete the table
* @throws IOException if there was a problem accessing the database
*/
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(ENUM_VALUE_TABLE_NAME);
}
abstract void deleteTable(DBHandle handle) throws IOException;
/**
* Remove the record for the given enum Value ID.

View file

@ -32,33 +32,33 @@ class EnumValueDBAdapterNoTable extends EnumValueDBAdapter {
* Gets a pre-table version of the adapter for the enumeration data type values database table.
* @param handle handle to the database which doesn't contain the table.
*/
public EnumValueDBAdapterNoTable(DBHandle handle) {
EnumValueDBAdapterNoTable(DBHandle handle) {
// no table needed
}
@Override
public void createRecord(long enumID, String name, long value, String comment)
void createRecord(long enumID, String name, long value, String comment)
throws IOException {
throw new UnsupportedOperationException();
}
@Override
public DBRecord getRecord(long valueID) throws IOException {
DBRecord getRecord(long valueID) throws IOException {
return null;
}
@Override
public void updateRecord(DBRecord record) throws IOException {
void updateRecord(DBRecord record) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void removeRecord(long valueID) throws IOException {
void removeRecord(long valueID) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public Field[] getValueIdsInEnum(long enumID) throws IOException {
Field[] getValueIdsInEnum(long enumID) throws IOException {
return Field.EMPTY_ARRAY;
}

View file

@ -39,7 +39,7 @@ class EnumValueDBAdapterV0 extends EnumValueDBAdapter {
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public EnumValueDBAdapterV0(DBHandle handle) throws VersionException {
EnumValueDBAdapterV0(DBHandle handle) throws VersionException {
table = handle.getTable(ENUM_VALUE_TABLE_NAME);
if (table == null) {
@ -55,31 +55,35 @@ class EnumValueDBAdapterV0 extends EnumValueDBAdapter {
}
@Override
public void createRecord(long enumID, String name, long value, String comment)
void createRecord(long enumID, String name, long value, String comment)
throws IOException {
throw new UnsupportedOperationException("Cannot update Version 0");
}
@Override
public DBRecord getRecord(long valueID) throws IOException {
DBRecord getRecord(long valueID) throws IOException {
return translateRecord(table.getRecord(valueID));
}
@Override
public void removeRecord(long valueID) throws IOException {
void removeRecord(long valueID) throws IOException {
throw new UnsupportedOperationException("Cannot remove Version 0");
}
@Override
public void updateRecord(DBRecord record) throws IOException {
void updateRecord(DBRecord record) throws IOException {
throw new UnsupportedOperationException("Cannot update Version 0");
}
@Override
public Field[] getValueIdsInEnum(long enumID) throws IOException {
Field[] getValueIdsInEnum(long enumID) throws IOException {
return table.findRecords(new LongField(enumID), ENUMVAL_ID_COL);
}
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(ENUM_VALUE_TABLE_NAME);
}
@Override
public DBRecord translateRecord(DBRecord oldRec) {
if (oldRec == null) {

View file

@ -22,6 +22,8 @@ import ghidra.util.exception.VersionException;
/**
* Version 1 implementation for the enumeration tables adapter.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class EnumValueDBAdapterV1 extends EnumValueDBAdapter {
@ -36,36 +38,32 @@ class EnumValueDBAdapterV1 extends EnumValueDBAdapter {
/**
* Gets a version 1 adapter for the Enumeration Data Type Values database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if IO error occurs
*/
public EnumValueDBAdapterV1(DBHandle handle, boolean create)
EnumValueDBAdapterV1(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + ENUM_VALUE_TABLE_NAME;
if (create) {
table = handle.createTable(ENUM_VALUE_TABLE_NAME, SCHEMA, new int[] { ENUMVAL_ID_COL });
table = handle.createTable(tableName, SCHEMA, new int[] { ENUMVAL_ID_COL });
}
else {
table = handle.getTable(ENUM_VALUE_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException(true);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + ENUM_VALUE_TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}
}
@Override
public void createRecord(long enumID, String name, long value, String comment)
void createRecord(long enumID, String name, long value, String comment)
throws IOException {
DBRecord record = SCHEMA.createRecord(table.getKey());
record.setLongValue(ENUMVAL_ID_COL, enumID);
@ -76,22 +74,22 @@ class EnumValueDBAdapterV1 extends EnumValueDBAdapter {
}
@Override
public DBRecord getRecord(long valueID) throws IOException {
DBRecord getRecord(long valueID) throws IOException {
return table.getRecord(valueID);
}
@Override
public void removeRecord(long valueID) throws IOException {
void removeRecord(long valueID) throws IOException {
table.deleteRecord(valueID);
}
@Override
public void updateRecord(DBRecord record) throws IOException {
void updateRecord(DBRecord record) throws IOException {
table.putRecord(record);
}
@Override
public Field[] getValueIdsInEnum(long enumID) throws IOException {
Field[] getValueIdsInEnum(long enumID) throws IOException {
return table.findRecords(new LongField(enumID), ENUMVAL_ID_COL);
}
@ -100,6 +98,10 @@ class EnumValueDBAdapterV1 extends EnumValueDBAdapter {
return table.iterator();
}
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(table.getName());
}
@Override
public DBRecord translateRecord(DBRecord r) {
return r;

View file

@ -24,12 +24,14 @@ import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsImpl;
import ghidra.program.database.DBObjectCache;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionSignature;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.Msg;
import ghidra.util.UniversalID;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.InvalidInputException;
class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
@ -108,13 +110,17 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
try {
checkIsValid();
StringBuffer buf = new StringBuffer();
if (includeCallingConvention && hasNoReturn()) {
buf.append(NORETURN_DISPLAY_STRING);
buf.append(" ");
}
DataType returnType = getReturnType();
buf.append((returnType != null ? returnType.getDisplayName() : "void"));
buf.append(" ");
if (includeCallingConvention) {
GenericCallingConvention genericCallingConvention = getGenericCallingConvention();
if (genericCallingConvention != GenericCallingConvention.unknown) {
buf.append(genericCallingConvention.name());
String callingConvention = getCallingConventionName();
if (!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConvention)) {
buf.append(callingConvention);
buf.append(" ");
}
}
@ -188,7 +194,6 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
lock.acquire();
try {
checkDeleted();
setArguments(functionDefinition.getArguments());
try {
setReturnType(functionDefinition.getReturnType());
@ -197,7 +202,16 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
setReturnType(DEFAULT);
}
setVarArgs(functionDefinition.hasVarArgs());
setGenericCallingConvention(functionDefinition.getGenericCallingConvention());
setNoReturn(functionDefinition.hasNoReturn());
try {
setCallingConvention(functionDefinition.getCallingConventionName(), false);
}
catch (InvalidInputException e) {
// will not happen
}
}
catch (IOException e) {
dataMgr.dbError(e);
}
finally {
lock.release();
@ -394,8 +408,9 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
(comment != null && comment.equals(myComment))) &&
(DataTypeUtilities.isSameOrEquivalentDataType(getReturnType(),
signature.getReturnType())) &&
(getGenericCallingConvention() == signature.getGenericCallingConvention()) &&
(hasVarArgs() == signature.hasVarArgs())) {
getCallingConventionName().equals(signature.getCallingConventionName()) &&
(hasVarArgs() == signature.hasVarArgs()) &&
(hasNoReturn() == signature.hasNoReturn())) {
ParameterDefinition[] args = signature.getArguments();
ParameterDefinition[] thisArgs = this.getArguments();
if (args.length == thisArgs.length) {
@ -517,6 +532,22 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
}
}
@Override
public boolean hasNoReturn() {
lock.acquire();
try {
checkIsValid();
if (record == null) {
return false;
}
byte flags = record.getByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_FLAGS_COL);
return ((flags & FunctionDefinitionDBAdapter.FUNCTION_DEF_NORETURN_FLAG) != 0);
}
finally {
lock.release();
}
}
@Override
public void setVarArgs(boolean hasVarArgs) {
lock.acquire();
@ -544,20 +575,17 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
}
@Override
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention) {
public void setNoReturn(boolean hasNoReturn) {
lock.acquire();
try {
checkDeleted();
int ordinal = genericCallingConvention.ordinal();
if (ordinal < 0 ||
ordinal > FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_MASK) {
Msg.error(this, "GenericCallingConvention ordinal unsupported: " + ordinal);
return;
}
byte flags = record.getByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_FLAGS_COL);
flags &=
~(FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_MASK << FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_SHIFT);
flags |= ordinal << FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_SHIFT;
if (hasNoReturn) {
flags |= FunctionDefinitionDBAdapter.FUNCTION_DEF_NORETURN_FLAG;
}
else {
flags &= ~FunctionDefinitionDBAdapter.FUNCTION_DEF_NORETURN_FLAG;
}
record.setByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_FLAGS_COL, flags);
try {
funDefAdapter.updateRecord(record, true);
@ -573,18 +601,70 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
}
@Override
public GenericCallingConvention getGenericCallingConvention() {
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention) {
lock.acquire();
try {
checkDeleted();
setCallingConvention(genericCallingConvention.name(), false);
}
catch (IOException e) {
dataMgr.dbError(e);
}
catch (InvalidInputException e) {
throw new AssertException(e);
}
finally {
lock.release();
}
}
@Override
public void setCallingConvention(String conventionName) throws InvalidInputException {
lock.acquire();
try {
checkDeleted();
setCallingConvention(conventionName, true);
}
catch (IOException e) {
dataMgr.dbError(e);
}
finally {
lock.release();
}
}
private void setCallingConvention(String conventionName, boolean restrictive)
throws InvalidInputException, IOException {
byte id = dataMgr.getCallingConventionID(conventionName, restrictive);
record.setByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_CALLCONV_COL, id);
funDefAdapter.updateRecord(record, true);
dataMgr.dataTypeChanged(this, false);
}
@Override
public PrototypeModel getCallingConvention() {
ProgramArchitecture arch = dataMgr.getProgramArchitecture();
if (arch == null) {
return null;
}
String callingConvention = getCallingConventionName();
CompilerSpec compilerSpec = arch.getCompilerSpec();
return compilerSpec.getCallingConvention(callingConvention);
}
@Override
public String getCallingConventionName() {
lock.acquire();
try {
checkIsValid();
if (record == null) {
return GenericCallingConvention.unknown;
return Function.UNKNOWN_CALLING_CONVENTION_STRING;
}
byte flags = record.getByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_FLAGS_COL);
int ordinal =
(flags >> FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_SHIFT) &
FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_MASK;
return GenericCallingConvention.get(ordinal);
byte id = record.getByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_CALLCONV_COL);
if (funDefAdapter.usesGenericCallingConventionId()) {
return FunctionDefinitionDBAdapter.getGenericCallingConventionName(id);
}
return dataMgr.getCallingConventionName(id);
}
finally {
lock.release();

View file

@ -18,68 +18,81 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.program.database.util.DBRecordAdapter;
import ghidra.program.model.data.GenericCallingConvention;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.util.UniversalID;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
* Adapter to access the Function Signature Definition database table.
*/
abstract class FunctionDefinitionDBAdapter {
abstract class FunctionDefinitionDBAdapter implements DBRecordAdapter {
static final String FUNCTION_DEF_TABLE_NAME = "Function Definitions";
static final Schema FUN_DEF_SCHEMA = FunctionDefinitionDBAdapterV1.V1_FUN_DEF_SCHEMA;
static final Schema FUN_DEF_SCHEMA = FunctionDefinitionDBAdapterV2.V2_FUN_DEF_SCHEMA;
static final int FUNCTION_DEF_NAME_COL = FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_NAME_COL;
static final int FUNCTION_DEF_NAME_COL = FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_NAME_COL;
static final int FUNCTION_DEF_COMMENT_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_COMMENT_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_COMMENT_COL;
static final int FUNCTION_DEF_CAT_ID_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_CAT_ID_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_CAT_ID_COL;
static final int FUNCTION_DEF_RETURN_ID_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_RETURN_ID_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_RETURN_ID_COL;
static final int FUNCTION_DEF_FLAGS_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_FLAGS_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_FLAGS_COL;
static final int FUNCTION_DEF_CALLCONV_COL =
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_CALLCONV_COL;
static final int FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL;
static final int FUNCTION_DEF_SOURCE_DT_ID_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_UNIVERSAL_DT_ID_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_UNIVERSAL_DT_ID_COL;
static final int FUNCTION_DEF_SOURCE_SYNC_TIME_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_SOURCE_SYNC_TIME_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_SOURCE_SYNC_TIME_COL;
static final int FUNCTION_DEF_LAST_CHANGE_TIME_COL =
FunctionDefinitionDBAdapterV1.V1_FUNCTION_DEF_LAST_CHANGE_TIME_COL;
FunctionDefinitionDBAdapterV2.V2_FUNCTION_DEF_LAST_CHANGE_TIME_COL;
static final byte FUNCTION_DEF_VARARG_FLAG = (byte) 0x1; // Bit 0 is flag for "has vararg".
// Flags Bits 1..4 used for generic calling convention ID
static final int GENERIC_CALLING_CONVENTION_FLAG_MASK = 0xf;
static final int GENERIC_CALLING_CONVENTION_FLAG_SHIFT = 1;
static final byte FUNCTION_DEF_NORETURN_FLAG = (byte) 0x2; // Bit 1 is flag for "has noreturn" (added with V2).
/**
* Gets an adapter for working with the function definition data type database table. The adapter is based
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param callConvAdapter calling convention table adapter suitable to add new conventions
* (e.g., this adapter being used during upgrade operation). Only used when openMode is
* {@link DBConstants#UPGRADE} when adding new calling conventions must be permitted.
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of function definition data types.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task is cancelled
*/
static FunctionDefinitionDBAdapter getAdapter(DBHandle handle, int openMode,
TaskMonitor monitor) throws VersionException, IOException {
String tablePrefix, CallingConventionDBAdapter callConvAdapter, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new FunctionDefinitionDBAdapterV1(handle, true);
return new FunctionDefinitionDBAdapterV2(handle, tablePrefix, true);
}
try {
return new FunctionDefinitionDBAdapterV1(handle, false);
return new FunctionDefinitionDBAdapterV2(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
throw e;
}
FunctionDefinitionDBAdapter adapter = findReadOnlyAdapter(handle);
FunctionDefinitionDBAdapter adapter;
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = findReadOnlyAdapter(handle, tablePrefix, callConvAdapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
else {
adapter = findReadOnlyAdapter(handle, tablePrefix, null);
}
return adapter;
}
@ -88,18 +101,27 @@ abstract class FunctionDefinitionDBAdapter {
/**
* Tries to get a read only adapter for the database whose handle is passed to this method.
* @param handle handle to prior version of the database.
* @param tablePrefix prefix to be used with default table name
* @param callConvAdapter calling convention table adapter suitable to add new conventions
* (e.g., this adapter being used during upgrade operation). Should be null if not performing
* an upgrade.
* @return the read only Function Definition data type table adapter
* @throws VersionException if a read only adapter can't be obtained for the database handle's version.
*/
static FunctionDefinitionDBAdapter findReadOnlyAdapter(DBHandle handle)
private static FunctionDefinitionDBAdapter findReadOnlyAdapter(DBHandle handle,
String tablePrefix, CallingConventionDBAdapter callConvAdapter)
throws VersionException {
try {
return new FunctionDefinitionDBAdapterV1(handle, tablePrefix, callConvAdapter);
}
catch (VersionException e) {
// ignore
}
try {
return new FunctionDefinitionDBAdapterV0(handle);
}
catch (VersionException e) {
if (!e.isUpgradable()) {
throw e;
}
// ignore
}
return new FunctionDefinitionDBAdapterNoTable(handle);
@ -109,29 +131,35 @@ abstract class FunctionDefinitionDBAdapter {
* Upgrades the Function Definition data type table from the oldAdapter's version to the current version.
* @param handle handle to the database whose table is to be upgraded to a newer version.
* @param oldAdapter the adapter for the existing table to be upgraded.
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return the adapter for the new upgraded version of the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if the database can't be read or written.
* @throws CancelledException if task is cancelled
*/
static FunctionDefinitionDBAdapter upgrade(DBHandle handle,
FunctionDefinitionDBAdapter oldAdapter) throws VersionException, IOException {
private static FunctionDefinitionDBAdapter upgrade(DBHandle handle,
FunctionDefinitionDBAdapter oldAdapter, String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
FunctionDefinitionDBAdapter tmpAdapter = null;
try {
tmpAdapter = new FunctionDefinitionDBAdapterV1(tmpHandle, true);
tmpAdapter = new FunctionDefinitionDBAdapterV2(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec, false);
}
oldAdapter.deleteTable(handle);
FunctionDefinitionDBAdapterV1 newAdapter =
new FunctionDefinitionDBAdapterV1(handle, true);
FunctionDefinitionDBAdapter newAdapter =
new FunctionDefinitionDBAdapterV2(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec, false);
}
@ -150,7 +178,8 @@ abstract class FunctionDefinitionDBAdapter {
* @param categoryID the ID for the category that contains this data type.
* @param returnDtID the ID of the data type that is returned by this function definition.
* @param hasVarArgs true if this function definition has a variable length argument list.
* @param genericCallingConvention generic calling convention
* @param hasNoReturn true if this function definition has noreturn enabled
* @param callingConventionID calling convention ID
* @param sourceArchiveID the ID for the source archive where this data type originated.
* @param sourceDataTypeID the ID of the associated data type in the source archive.
* @param lastChangeTime the time this data type was last changed.
@ -158,8 +187,8 @@ abstract class FunctionDefinitionDBAdapter {
* @throws IOException if the database can't be accessed.
*/
abstract DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasVarArgs, GenericCallingConvention genericCallingConvention,
long sourceArchiveID, long sourceDataTypeID, long lastChangeTime) throws IOException;
boolean hasNoReturn, boolean hasVarArgs, byte callingConventionID, long sourceArchiveID,
long sourceDataTypeID, long lastChangeTime) throws IOException;
/**
* Gets a function signature definition data type record from the database based on its ID.
@ -174,7 +203,7 @@ abstract class FunctionDefinitionDBAdapter {
* @return the function definition data type record iterator.
* @throws IOException if the database can't be accessed.
*/
abstract RecordIterator getRecords() throws IOException;
public abstract RecordIterator getRecords() throws IOException;
/**
* Removes the function definition data type record with the specified ID.
@ -227,4 +256,27 @@ abstract class FunctionDefinitionDBAdapter {
abstract DBRecord getRecordWithIDs(UniversalID sourceID, UniversalID datatypeID)
throws IOException;
/**
* Determine if the calling convention ID within record reflects a Generic Calling Convention
* ordinal (i.e., true if V1 adapter in use for read-only mode).
* See {@link #getGenericCallingConventionName(int)} for Generic Calling Convention name lookup.
* @return true if calling convention ID within record reflects a Generic Calling Convention
* ordinal.
*/
boolean usesGenericCallingConventionId() {
return false;
}
/**
* Get old GenericCallingConvention name for specified ordinal value.
* @param ordinal old GenericCallingConvention ordinal
* @return old GenericCallingConvention name
*/
static String getGenericCallingConventionName(int ordinal) {
GenericCallingConvention genericCallingConvention = GenericCallingConvention.get(ordinal);
return genericCallingConvention != GenericCallingConvention.unknown
? genericCallingConvention.getDeclarationName()
: CompilerSpec.CALLING_CONVENTION_unknown;
}
}

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import db.*;
import ghidra.program.database.util.EmptyRecordIterator;
import ghidra.program.model.data.GenericCallingConvention;
import ghidra.util.UniversalID;
/**
@ -37,15 +36,19 @@ class FunctionDefinitionDBAdapterNoTable extends FunctionDefinitionDBAdapter {
}
@Override
public DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasVarArgs, GenericCallingConvention genericCallingConvention,
long sourceArchiveID, long sourceDataTypeID, long lastChangeTime) throws IOException {
throw new UnsupportedOperationException(
"Not allowed to update version prior to existence of Function Definition Data Types table.");
DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasNoReturn, boolean hasVarArgs, byte callingConventionID, long sourceArchiveID,
long sourceDataTypeID, long lastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public DBRecord getRecord(long functionDefID) throws IOException {
public int getRecordCount() {
return 0;
}
@Override
DBRecord getRecord(long functionDefID) throws IOException {
return null;
}
@ -55,22 +58,22 @@ class FunctionDefinitionDBAdapterNoTable extends FunctionDefinitionDBAdapter {
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean removeRecord(long functionDefID) throws IOException {
boolean removeRecord(long functionDefID) throws IOException {
return false;
}
@Override
protected void deleteTable(DBHandle handle) {
void deleteTable(DBHandle handle) {
// do nothing
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return Field.EMPTY_ARRAY;
}

View file

@ -18,7 +18,8 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.util.UniversalID;
import ghidra.util.UniversalIdGenerator;
import ghidra.util.exception.VersionException;
@ -28,12 +29,15 @@ import ghidra.util.exception.VersionException;
*/
class FunctionDefinitionDBAdapterV0 extends FunctionDefinitionDBAdapter
implements RecordTranslator {
static final int VERSION = 0;
static final int V0_FUNCTION_DEF_NAME_COL = 0;
static final int V0_FUNCTION_DEF_COMMENT_COL = 1;
static final int V0_FUNCTION_DEF_CAT_ID_COL = 2;
static final int V0_FUNCTION_DEF_RETURN_ID_COL = 3;
static final int V0_FUNCTION_DEF_FLAGS_COL = 4;
// DO NOT REMOVE WHAT'S BELOW - this documents the schema used in version 0.
// static final Schema V0_FUN_DEF_SCHEMA = new Schema(VERSION, "Data Type ID",
// new Class[] {StringField.class, StringField.class,
@ -51,33 +55,31 @@ class FunctionDefinitionDBAdapterV0 extends FunctionDefinitionDBAdapter
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public FunctionDefinitionDBAdapterV0(DBHandle handle) throws VersionException {
FunctionDefinitionDBAdapterV0(DBHandle handle) throws VersionException {
table = handle.getTable(FUNCTION_DEF_TABLE_NAME);
if (table == null) {
throw new VersionException("Missing Table: " + FUNCTION_DEF_TABLE_NAME);
throw new VersionException(true);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + FUNCTION_DEF_TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
@Override
public DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasVarArgs, GenericCallingConvention genericCallingConvention,
long sourceArchiveID, long sourceDataTypeID, long lastChangeTime) throws IOException {
throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION +
" of " + FUNCTION_DEF_TABLE_NAME + " table.");
public int getRecordCount() {
return table.getRecordCount();
}
@Override
public DBRecord getRecord(long functionDefID) throws IOException {
DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasNoReturn, boolean hasVarArgs, byte callingConventionID, long sourceArchiveID,
long sourceDataTypeID, long lastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
DBRecord getRecord(long functionDefID) throws IOException {
return translateRecord(table.getRecord(functionDefID));
}
@ -87,22 +89,22 @@ class FunctionDefinitionDBAdapterV0 extends FunctionDefinitionDBAdapter
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean removeRecord(long functionDefID) throws IOException {
return table.deleteRecord(functionDefID);
boolean removeRecord(long functionDefID) throws IOException {
throw new UnsupportedOperationException();
}
@Override
protected void deleteTable(DBHandle handle) throws IOException {
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(FUNCTION_DEF_TABLE_NAME);
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return table.findRecords(new LongField(categoryID), V0_FUNCTION_DEF_CAT_ID_COL);
}
@ -111,6 +113,11 @@ class FunctionDefinitionDBAdapterV0 extends FunctionDefinitionDBAdapter
return Field.EMPTY_ARRAY;
}
@Override
DBRecord getRecordWithIDs(UniversalID sourceID, UniversalID datatypeID) throws IOException {
return null;
}
@Override
public DBRecord translateRecord(DBRecord oldRec) {
if (oldRec == null) {
@ -123,6 +130,8 @@ class FunctionDefinitionDBAdapterV0 extends FunctionDefinitionDBAdapter
rec.setLongValue(FUNCTION_DEF_RETURN_ID_COL,
oldRec.getLongValue(V0_FUNCTION_DEF_RETURN_ID_COL));
rec.setByteValue(FUNCTION_DEF_FLAGS_COL, oldRec.getByteValue(V0_FUNCTION_DEF_FLAGS_COL));
rec.setByteValue(FUNCTION_DEF_CALLCONV_COL,
DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID);
rec.setLongValue(FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL, DataTypeManager.LOCAL_ARCHIVE_KEY);
rec.setLongValue(FUNCTION_DEF_SOURCE_DT_ID_COL, UniversalIdGenerator.nextID().getValue());
rec.setLongValue(FUNCTION_DEF_SOURCE_SYNC_TIME_COL, DataType.NO_SOURCE_SYNC_TIME);
@ -130,9 +139,4 @@ class FunctionDefinitionDBAdapterV0 extends FunctionDefinitionDBAdapter
return rec;
}
@Override
DBRecord getRecordWithIDs(UniversalID sourceID, UniversalID datatypeID) throws IOException {
return null;
}
}

View file

@ -16,19 +16,24 @@
package ghidra.program.database.data;
import java.io.IOException;
import java.util.Date;
import db.*;
import ghidra.program.model.data.GenericCallingConvention;
import ghidra.util.Msg;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.util.UniversalID;
import ghidra.util.UniversalIdGenerator;
import ghidra.util.exception.VersionException;
/**
* Version 1 implementation for accessing the Function Signature Definition database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class FunctionDefinitionDBAdapterV1 extends FunctionDefinitionDBAdapter {
class FunctionDefinitionDBAdapterV1 extends FunctionDefinitionDBAdapter
implements RecordTranslator {
static final int VERSION = 1;
static final int V1_FUNCTION_DEF_NAME_COL = 0;
static final int V1_FUNCTION_DEF_COMMENT_COL = 1;
static final int V1_FUNCTION_DEF_CAT_ID_COL = 2;
@ -38,116 +43,91 @@ class FunctionDefinitionDBAdapterV1 extends FunctionDefinitionDBAdapter {
static final int V1_FUNCTION_DEF_UNIVERSAL_DT_ID_COL = 6;
static final int V1_FUNCTION_DEF_SOURCE_SYNC_TIME_COL = 7;
static final int V1_FUNCTION_DEF_LAST_CHANGE_TIME_COL = 8;
static final Schema V1_FUN_DEF_SCHEMA = new Schema(VERSION, "Data Type ID",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, LongField.INSTANCE,
LongField.INSTANCE, ByteField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE,
LongField.INSTANCE, LongField.INSTANCE },
new String[] { "Name", "Comment", "Category ID", "Return Type ID", "Flags",
"Source Archive ID", "Source Data Type ID", "Source Sync Time", "Last Change Time" });
// DO NOT REMOVE WHAT'S BELOW - this documents the schema used in version 0.
// static final Schema V1_FUN_DEF_SCHEMA = new Schema(VERSION, "Data Type ID",
// new Field[] { StringField.INSTANCE, StringField.INSTANCE, LongField.INSTANCE,
// LongField.INSTANCE, ByteField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE,
// LongField.INSTANCE, LongField.INSTANCE },
// new String[] { "Name", "Comment", "Category ID", "Return Type ID", "Flags",
// "Source Archive ID", "Source Data Type ID", "Source Sync Time", "Last Change Time" });
// Flags Bits 1..4 used for generic calling convention ID
private static final int GENERIC_CALLING_CONVENTION_FLAG_MASK = 0xf;
private static final int GENERIC_CALLING_CONVENTION_FLAG_SHIFT = 1;
private Table table;
private CallingConventionDBAdapter callConvAdapter; // must be null if not performing upgrade
/**
* Gets a version 1 adapter for the Function Definition database table.
* Gets a version 1 read-only adapter for the Function Definition database table.
* @param handle handle to the database containing the table.
* @param create true if this constructor should create the table.
* @param tablePrefix prefix to be used with default table name
* @param callConvAdapter calling convention table adapter suitable to add new conventions
* (e.g., this adapter being used during upgrade operation). Should be null if not performing
* an upgrade in which case calling convention IDs will reflect generic convention ordinals.
*
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
*/
public FunctionDefinitionDBAdapterV1(DBHandle handle, boolean create)
throws VersionException, IOException {
if (create) {
table = handle.createTable(FUNCTION_DEF_TABLE_NAME, V1_FUN_DEF_SCHEMA,
new int[] { V1_FUNCTION_DEF_CAT_ID_COL, V1_FUNCTION_DEF_UNIVERSAL_DT_ID_COL });
public FunctionDefinitionDBAdapterV1(DBHandle handle, String tablePrefix,
CallingConventionDBAdapter callConvAdapter) throws VersionException {
this.callConvAdapter = callConvAdapter;
String tableName = tablePrefix + FUNCTION_DEF_TABLE_NAME;
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException(true);
}
else {
table = handle.getTable(FUNCTION_DEF_TABLE_NAME);
if (table == null) {
throw new VersionException("Missing Table: " + FUNCTION_DEF_TABLE_NAME);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " +
FUNCTION_DEF_TABLE_NAME + " but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
throw new VersionException(version < VERSION);
}
}
@Override
public DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasVarArgs, GenericCallingConvention genericCallingConvention,
long sourceArchiveID, long sourceDataTypeID, long lastChangeTime) throws IOException {
byte flags = (byte) 0;
if (hasVarArgs) {
flags |= FunctionDefinitionDBAdapter.FUNCTION_DEF_VARARG_FLAG;
}
if (genericCallingConvention != null) {
int ordinal = genericCallingConvention.ordinal();
if (ordinal < 0 ||
ordinal > FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_MASK) {
Msg.error(this, "GenericCallingConvention ordinal unsupported: " + ordinal);
}
else {
flags |=
ordinal << FunctionDefinitionDBAdapter.GENERIC_CALLING_CONVENTION_FLAG_SHIFT;
}
}
long tableKey = table.getKey();
// if (tableKey <= DataManager.VOID_DATATYPE_ID) {
// tableKey = DataManager.VOID_DATATYPE_ID +1;
// }
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.FUNCTION_DEF, tableKey);
DBRecord record = V1_FUN_DEF_SCHEMA.createRecord(key);
record.setString(V1_FUNCTION_DEF_NAME_COL, name);
record.setString(V1_FUNCTION_DEF_COMMENT_COL, comments);
record.setLongValue(V1_FUNCTION_DEF_CAT_ID_COL, categoryID);
record.setLongValue(V1_FUNCTION_DEF_RETURN_ID_COL, returnDtID);
record.setByteValue(V1_FUNCTION_DEF_FLAGS_COL, flags);
record.setLongValue(V1_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL, sourceArchiveID);
record.setLongValue(V1_FUNCTION_DEF_UNIVERSAL_DT_ID_COL, sourceDataTypeID);
record.setLongValue(V1_FUNCTION_DEF_SOURCE_SYNC_TIME_COL, lastChangeTime);
record.setLongValue(V1_FUNCTION_DEF_LAST_CHANGE_TIME_COL, lastChangeTime);
table.putRecord(record);
return record;
boolean usesGenericCallingConventionId() {
return callConvAdapter == null;
}
@Override
public DBRecord getRecord(long functionDefID) throws IOException {
return table.getRecord(functionDefID);
public int getRecordCount() {
return table.getRecordCount();
}
@Override
public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
if (setLastChangeTime) {
record.setLongValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_LAST_CHANGE_TIME_COL,
(new Date()).getTime());
}
table.putRecord(record);
DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasNoReturn, boolean hasVarArgs, byte callingConventionID, long sourceArchiveID,
long sourceDataTypeID, long lastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
DBRecord getRecord(long functionDefID) throws IOException {
return translateRecord(table.getRecord(functionDefID));
}
@Override
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public RecordIterator getRecords() throws IOException {
return table.iterator();
return new TranslatedRecordIterator(table.iterator(), this);
}
@Override
public boolean removeRecord(long functionDefID) throws IOException {
return table.deleteRecord(functionDefID);
boolean removeRecord(long functionDefID) throws IOException {
throw new UnsupportedOperationException();
}
@Override
protected void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(FUNCTION_DEF_TABLE_NAME);
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(table.getName());
}
@Override
public Field[] getRecordIdsInCategory(long categoryID) throws IOException {
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return table.findRecords(new LongField(categoryID), V1_FUNCTION_DEF_CAT_ID_COL);
}
@ -169,4 +149,48 @@ class FunctionDefinitionDBAdapterV1 extends FunctionDefinitionDBAdapter {
}
return null;
}
@Override
public DBRecord translateRecord(DBRecord oldRec) {
if (oldRec == null) {
return null;
}
DBRecord rec = FunctionDefinitionDBAdapter.FUN_DEF_SCHEMA.createRecord(oldRec.getKey());
rec.setString(FUNCTION_DEF_NAME_COL, oldRec.getString(V1_FUNCTION_DEF_NAME_COL));
rec.setString(FUNCTION_DEF_COMMENT_COL, oldRec.getString(V1_FUNCTION_DEF_COMMENT_COL));
rec.setLongValue(FUNCTION_DEF_CAT_ID_COL, oldRec.getLongValue(V1_FUNCTION_DEF_CAT_ID_COL));
rec.setLongValue(FUNCTION_DEF_RETURN_ID_COL, oldRec.getLongValue(V1_FUNCTION_DEF_RETURN_ID_COL));
byte flags = oldRec.getByteValue(V1_FUNCTION_DEF_FLAGS_COL);
int mask = GENERIC_CALLING_CONVENTION_FLAG_MASK << GENERIC_CALLING_CONVENTION_FLAG_SHIFT;
int genericCallConvId = (flags & mask) >> GENERIC_CALLING_CONVENTION_FLAG_SHIFT;
flags &= (byte) (~mask); // clear old flag bits used for calling convention
byte callingConventionId = DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID;
try {
if (callConvAdapter == null) {
// Must use old generic calling convention ordinal as ID
callingConventionId = (byte) genericCallConvId;
}
else {
// It is expected that an open transaction exists during upgrade use
// and that all records are upgraded prior to general use
String callingConvention = getGenericCallingConventionName(genericCallConvId);
callingConventionId = callConvAdapter.getCallingConventionId(callingConvention,
cc -> {
/* ignore */ });
}
}
catch (IOException e) {
// ignore - use unknown convention ID
}
rec.setByteValue(FUNCTION_DEF_FLAGS_COL, flags);
rec.setByteValue(FUNCTION_DEF_CALLCONV_COL, callingConventionId);
rec.setLongValue(FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL, DataTypeManager.LOCAL_ARCHIVE_KEY);
rec.setLongValue(FUNCTION_DEF_SOURCE_DT_ID_COL, UniversalIdGenerator.nextID().getValue());
rec.setLongValue(FUNCTION_DEF_SOURCE_SYNC_TIME_COL, DataType.NO_SOURCE_SYNC_TIME);
rec.setLongValue(FUNCTION_DEF_LAST_CHANGE_TIME_COL, DataType.NO_LAST_CHANGE_TIME);
return rec;
}
}

View file

@ -0,0 +1,164 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.data;
import java.io.IOException;
import java.util.Date;
import db.*;
import ghidra.util.UniversalID;
import ghidra.util.exception.VersionException;
/**
* Version 2 implementation for accessing the Function Signature Definition database table.
*/
class FunctionDefinitionDBAdapterV2 extends FunctionDefinitionDBAdapter {
static final int VERSION = 2;
static final int V2_FUNCTION_DEF_NAME_COL = 0;
static final int V2_FUNCTION_DEF_COMMENT_COL = 1;
static final int V2_FUNCTION_DEF_CAT_ID_COL = 2;
static final int V2_FUNCTION_DEF_RETURN_ID_COL = 3;
static final int V2_FUNCTION_DEF_FLAGS_COL = 4;
static final int V2_FUNCTION_DEF_CALLCONV_COL = 5;
static final int V2_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL = 6;
static final int V2_FUNCTION_DEF_UNIVERSAL_DT_ID_COL = 7;
static final int V2_FUNCTION_DEF_SOURCE_SYNC_TIME_COL = 8;
static final int V2_FUNCTION_DEF_LAST_CHANGE_TIME_COL = 9;
static final Schema V2_FUN_DEF_SCHEMA = new Schema(VERSION, "Data Type ID",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, LongField.INSTANCE,
LongField.INSTANCE, ByteField.INSTANCE, ByteField.INSTANCE, LongField.INSTANCE,
LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE },
new String[] { "Name", "Comment", "Category ID", "Return Type ID", "Flags", "Call Conv ID",
"Source Archive ID", "Source Data Type ID", "Source Sync Time", "Last Change Time" });
private Table table;
/**
* Gets a version 2 adapter for the Function Definition database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO error occurs
*/
public FunctionDefinitionDBAdapterV2(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + FUNCTION_DEF_TABLE_NAME;
if (create) {
table = handle.createTable(tableName, V2_FUN_DEF_SCHEMA,
new int[] { V2_FUNCTION_DEF_CAT_ID_COL, V2_FUNCTION_DEF_UNIVERSAL_DT_ID_COL });
}
else {
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException(true);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
throw new VersionException(version < VERSION);
}
}
}
@Override
public int getRecordCount() {
return table.getRecordCount();
}
@Override
DBRecord createRecord(String name, String comments, long categoryID, long returnDtID,
boolean hasNoReturn, boolean hasVarArgs, byte callingConventionID, long sourceArchiveID,
long sourceDataTypeID, long lastChangeTime) throws IOException {
byte flags = (byte) 0;
if (hasVarArgs) {
flags |= FUNCTION_DEF_VARARG_FLAG;
}
if (hasNoReturn) {
flags |= FUNCTION_DEF_NORETURN_FLAG;
}
long tableKey = table.getKey();
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.FUNCTION_DEF, tableKey);
DBRecord record = V2_FUN_DEF_SCHEMA.createRecord(key);
record.setString(V2_FUNCTION_DEF_NAME_COL, name);
record.setString(V2_FUNCTION_DEF_COMMENT_COL, comments);
record.setLongValue(V2_FUNCTION_DEF_CAT_ID_COL, categoryID);
record.setLongValue(V2_FUNCTION_DEF_RETURN_ID_COL, returnDtID);
record.setByteValue(V2_FUNCTION_DEF_FLAGS_COL, flags);
record.setByteValue(V2_FUNCTION_DEF_CALLCONV_COL, callingConventionID);
record.setLongValue(V2_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL, sourceArchiveID);
record.setLongValue(V2_FUNCTION_DEF_UNIVERSAL_DT_ID_COL, sourceDataTypeID);
record.setLongValue(V2_FUNCTION_DEF_SOURCE_SYNC_TIME_COL, lastChangeTime);
record.setLongValue(V2_FUNCTION_DEF_LAST_CHANGE_TIME_COL, lastChangeTime);
table.putRecord(record);
return record;
}
@Override
DBRecord getRecord(long functionDefID) throws IOException {
return table.getRecord(functionDefID);
}
@Override
void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException {
if (setLastChangeTime) {
record.setLongValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_LAST_CHANGE_TIME_COL,
(new Date()).getTime());
}
table.putRecord(record);
}
@Override
public RecordIterator getRecords() throws IOException {
return table.iterator();
}
@Override
boolean removeRecord(long functionDefID) throws IOException {
return table.deleteRecord(functionDefID);
}
@Override
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(table.getName());
}
@Override
Field[] getRecordIdsInCategory(long categoryID) throws IOException {
return table.findRecords(new LongField(categoryID), V2_FUNCTION_DEF_CAT_ID_COL);
}
@Override
Field[] getRecordIdsForSourceArchive(long archiveID) throws IOException {
return table.findRecords(new LongField(archiveID), V2_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL);
}
@Override
DBRecord getRecordWithIDs(UniversalID sourceID, UniversalID datatypeID) throws IOException {
Field[] keys = table.findRecords(new LongField(datatypeID.getValue()),
V2_FUNCTION_DEF_UNIVERSAL_DT_ID_COL);
for (int i = 0; i < keys.length; i++) {
DBRecord record = table.getRecord(keys[i]);
if (record.getLongValue(V2_FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL) == sourceID.getValue()) {
return record;
}
}
return null;
}
}

View file

@ -18,6 +18,7 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -39,22 +40,24 @@ abstract class FunctionParameterAdapter {
FunctionParameterAdapterV1.V1_PARAMETER_DT_LENGTH_COL;
/**
* Gets an adapter for working with the function definition parameters database table. The adapter is based
* on the version of the database associated with the specified database handle and the openMode.
* Gets an adapter for working with the function definition parameters database table.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of function definition parameters.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task is cancelled
*/
static FunctionParameterAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
static FunctionParameterAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new FunctionParameterAdapterV1(handle, true);
return new FunctionParameterAdapterV1(handle, tablePrefix, true);
}
try {
return new FunctionParameterAdapterV1(handle, false);
return new FunctionParameterAdapterV1(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -62,7 +65,7 @@ abstract class FunctionParameterAdapter {
}
FunctionParameterAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
@ -74,7 +77,8 @@ abstract class FunctionParameterAdapter {
* @return the read only Function Definition Parameters table adapter
* @throws VersionException if a read only adapter can't be obtained for the database handle's version.
*/
static FunctionParameterAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
private static FunctionParameterAdapter findReadOnlyAdapter(DBHandle handle)
throws VersionException {
try {
return new FunctionParameterAdapterV0(handle);
}
@ -91,28 +95,35 @@ abstract class FunctionParameterAdapter {
* current version.
* @param handle handle to the database whose table is to be upgraded to a newer version.
* @param oldAdapter the adapter for the existing table to be upgraded.
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return the adapter for the new upgraded version of the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if the database can't be read or written.
* @throws CancelledException if task is cancelled
*/
static FunctionParameterAdapter upgrade(DBHandle handle, FunctionParameterAdapter oldAdapter)
throws VersionException, IOException {
private static FunctionParameterAdapter upgrade(DBHandle handle,
FunctionParameterAdapter oldAdapter, String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
FunctionParameterAdapter tmpAdapter = null;
try {
tmpAdapter = new FunctionParameterAdapterV1(tmpHandle, true);
tmpAdapter = new FunctionParameterAdapterV1(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec);
}
oldAdapter.deleteTable(handle);
FunctionParameterAdapterV1 newAdapter = new FunctionParameterAdapterV1(handle, true);
FunctionParameterAdapterV1 newAdapter =
new FunctionParameterAdapterV1(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec);
}

View file

@ -26,6 +26,7 @@ import ghidra.util.exception.VersionException;
class FunctionParameterAdapterV0 extends FunctionParameterAdapter implements RecordTranslator {
static final int VERSION = 0;
// Parameter Table Columns
static final int V0_PARAMETER_PARENT_ID_COL = 0;
static final int V0_PARAMETER_DT_ID_COL = 1;
@ -52,34 +53,15 @@ class FunctionParameterAdapterV0 extends FunctionParameterAdapter implements Rec
if (parameterTable == null) {
throw new VersionException(true);
}
int version = parameterTable.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + PARAMETER_TABLE_NAME +
" but got " + parameterTable.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
if (parameterTable.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
@Override
public DBRecord createRecord(long dataTypeID, long parentID, int ordinal, String name,
String comment, int dtLength) throws IOException {
long tableKey = parameterTable.getKey();
// if (tableKey <= DataManager.VOID_DATATYPE_ID) {
// tableKey = DataManager.VOID_DATATYPE_ID +1;
// }
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.PARAMETER, tableKey);
DBRecord record = V0_PARAMETER_SCHEMA.createRecord(key);
record.setLongValue(V0_PARAMETER_PARENT_ID_COL, parentID);
record.setLongValue(V0_PARAMETER_DT_ID_COL, dataTypeID);
record.setString(V0_PARAMETER_NAME_COL, name);
record.setString(V0_PARAMETER_COMMENT_COL, comment);
record.setIntValue(V0_PARAMETER_ORDINAL_COL, ordinal);
parameterTable.putRecord(record);
return record;
throw new UnsupportedOperationException();
}
@Override

View file

@ -22,6 +22,8 @@ import ghidra.util.exception.VersionException;
/**
* Version 1 implementation for accessing the Function Definition Parameters database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class FunctionParameterAdapterV1 extends FunctionParameterAdapter {
static final int VERSION = 1;
@ -45,30 +47,27 @@ class FunctionParameterAdapterV1 extends FunctionParameterAdapter {
/**
* Gets a version 1 adapter for the Function Definition Parameter database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO error occurs
*/
public FunctionParameterAdapterV1(DBHandle handle, boolean create)
public FunctionParameterAdapterV1(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + PARAMETER_TABLE_NAME;
if (create) {
table = handle.createTable(PARAMETER_TABLE_NAME, V1_PARAMETER_SCHEMA,
table = handle.createTable(tableName, V1_PARAMETER_SCHEMA,
new int[] { V1_PARAMETER_PARENT_ID_COL });
}
else {
table = handle.getTable(PARAMETER_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException(true);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + PARAMETER_TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}
}
@ -76,12 +75,7 @@ class FunctionParameterAdapterV1 extends FunctionParameterAdapter {
@Override
public DBRecord createRecord(long dataTypeID, long parentID, int ordinal, String name,
String comment, int dtLength) throws IOException {
long tableKey = table.getKey();
// if (tableKey <= DataManager.VOID_DATATYPE_ID) {
// tableKey = DataManager.VOID_DATATYPE_ID +1;
// }
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.PARAMETER, tableKey);
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.PARAMETER, table.getKey());
DBRecord record = V1_PARAMETER_SCHEMA.createRecord(key);
record.setLongValue(V1_PARAMETER_PARENT_ID_COL, parentID);
record.setLongValue(V1_PARAMETER_DT_ID_COL, dataTypeID);
@ -115,7 +109,7 @@ class FunctionParameterAdapterV1 extends FunctionParameterAdapter {
@Override
protected void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(PARAMETER_TABLE_NAME);
handle.deleteTable(table.getName());
}
@Override

View file

@ -21,7 +21,6 @@ import java.util.Set;
import db.DBConstants;
import db.DBHandle;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
*
@ -31,16 +30,25 @@ import ghidra.util.task.TaskMonitor;
*
*/
abstract class ParentChildAdapter {
static final String TABLE_NAME = "DT_PARENT_CHILD";
static final String PARENT_CHILD_TABLE_NAME = "DT_PARENT_CHILD";
static ParentChildAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
/**
* Gets an adapter for working with the function definition parameters database table.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @return the adapter for accessing the table of function definition parameters.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
*/
static ParentChildAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix)
throws VersionException, IOException {
if (openMode == DBConstants.CREATE) {
return new ParentChildDBAdapterV0(handle, true);
return new ParentChildDBAdapterV0(handle, tablePrefix, true);
}
try {
return new ParentChildDBAdapterV0(handle, false);
return new ParentChildDBAdapterV0(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -48,20 +56,20 @@ abstract class ParentChildAdapter {
}
ParentChildAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix);
}
return adapter;
}
}
static ParentChildAdapter findReadOnlyAdapter(DBHandle handle) {
private static ParentChildAdapter findReadOnlyAdapter(DBHandle handle) {
return new ParentChildDBAdapterNoTable(handle);
}
static ParentChildAdapter upgrade(DBHandle handle, ParentChildAdapter oldAdapter)
throws VersionException, IOException {
private static ParentChildAdapter upgrade(DBHandle handle, ParentChildAdapter oldAdapter,
String tablePrefix) throws VersionException, IOException {
ParentChildDBAdapterV0 adapter = new ParentChildDBAdapterV0(handle, true);
ParentChildDBAdapterV0 adapter = new ParentChildDBAdapterV0(handle, tablePrefix, true);
adapter.setNeedsInitializing();
return adapter;
}

View file

@ -22,6 +22,11 @@ import java.util.Set;
import db.*;
import ghidra.util.exception.VersionException;
/**
* Version 0 implementation for accessing the datatype parent/child database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class ParentChildDBAdapterV0 extends ParentChildAdapter {
private static final int VERSION = 0;
@ -35,19 +40,28 @@ class ParentChildDBAdapterV0 extends ParentChildAdapter {
private Table table;
private boolean needsInitializing = false;
ParentChildDBAdapterV0(DBHandle handle, boolean create) throws VersionException, IOException {
/**
* Gets a version 1 adapter for the datatype parent/child database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO error occurs
*/
ParentChildDBAdapterV0(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + PARENT_CHILD_TABLE_NAME;
if (create) {
table = handle.createTable(TABLE_NAME, V0_SCHEMA, new int[] { PARENT_COL, CHILD_COL });
table = handle.createTable(tableName, V0_SCHEMA, new int[] { PARENT_COL, CHILD_COL });
}
else {
table = handle.getTable(TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException(true);
}
if (table.getSchema().getVersion() != 0) {
throw new VersionException("Expected version 0 for table " + TABLE_NAME +
" but got " + table.getSchema().getVersion());
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
}

View file

@ -18,6 +18,7 @@ package ghidra.program.database.data;
import java.io.IOException;
import db.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -36,14 +37,26 @@ abstract class PointerDBAdapter implements RecordTranslator {
static final int PTR_CATEGORY_COL = 1;
static final int PTR_LENGTH_COL = 2;
static PointerDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
/**
* Gets an adapter for working with the enumeration data type values database table. The adapter is based
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of enumeration data type values.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task is cancelled
*/
static PointerDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new PointerDBAdapterV2(handle, true);
return new PointerDBAdapterV2(handle, tablePrefix, true);
}
try {
return new PointerDBAdapterV2(handle, false);
return new PointerDBAdapterV2(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -51,7 +64,7 @@ abstract class PointerDBAdapter implements RecordTranslator {
}
PointerDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter, monitor);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
@ -67,22 +80,25 @@ abstract class PointerDBAdapter implements RecordTranslator {
}
static PointerDBAdapter upgrade(DBHandle handle, PointerDBAdapter oldAdapter,
TaskMonitor monitor) throws VersionException, IOException {
String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
PointerDBAdapter tmpAdapter = null;
try {
tmpAdapter = new PointerDBAdapterV2(tmpHandle, true);
tmpAdapter = new PointerDBAdapterV2(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec);
}
oldAdapter.deleteTable(handle);
PointerDBAdapter newAdapter = new PointerDBAdapterV2(handle, true);
PointerDBAdapter newAdapter = new PointerDBAdapterV2(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec);
}

View file

@ -20,36 +20,46 @@ import java.io.IOException;
import db.*;
import ghidra.util.exception.VersionException;
/**
* Version 2 implementation for accessing the PointerDB database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class PointerDBAdapterV2 extends PointerDBAdapter {
final static int VERSION = 2;
private Table table;
PointerDBAdapterV2(DBHandle handle, boolean create) throws VersionException, IOException {
/**
* Gets a version 2 adapter for the PointerDB database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if IO error occurs
*/
PointerDBAdapterV2(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + POINTER_TABLE_NAME;
if (create) {
table = handle.createTable(POINTER_TABLE_NAME, SCHEMA, new int[] { PTR_CATEGORY_COL });
table = handle.createTable(tableName, SCHEMA, new int[] { PTR_CATEGORY_COL });
}
else {
table = handle.getTable(POINTER_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException("Missing Table: " + POINTER_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
else if (table.getSchema().getVersion() != VERSION) {
int version = table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(true);
}
throw new VersionException(VersionException.NEWER_VERSION, false);
int version = table.getSchema().getVersion();
if (version != VERSION) {
throw new VersionException(version < VERSION);
}
}
}
@Override
DBRecord createRecord(long dataTypeID, long categoryID, int length) throws IOException {
long tableKey = table.getKey();
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.POINTER, tableKey);
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.POINTER, table.getKey());
DBRecord record = SCHEMA.createRecord(key);
record.setLongValue(PTR_DT_ID_COL, dataTypeID);
record.setLongValue(PTR_CATEGORY_COL, categoryID);
@ -85,7 +95,7 @@ class PointerDBAdapterV2 extends PointerDBAdapter {
@Override
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(POINTER_TABLE_NAME);
handle.deleteTable(table.getName());
}
@Override

View file

@ -50,6 +50,9 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB
* @param handle open database handle
* @param addrMap the address map (instance settings not supported if null)
* @param openMode the program open mode (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).
* @param errHandler the database io error handler
* @param lock the program synchronization lock
* @param monitor the progress monitor
@ -57,18 +60,18 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB
* @throws VersionException if the database does not match the expected version.
* @throws IOException if a database IO error occurs.
*/
public ProgramBasedDataTypeManagerDB(DBHandle handle, AddressMap addrMap, int openMode,
ErrorHandler errHandler, Lock lock, TaskMonitor monitor)
protected ProgramBasedDataTypeManagerDB(DBHandle handle, AddressMap addrMap, int openMode,
String tablePrefix, ErrorHandler errHandler, Lock lock, TaskMonitor monitor)
throws CancelledException, VersionException, IOException {
super(handle, addrMap, openMode, errHandler, lock, monitor);
super(handle, addrMap, openMode, tablePrefix, errHandler, lock, monitor);
}
protected void initializeOtherAdapters(int openMode, TaskMonitor monitor)
throws CancelledException, IOException, VersionException {
if (addrMap != null) {
instanceSettingsAdapter =
SettingsDBAdapter.getAdapter(INSTANCE_SETTINGS_TABLE_NAME, dbHandle, openMode,
addrMap, monitor);
SettingsDBAdapter.getAdapter(tablePrefix + INSTANCE_SETTINGS_TABLE_NAME, dbHandle,
openMode, addrMap, monitor);
}
}

View file

@ -31,8 +31,7 @@ import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ChangeManager;
import ghidra.util.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
/**
@ -61,7 +60,7 @@ public class ProgramDataTypeManager extends ProgramBasedDataTypeManagerDB
public ProgramDataTypeManager(DBHandle handle, AddressMap addrMap, int openMode,
ErrorHandler errHandler, Lock lock, TaskMonitor monitor)
throws CancelledException, VersionException, IOException {
super(handle, addrMap, openMode, errHandler, lock, monitor);
super(handle, addrMap, openMode, null, errHandler, lock, monitor);
upgrade = (openMode == DBConstants.UPGRADE);
}
@ -79,8 +78,16 @@ public class ProgramDataTypeManager extends ProgramBasedDataTypeManagerDB
@Override
public void setProgram(ProgramDB p) {
this.program = p;
dataOrganization = p.getCompilerSpec().getDataOrganization();
removeOldFileNameList();
try {
setProgramArchitecture(p, p.getSymbolTable().getVariableStorageManager(), false,
TaskMonitor.DUMMY);
}
catch (CancelledException e) {
throw new AssertException(e); // unexpected - no IO performed
}
catch (IOException e) {
errHandler.dbError(e);
}
if (upgrade) {
removeOldFileNameList();
}
@ -102,11 +109,22 @@ public class ProgramDataTypeManager extends ProgramBasedDataTypeManagerDB
public void programReady(int openMode, int currentRevision, TaskMonitor monitor)
throws IOException, CancelledException {
if (openMode == DBConstants.UPGRADE) {
doSourceArchiveUpdates(program.getCompilerSpec(), monitor);
doSourceArchiveUpdates(monitor);
migrateOldFlexArrayComponentsIfRequired(monitor);
}
}
/**
* Update program-architecture information following a language upgrade/change
* @param monitor task monitor
* @throws IOException if IO error occurs
* @throws CancelledException if task monitor cancelled
*/
public void languageChanged(TaskMonitor monitor) throws IOException, CancelledException {
setProgramArchitecture(program, program.getSymbolTable().getVariableStorageManager(), true,
monitor);
}
@Override
public String getName() {
return program.getName();
@ -296,12 +314,4 @@ public class ProgramDataTypeManager extends ProgramBasedDataTypeManagerDB
return ArchiveType.PROGRAM;
}
@Override
public DataOrganization getDataOrganization() {
if (dataOrganization == null) {
dataOrganization = program.getCompilerSpec().getDataOrganization();
}
return dataOrganization;
}
}

View file

@ -22,6 +22,7 @@ import java.util.List;
import db.*;
import ghidra.program.model.data.SourceArchive;
import ghidra.util.UniversalID;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -32,8 +33,10 @@ import ghidra.util.task.TaskMonitor;
*/
abstract class SourceArchiveAdapter {
static final String TABLE_NAME = "Data Type Archive IDs";
static final String SOURCE_ARCHIVE_TABLE_NAME = "Data Type Archive IDs";
static final Schema SCHEMA = SourceArchiveAdapterV0.V0_SCHEMA;
// Data Type Archive ID Columns
static final int ARCHIVE_ID_DOMAIN_FILE_ID_COL =
SourceArchiveAdapterV0.V0_ARCHIVE_ID_DOMAIN_FILE_ID_COL;
@ -52,18 +55,20 @@ abstract class SourceArchiveAdapter {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of data type archive ID entries.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task is cancelled
*/
static SourceArchiveAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
static SourceArchiveAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
if (openMode == DBConstants.CREATE) {
return new SourceArchiveAdapterV0(handle, true);
return new SourceArchiveAdapterV0(handle, tablePrefix, true);
}
try {
return new SourceArchiveAdapterV0(handle, false);
return new SourceArchiveAdapterV0(handle, tablePrefix, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -71,7 +76,7 @@ abstract class SourceArchiveAdapter {
}
SourceArchiveAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
@ -83,7 +88,8 @@ abstract class SourceArchiveAdapter {
* @return the read only Data Type Archive ID table adapter
* @throws VersionException if a read only adapter can't be obtained for the database handle's version.
*/
static SourceArchiveAdapter findReadOnlyAdapter(DBHandle handle) {
private static SourceArchiveAdapter findReadOnlyAdapter(DBHandle handle)
throws VersionException {
return new SourceArchiveAdapterNoTable(handle);
}
@ -95,24 +101,28 @@ abstract class SourceArchiveAdapter {
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if the database can't be read or written.
* @throws CancelledException if task is cancelled
*/
static SourceArchiveAdapter upgrade(DBHandle handle, SourceArchiveAdapter oldAdapter)
throws VersionException, IOException {
private static SourceArchiveAdapter upgrade(DBHandle handle, SourceArchiveAdapter oldAdapter,
String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
SourceArchiveAdapter tmpAdapter = null;
try {
tmpAdapter = new SourceArchiveAdapterV0(tmpHandle, true);
tmpAdapter = new SourceArchiveAdapterV0(tmpHandle, tablePrefix, true);
Iterator<DBRecord> it = oldAdapter.getRecords().iterator();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec);
}
oldAdapter.deleteTable(handle);
SourceArchiveAdapter newAdapter = new SourceArchiveAdapterV0(handle, true);
SourceArchiveAdapter newAdapter = new SourceArchiveAdapterV0(handle, tablePrefix, true);
it = tmpAdapter.getRecords().iterator();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec);
}
@ -125,22 +135,33 @@ abstract class SourceArchiveAdapter {
}
}
/**
* Delete table from database
* @param handle database handle
* @throws IOException if IO error occurs
*/
abstract void deleteTable(DBHandle handle) throws IOException;
/**
* Creates a new source archive record using the information from the given source archive.
* @param sourceArchive the source archive from which to get the archive information.
* @return new archive record which corresponds to specified sourceArchive
* @throws IOException if IO error occurs
*/
abstract DBRecord createRecord(SourceArchive sourceArchive) throws IOException;
/**
* Returns a list containing all records in the archive table
* @return
* @return list of all archive records
* @throws IOException if IO error occurs
*/
abstract List<DBRecord> getRecords() throws IOException;
/**
* Returns the record for the given key (sourceArchiveID)
* @param key ID of data type archive record
* @return archive record or null if not found
* @throws IOException if IO error occurs
*/
abstract DBRecord getRecord(long key) throws IOException;
@ -153,7 +174,7 @@ abstract class SourceArchiveAdapter {
/**
* Remove the record for the given data type archive ID.
* @param dataTypeArchiveID ID of data type archive record to delete
* @param key ID of data type archive record to delete
* @return true if the record was deleted
* @throws IOException if there was a problem accessing the database
*/

View file

@ -26,6 +26,8 @@ import ghidra.util.exception.VersionException;
/**
* Version 0 implementation for accessing the Data Type Archive ID database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class SourceArchiveAdapterV0 extends SourceArchiveAdapter {
static final int VERSION = 0;
@ -45,38 +47,33 @@ class SourceArchiveAdapterV0 extends SourceArchiveAdapter {
/**
* Gets a version 1 adapter for the Data Type Archive ID table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if an IO errr occurs
*/
public SourceArchiveAdapterV0(DBHandle handle, boolean create)
public SourceArchiveAdapterV0(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + SOURCE_ARCHIVE_TABLE_NAME;
if (create) {
table = handle.createTable(TABLE_NAME, V0_SCHEMA);
table = handle.createTable(tableName, V0_SCHEMA);
createRecordForLocalManager();
}
else {
table = handle.getTable(TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException(true);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}
}
/**
*
* @throws IOException
* Create standard entry which corresponds to local datatype manager
* @throws IOException if an IO error occurs
*/
private void createRecordForLocalManager() throws IOException {
DBRecord record = V0_SCHEMA.createRecord(DataTypeManager.LOCAL_ARCHIVE_KEY);
@ -129,6 +126,7 @@ class SourceArchiveAdapterV0 extends SourceArchiveAdapter {
@Override
protected void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(table.getName());
}
}

View file

@ -19,7 +19,6 @@ import java.util.HashMap;
import java.util.Map;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.CompilerSpecID;
import ghidra.util.UniversalID;
@ -31,8 +30,8 @@ public class SourceArchiveUpgradeMap {
new long[] { OLD_CLIB_ARCHIVE_ID, OLD_NTDDK_ARCHIVE_ID, OLD_WINDOWS_ARCHIVE_ID };
private CompilerSpecID WINDOWS_CSPEC_ID = new CompilerSpecID("windows");
private Map<UniversalID, SourceArchive> windowsMap;
private Map<UniversalID, SourceArchive> defaultMap;
private Map<UniversalID, SourceArchive> oldArchiveRemappings;
public SourceArchiveUpgradeMap() {
@ -47,34 +46,25 @@ public class SourceArchiveUpgradeMap {
SourceArchive newDefaultClibArchive =
new SourceArchiveImpl(NEW_DEFAULT_CLIB_ARCHIVE_ID, NEW_DEFAULT_CLIB_ARCHIVE_NAME);
// create mapping for WINDOWS
windowsMap = new HashMap<UniversalID, SourceArchive>();
windowsMap.put(new UniversalID(OLD_CLIB_ARCHIVE_ID), newWindowsArchive);
windowsMap.put(new UniversalID(OLD_WINDOWS_ARCHIVE_ID), newWindowsArchive);
windowsMap.put(new UniversalID(OLD_NTDDK_ARCHIVE_ID), newWindowsArchive);
oldArchiveRemappings = new HashMap<UniversalID, SourceArchive>();
// create defaultMap
defaultMap = new HashMap<UniversalID, SourceArchive>();
defaultMap.put(new UniversalID(OLD_CLIB_ARCHIVE_ID), newDefaultClibArchive);
// create mappings for old Windows archives
oldArchiveRemappings.put(new UniversalID(OLD_CLIB_ARCHIVE_ID), newWindowsArchive);
oldArchiveRemappings.put(new UniversalID(OLD_WINDOWS_ARCHIVE_ID), newWindowsArchive);
oldArchiveRemappings.put(new UniversalID(OLD_NTDDK_ARCHIVE_ID), newWindowsArchive);
// create mappings for old default archives
oldArchiveRemappings.put(new UniversalID(OLD_CLIB_ARCHIVE_ID), newDefaultClibArchive);
// create mappings for old removed archives
SourceArchive removedSourceArchive = new SourceArchiveImpl();
defaultMap.put(new UniversalID(OLD_WINDOWS_ARCHIVE_ID), removedSourceArchive);
defaultMap.put(new UniversalID(OLD_NTDDK_ARCHIVE_ID), removedSourceArchive);
oldArchiveRemappings.put(new UniversalID(OLD_WINDOWS_ARCHIVE_ID), removedSourceArchive);
oldArchiveRemappings.put(new UniversalID(OLD_NTDDK_ARCHIVE_ID), removedSourceArchive);
}
public SourceArchive getMappedSourceArchive(SourceArchive sourceArchive,
CompilerSpec compiler) {
if (compiler != null) {
CompilerSpecID compilerSpecID = compiler.getCompilerSpecID();
if (WINDOWS_CSPEC_ID.equals(compilerSpecID)) {
SourceArchive replacementSourceArchive =
windowsMap.get(sourceArchive.getSourceArchiveID());
if (replacementSourceArchive != null) {
return replacementSourceArchive;
}
}
}
return defaultMap.get(sourceArchive.getSourceArchiveID());
public SourceArchive getMappedSourceArchive(SourceArchive sourceArchive) {
return oldArchiveRemappings.get(sourceArchive.getSourceArchiveID());
}
public static boolean isReplacedSourceArchive(long id) {

View file

@ -376,7 +376,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
componentName, comment);
}
// handle aligned bitfield insertion
// handle aligned bitfield insertion (packing enabled)
BitFieldDataType bitFieldDt = new BitFieldDBDataType(baseDataType, bitSize, 0);
return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
}
@ -1860,7 +1860,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
@Override
protected void fixupComponents() throws IOException {
boolean isPacked = isPackingEnabled();
boolean didChange = false;
boolean forceRepack = false;
boolean changed = false;
boolean warn = false;
int n = components.size();
for (int i = 0; i < n; i++) {
@ -1870,7 +1871,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
continue; // length can't change
}
if (dt instanceof BitFieldDataType) {
// TODO: could get messy
// Always repack if bitfields present and packing enabled
forceRepack |= isPacked;
continue;
}
int length = DataTypeComponent.usesZeroLengthComponent(dt) ? 0 : dt.getLength();
@ -1881,18 +1883,18 @@ class StructureDB extends CompositeDB implements StructureInternal {
if (dtcLen != length) {
if (isPacked) {
dtc.setLength(length, true);
didChange = true;
changed = true;
}
else if (length < dtcLen) {
dtc.setLength(length, true);
shiftOffsets(i + 1, dtcLen - length, 0); // updates structure record and last modified time
didChange = true;
changed = true;
}
else if (length > dtcLen) {
int consumed = consumeBytesAfter(i, length - dtcLen); // updates component record
if (consumed > 0) {
shiftOffsets(i + 1, -consumed, 0); // updates structure record and last modified time
didChange = true;
changed = true;
}
}
if (dtc.getLength() != length) {
@ -1900,11 +1902,14 @@ class StructureDB extends CompositeDB implements StructureInternal {
}
}
}
if (didChange) {
if (changed || forceRepack) {
// Do not notify parents - must be invoked in composite dependency order
repack(false, false);
compositeAdapter.updateRecord(record, true);
dataMgr.dataTypeChanged(this, false);
// Treat as an auto-change as a result of data organization change
changed |= repack(true, false);
}
if (changed) {
compositeAdapter.updateRecord(record, false); // force record update
dataMgr.dataTypeChanged(this, true);
}
if (warn) {
Msg.warn(this, "Failed to resize one or more structure components: " + getPathName());
@ -2238,10 +2243,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
checkAncestry(replacementDt);
}
catch (Exception e) {
// TODO: should we use Undefined1 instead to avoid cases where DEFAULT datatype can
// not be used (bitfield, aligned structure, etc.)
// TODO: failing silently is rather hidden
replacementDt = DataType.DEFAULT;
// TODO: should we flag bad replacement
replacementDt = isPackingEnabled() ? Undefined1DataType.dataType : DataType.DEFAULT;
}
boolean changed = false;

View file

@ -19,6 +19,7 @@ import java.io.IOException;
import db.*;
import ghidra.util.UniversalID;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
@ -51,15 +52,18 @@ abstract class TypedefDBAdapter {
* on the version of the database associated with the specified database handle and the openMode.
* @param handle handle to the database to be accessed.
* @param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
* @param tablePrefix prefix to be used with default table name
* @param monitor the monitor to use for displaying status or for canceling.
* @return the adapter for accessing the table of Typedef data types.
* @throws VersionException if the database handle's version doesn't match the expected version.
* @throws IOException if there is trouble accessing the database.
* @throws CancelledException if task is cancelled
*/
static TypedefDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
static TypedefDBAdapter getAdapter(DBHandle handle, int openMode, String tablePrefix,
TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
try {
return new TypedefDBAdapterV2(handle, openMode == DBConstants.CREATE);
return new TypedefDBAdapterV2(handle, tablePrefix, openMode == DBConstants.CREATE);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
@ -67,7 +71,7 @@ abstract class TypedefDBAdapter {
}
TypedefDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
adapter = upgrade(handle, adapter, tablePrefix, monitor);
}
return adapter;
}
@ -79,7 +83,7 @@ abstract class TypedefDBAdapter {
* @return the read only Typedef table adapter
* @throws VersionException if a read only adapter can't be obtained for the database handle's version.
*/
static TypedefDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
private static TypedefDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException {
try {
return new TypedefDBAdapterV1(handle);
}
@ -93,28 +97,34 @@ abstract class TypedefDBAdapter {
* Upgrades the Typedef data type table from the oldAdapter's version to the current version.
* @param handle handle to the database whose table is to be upgraded to a newer version.
* @param oldAdapter the adapter for the existing table to be upgraded.
* @param tablePrefix prefix to be used with default table name
* @param monitor task monitor
* @return the adapter for the new upgraded version of the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if the database can't be read or written.
* @throws CancelledException if task is cancelled
*/
static TypedefDBAdapter upgrade(DBHandle handle, TypedefDBAdapter oldAdapter)
throws VersionException, IOException {
private static TypedefDBAdapter upgrade(DBHandle handle, TypedefDBAdapter oldAdapter,
String tablePrefix, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
DBHandle tmpHandle = new DBHandle();
long id = tmpHandle.startTransaction();
TypedefDBAdapter tmpAdapter = null;
try {
tmpAdapter = new TypedefDBAdapterV2(tmpHandle, true);
tmpAdapter = new TypedefDBAdapterV2(tmpHandle, tablePrefix, true);
RecordIterator it = oldAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
tmpAdapter.updateRecord(rec, false);
}
oldAdapter.deleteTable(handle);
TypedefDBAdapter newAdapter = new TypedefDBAdapterV2(handle, true);
TypedefDBAdapter newAdapter = new TypedefDBAdapterV2(handle, tablePrefix, true);
it = tmpAdapter.getRecords();
while (it.hasNext()) {
monitor.checkCanceled();
DBRecord rec = it.next();
newAdapter.updateRecord(rec, false);
}

View file

@ -28,15 +28,19 @@ import ghidra.util.exception.VersionException;
* Version 0 implementation for accessing the Typedef database table.
*/
class TypedefDBAdapterV0 extends TypedefDBAdapter implements RecordTranslator {
static final int VERSION = 0;
private static final int V0_TYPEDEF_DT_ID_COL = 0;
private static final int V0_TYPEDEF_NAME_COL = 1;
private static final int V0_TYPEDEF_CAT_COL = 2;
// DO NOT REMOVE WHAT'S BELOW - this documents the schema used in version 0.
// static final Schema V0_SCHEMA = new Schema(VERSION, "Typedef ID",
// new Class[] {LongField.class, StringField.class,
// LongField.class},
// new String[] {"Data Type ID", "Name", "Category ID"});
private Table table;
/**
@ -51,14 +55,8 @@ class TypedefDBAdapterV0 extends TypedefDBAdapter implements RecordTranslator {
if (table == null) {
throw new VersionException("Missing Table: " + TYPEDEF_TABLE_NAME);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + TYPEDEF_TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
if (table.getSchema().getVersion() != VERSION) {
throw new VersionException(false);
}
}

View file

@ -25,7 +25,9 @@ import ghidra.util.exception.VersionException;
* Version 1 implementation for accessing the Typedef database table.
*/
class TypedefDBAdapterV1 extends TypedefDBAdapter implements RecordTranslator {
static final int VERSION = 1;
static final int V1_TYPEDEF_DT_ID_COL = 0;
static final int V1_TYPEDEF_NAME_COL = 1;
static final int V1_TYPEDEF_CAT_COL = 2;
@ -40,6 +42,7 @@ class TypedefDBAdapterV1 extends TypedefDBAdapter implements RecordTranslator {
// LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE },
// new String[] { "Data Type ID", "Name", "Category ID", "Source Archive ID",
// "Universal Data Type ID", "Source Sync Time", "Last Change Time" });
private Table table;
/**
@ -56,12 +59,7 @@ class TypedefDBAdapterV1 extends TypedefDBAdapter implements RecordTranslator {
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + TYPEDEF_TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}

View file

@ -24,9 +24,13 @@ import ghidra.util.exception.VersionException;
/**
* Version 2 implementation for accessing the Typedef database table.
*
* NOTE: Use of tablePrefix introduced with this adapter version.
*/
class TypedefDBAdapterV2 extends TypedefDBAdapter {
static final int VERSION = 2;
static final int V2_TYPEDEF_DT_ID_COL = 0;
static final int V2_TYPEDEF_FLAGS_COL = 1;
static final int V2_TYPEDEF_NAME_COL = 2;
@ -35,61 +39,53 @@ class TypedefDBAdapterV2 extends TypedefDBAdapter {
static final int V2_TYPEDEF_UNIVERSAL_DT_ID_COL = 5;
static final int V2_TYPEDEF_SOURCE_SYNC_TIME_COL = 6;
static final int V2_TYPEDEF_LAST_CHANGE_TIME_COL = 7;
static final Schema V2_SCHEMA = new Schema(VERSION, "Typedef ID",
new Field[] { LongField.INSTANCE, ShortField.INSTANCE, StringField.INSTANCE,
LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE,
LongField.INSTANCE },
new String[] { "Data Type ID", "Flags", "Name", "Category ID", "Source Archive ID",
"Universal Data Type ID", "Source Sync Time", "Last Change Time" });
private Table table;
/**
* Gets a version 1 adapter for the Typedef database table.
* @param handle handle to the database containing the table.
* @param tablePrefix prefix to be used with default table name
* @param create true if this constructor should create the table.
* @throws VersionException if the the table's version does not match the expected version
* for this adapter.
* @throws IOException if IO error occurs
*/
public TypedefDBAdapterV2(DBHandle handle, boolean create)
public TypedefDBAdapterV2(DBHandle handle, String tablePrefix, boolean create)
throws VersionException, IOException {
String tableName = tablePrefix + TYPEDEF_TABLE_NAME;
if (create) {
table = handle.createTable(TYPEDEF_TABLE_NAME, V2_SCHEMA,
table = handle.createTable(tableName, V2_SCHEMA,
new int[] { V2_TYPEDEF_CAT_COL, V2_TYPEDEF_UNIVERSAL_DT_ID_COL });
}
else {
table = handle.getTable(TYPEDEF_TABLE_NAME);
table = handle.getTable(tableName);
if (table == null) {
throw new VersionException("Missing Table: " + TYPEDEF_TABLE_NAME);
throw new VersionException("Missing Table: " + tableName);
}
int version = table.getSchema().getVersion();
if (version != VERSION) {
String msg = "Expected version " + VERSION + " for table " + TYPEDEF_TABLE_NAME +
" but got " + table.getSchema().getVersion();
if (version < VERSION) {
throw new VersionException(msg, VersionException.OLDER_VERSION, true);
}
throw new VersionException(msg, VersionException.NEWER_VERSION, false);
throw new VersionException(version < VERSION);
}
}
}
@Override
void deleteTable(DBHandle handle) throws IOException {
handle.deleteTable(TYPEDEF_TABLE_NAME);
handle.deleteTable(table.getName());
}
@Override
public DBRecord createRecord(long dataTypeID, String name, short flags, long categoryID,
long sourceArchiveID, long sourceDataTypeID, long lastChangeTime) throws IOException {
long tableKey = table.getKey();
// if (tableKey <= DataManager.VOID_DATATYPE_ID) {
// tableKey = DataManager.VOID_DATATYPE_ID +1;
// }
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.TYPEDEF, tableKey);
long key = DataTypeManagerDB.createKey(DataTypeManagerDB.TYPEDEF, table.getKey());
DBRecord record = V2_SCHEMA.createRecord(key);
record.setLongValue(V2_TYPEDEF_DT_ID_COL, dataTypeID);
record.setShortValue(V2_TYPEDEF_FLAGS_COL, flags);

View file

@ -497,12 +497,10 @@ class UnionDB extends CompositeDB implements UnionInternal {
}
}
if (changed) {
// NOTE: since we do not retain our external alignment we have no way of knowing if
// it has changed, so we must assume it has if we are an aligned union
// Do not notify parents
if (!repack(false, false)) {
dataMgr.dataTypeChanged(this, false);
}
// Do not notify parents - must be invoked in composite dependency order
// Treat as an auto-change as a result of data organization change
repack(true, false);
dataMgr.dataTypeChanged(this, true);
}
}
@ -562,8 +560,8 @@ class UnionDB extends CompositeDB implements UnionInternal {
DataType baseDataType = bitfieldDt.getBaseDataType();
baseDataType = resolve(baseDataType);
// Both aligned and non-packed bitfields use same adjustment
// non-packed must force bitfield placement at byte offset 0
// Both packed and non-packed bitfields use same adjustment
// Non-packed must force bitfield placement at byte offset 0
int bitSize = bitfieldDt.getDeclaredBitSize();
int effectiveBitSize =
BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength());
@ -795,9 +793,8 @@ class UnionDB extends CompositeDB implements UnionInternal {
checkAncestry(replacementDt);
}
catch (Exception e) {
// TODO: should we use Undefined instead since we do not support
// DEFAULT in Unions
replacementDt = DataType.DEFAULT;
// TODO: should we flag bad replacement
replacementDt = Undefined1DataType.dataType;
}
boolean changed = false;
for (int i = components.size() - 1; i >= 0; i--) {

View file

@ -1,79 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.function;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
import java.io.IOException;
import db.*;
/**
* Adapter to access the Function Calling Conventions tables.
*/
abstract class CallingConventionDBAdapter {
static final byte UNKNOWN_CALLING_CONVENTION_ID = (byte) 0;
static final byte DEFAULT_CALLING_CONVENTION_ID = (byte) 1;
static final Schema CALLING_CONVENTION_SCHEMA =
CallingConventionDBAdapterV0.V0_CALLING_CONVENTION_SCHEMA;
// Calling Convention Columns
static final int CALLING_CONVENTION_NAME_COL =
CallingConventionDBAdapterV0.V0_CALLING_CONVENTION_NAME_COL;
static CallingConventionDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor)
throws VersionException, IOException {
if (openMode == DBConstants.CREATE) {
return new CallingConventionDBAdapterV0(handle, true);
}
try {
return new CallingConventionDBAdapterV0(handle, false);
}
catch (VersionException e) {
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
throw e;
}
CallingConventionDBAdapter adapter = findReadOnlyAdapter(handle);
if (openMode == DBConstants.UPGRADE) {
adapter = upgrade(handle, adapter);
}
return adapter;
}
}
static CallingConventionDBAdapter findReadOnlyAdapter(DBHandle handle) throws IOException {
try {
return new CallingConventionDBAdapterV0(handle, false);
}
catch (VersionException e) {
}
return new CallingConventionDBAdapterNoTable();
}
static CallingConventionDBAdapter upgrade(DBHandle handle, CallingConventionDBAdapter oldAdapter)
throws VersionException, IOException {
return new CallingConventionDBAdapterV0(handle, true);
}
abstract DBRecord createCallingConventionRecord(String name) throws IOException;
abstract DBRecord getCallingConventionRecord(byte callingConventionID) throws IOException;
abstract DBRecord getCallingConventionRecord(String name) throws IOException;
}

View file

@ -1,59 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.function;
import java.io.IOException;
import db.DBRecord;
/**
* Adapter needed for a read-only version of Program that is not going
* to be upgraded, and there is no Calling Convention table in the Program.
*
*/
class CallingConventionDBAdapterNoTable extends CallingConventionDBAdapter {
/**
*
*/
public CallingConventionDBAdapterNoTable() {
}
/* (non-Javadoc)
* @see ghidra.program.database.function.CallingConventionDBAdapter#createCallingConventionRecord(java.lang.String)
*/
@Override
public DBRecord createCallingConventionRecord(String name) throws IOException {
return null;
}
/* (non-Javadoc)
* @see ghidra.program.database.function.CallingConventionDBAdapter#getCallingConventionRecord(byte)
*/
@Override
public DBRecord getCallingConventionRecord(byte callingConventionID) throws IOException {
return null;
}
/* (non-Javadoc)
* @see ghidra.program.database.function.CallingConventionDBAdapter#getCallingConventionRecord(java.lang.String)
*/
@Override
public DBRecord getCallingConventionRecord(String name) throws IOException {
return null;
}
}

View file

@ -1,109 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.function;
import java.io.IOException;
import db.*;
import ghidra.util.exception.VersionException;
/**
* Version 0 implementation for the calling conventions tables adapter.
*
*/
class CallingConventionDBAdapterV0 extends CallingConventionDBAdapter {
static final String CALLING_CONVENTION_TABLE_NAME = "Calling Conventions";
// Calling Convention Columns
// Key field is the Calling convention ID, which is a Byte field.
static final int V0_CALLING_CONVENTION_NAME_COL = 0;
static final Schema V0_CALLING_CONVENTION_SCHEMA = new Schema(0, ByteField.INSTANCE, "ID",
new Field[] { StringField.INSTANCE }, new String[] { "Name" });
private Table callingConventionTable;
/**
* Constructor
*
*/
public CallingConventionDBAdapterV0(DBHandle handle, boolean create)
throws VersionException, IOException {
if (create) {
// No additional indexed fields.
callingConventionTable = handle.createTable(CALLING_CONVENTION_TABLE_NAME,
V0_CALLING_CONVENTION_SCHEMA, new int[] {});
}
else {
callingConventionTable = handle.getTable(CALLING_CONVENTION_TABLE_NAME);
if (callingConventionTable == null) {
throw new VersionException(true);
}
if (callingConventionTable.getSchema().getVersion() != 0) {
throw new VersionException(VersionException.NEWER_VERSION, false);
}
}
}
@Override
public DBRecord createCallingConventionRecord(String name) throws IOException {
byte key = getFirstAvailableKey();
DBRecord record = V0_CALLING_CONVENTION_SCHEMA.createRecord(new ByteField(key));
record.setString(V0_CALLING_CONVENTION_NAME_COL, name);
callingConventionTable.putRecord(record);
return record;
}
/**
* Get the first unused key value. Remember 0 is reserved for unknown and 1 for default.
* @return the first available key. This is a number for 2 to 255.
* @throws IOException if there are no more available keys.
*/
private byte getFirstAvailableKey() throws IOException {
byte key = 2;
for (; key < 256; key++) {
DBRecord record = getCallingConventionRecord(key);
if (record == null) {
return key;
}
}
if (key >= 256) {
throw new IOException("No more keys available for calling conventions.");
}
return key;
}
@Override
public DBRecord getCallingConventionRecord(byte callingConventionID) throws IOException {
return callingConventionTable.getRecord(new ByteField(callingConventionID));
}
@Override
public DBRecord getCallingConventionRecord(String name) throws IOException {
RecordIterator iterator = callingConventionTable.iterator();
while (iterator.hasNext()) {
DBRecord record = iterator.next();
String callingConventionName = record.getString(V0_CALLING_CONVENTION_NAME_COL);
if (callingConventionName.equals(name)) {
return record;
}
}
return null;
}
}

View file

@ -15,15 +15,15 @@
*/
package ghidra.program.database.function;
import java.io.IOException;
import db.*;
import ghidra.program.database.data.DataTypeManagerDB;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.listing.Function;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.exception.VersionException;
import java.io.IOException;
import db.*;
class FunctionAdapterV3 extends FunctionAdapter {
//
@ -116,7 +116,7 @@ class FunctionAdapterV3 extends FunctionAdapter {
rec.setByteValue(FUNCTION_FLAGS_COL, getSignatureSourceFlagBits(SourceType.DEFAULT));
rec.setLongValue(RETURN_DATA_TYPE_ID_COL, returnDataTypeId);
rec.setByteValue(CALLING_CONVENTION_ID_COL,
CallingConventionDBAdapter.UNKNOWN_CALLING_CONVENTION_ID);
DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID);
rec.setIntValue(STACK_PURGE_COL, Function.UNKNOWN_STACK_DEPTH_CHANGE);
table.putRecord(rec);
return rec;

View file

@ -229,11 +229,6 @@ public class FunctionDB extends DatabaseObject implements Function {
return super.hashCode();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getName(true);
@ -826,7 +821,7 @@ public class FunctionDB extends DatabaseObject implements Function {
PrototypeModel callingConvention = getCallingConvention();
if (callingConvention == null) {
callingConvention = getDefaultCallingConvention();
callingConvention = manager.getDefaultCallingConvention();
}
if (callingConvention == null) {
return;
@ -1310,6 +1305,7 @@ public class FunctionDB extends DatabaseObject implements Function {
source);
}
/**
* Increment updateInProgressCount indicating that an update operation is in progress and
* that any attempted refresh should be deferred. The updateRefreshReqd flag will be set
@ -2517,11 +2513,6 @@ public class FunctionDB extends DatabaseObject implements Function {
}
}
/*
* (non-Javadoc)
*
* @see ghidra.program.model.listing.Function#getCallingConvention()
*/
@Override
public PrototypeModel getCallingConvention() {
String name = getCallingConventionName();
@ -2535,11 +2526,6 @@ public class FunctionDB extends DatabaseObject implements Function {
return functionMgr.getCallingConvention(name);
}
/*
* (non-Javadoc)
*
* @see ghidra.program.model.listing.Function#getCallingConventionName()
*/
@Override
public String getCallingConventionName() {
manager.lock.acquire();
@ -2551,14 +2537,13 @@ public class FunctionDB extends DatabaseObject implements Function {
return thunkedFunction.getCallingConventionName();
}
byte callingConventionID = rec.getByteValue(FunctionAdapter.CALLING_CONVENTION_ID_COL);
if (callingConventionID == CallingConventionDBAdapter.UNKNOWN_CALLING_CONVENTION_ID) {
if (callingConventionID == DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID) {
return Function.UNKNOWN_CALLING_CONVENTION_STRING;
}
if (callingConventionID == CallingConventionDBAdapter.DEFAULT_CALLING_CONVENTION_ID) {
if (callingConventionID == DataTypeManagerDB.DEFAULT_CALLING_CONVENTION_ID) {
return Function.DEFAULT_CALLING_CONVENTION_STRING;
}
String name = manager.getCallingConventionName(callingConventionID);
return name != null ? name : UNKNOWN_CALLING_CONVENTION_STRING;
return program.getDataTypeManager().getCallingConventionName(callingConventionID);
}
finally {
manager.lock.release();
@ -2569,36 +2554,16 @@ public class FunctionDB extends DatabaseObject implements Function {
if (thunkedFunction != null) {
return thunkedFunction.getRealCallingConventionName();
}
String name = null;
byte callingConventionID = rec.getByteValue(FunctionAdapter.CALLING_CONVENTION_ID_COL);
if (callingConventionID != CallingConventionDBAdapter.UNKNOWN_CALLING_CONVENTION_ID &&
callingConventionID != CallingConventionDBAdapter.DEFAULT_CALLING_CONVENTION_ID) {
name = manager.getCallingConventionName(callingConventionID);
String name = program.getDataTypeManager().getCallingConventionName(callingConventionID);
if (UNKNOWN_CALLING_CONVENTION_STRING.equals(name) ||
DEFAULT_CALLING_CONVENTION_STRING.equals(name)) {
name = null;
}
// null returned for unknown or default calling convention
return name;
}
private PrototypeModel getDefaultCallingConvention() {
CompilerSpec compilerSpec = getProgram().getCompilerSpec();
if (compilerSpec != null) {
return compilerSpec.getDefaultCallingConvention();
}
return null;
}
@Override
public String getDefaultCallingConventionName() {
PrototypeModel defaultPrototype = getDefaultCallingConvention();
if (defaultPrototype != null) {
String defaultPrototypeName = defaultPrototype.getName();
if (defaultPrototypeName != null) {
return defaultPrototypeName;
}
}
return Function.DEFAULT_CALLING_CONVENTION_STRING;
}
@Override
public void setCallingConvention(String name) throws InvalidInputException {
manager.lock.acquire();
@ -2610,36 +2575,38 @@ public class FunctionDB extends DatabaseObject implements Function {
return;
}
byte newCallingConventionID = manager.getCallingConventionID(name);
byte newCallingConventionID =
program.getDataTypeManager().getCallingConventionID(name, true);
byte oldCallingConventionID =
rec.getByteValue(FunctionAdapter.CALLING_CONVENTION_ID_COL);
if (oldCallingConventionID != newCallingConventionID) {
if (oldCallingConventionID == newCallingConventionID) {
return; // no change
}
loadVariables();
rec.setByteValue(FunctionAdapter.CALLING_CONVENTION_ID_COL, newCallingConventionID);
manager.getFunctionAdapter().updateFunctionRecord(rec);
boolean hasCustomStorage = hasCustomVariableStorage();
if (!hasCustomStorage) {
// remove 'this' param if switching to __thiscall with dynamic storage
removeExplicitThisParameter();
}
frame.setInvalid();
if (!hasCustomStorage) {
createClassStructIfNeeded(); // TODO: How should thunks within Class namespace be handled?
loadVariables();
rec.setByteValue(FunctionAdapter.CALLING_CONVENTION_ID_COL, newCallingConventionID);
manager.getFunctionAdapter().updateFunctionRecord(rec);
boolean hasCustomStorage = hasCustomVariableStorage();
if (!hasCustomStorage) {
// remove 'this' param if switching to __thiscall with dynamic storage
removeExplicitThisParameter();
}
frame.setInvalid();
if (!hasCustomStorage) {
createClassStructIfNeeded(); // TODO: How should thunks within Class namespace be handled?
loadVariables();
removeExplicitThisParameter();
updateParametersAndReturn(); // assign dynamic storage
manager.functionChanged(this, ChangeManager.FUNCTION_CHANGED_PARAMETERS);
manager.functionChanged(this, ChangeManager.FUNCTION_CHANGED_RETURN);
}
else {
manager.functionChanged(this, 0); // change did not affect parameters
}
removeExplicitThisParameter();
updateParametersAndReturn(); // assign dynamic storage
manager.functionChanged(this, ChangeManager.FUNCTION_CHANGED_PARAMETERS);
manager.functionChanged(this, ChangeManager.FUNCTION_CHANGED_RETURN);
}
else {
manager.functionChanged(this, 0); // change did not affect parameters
}
}
catch (IOException e) {
@ -2654,7 +2621,7 @@ public class FunctionDB extends DatabaseObject implements Function {
void createClassStructIfNeeded() {
PrototypeModel callingConvention = getCallingConvention();
if (callingConvention == null ||
callingConvention.getGenericCallingConvention() != GenericCallingConvention.thiscall) {
!CompilerSpec.CALLING_CONVENTION_thiscall.equals(callingConvention.getName())) {
return;
}
Namespace parent = getParentNamespace();

View file

@ -26,6 +26,7 @@ import generic.FilteredIterator;
import ghidra.program.database.DBObjectCache;
import ghidra.program.database.ProgramDB;
import ghidra.program.database.code.CodeManager;
import ghidra.program.database.data.DataTypeManagerDB;
import ghidra.program.database.external.ExternalLocationDB;
import ghidra.program.database.map.AddressMap;
import ghidra.program.database.symbol.*;
@ -60,12 +61,10 @@ public class FunctionManagerDB implements FunctionManager {
private DBObjectCache<FunctionDB> cache;
private FunctionAdapter adapter;
private ThunkFunctionAdapter thunkAdapter;
private CallingConventionDBAdapter callingConventionAdapter;
private Map<String, Byte> callingConventionNameToIDMap = new HashMap<>();
private Map<Byte, String> callingConventionIDToNameMap = new HashMap<>();
private NamespaceManager namespaceMgr;
private SymbolManager symbolMgr;
private CodeManager codeMgr;
private DataTypeManagerDB dtMgr;
private FunctionTagManagerDB functionTagManager;
private Namespace globalNamespace;
@ -125,8 +124,6 @@ public class FunctionManagerDB implements FunctionManager {
}
adapter = FunctionAdapter.getAdapter(dbHandle, openMode, addrMap, monitor);
thunkAdapter = ThunkFunctionAdapter.getAdapter(dbHandle, openMode, addrMap, monitor);
callingConventionAdapter =
CallingConventionDBAdapter.getAdapter(dbHandle, openMode, monitor);
}
@Override
@ -138,136 +135,21 @@ public class FunctionManagerDB implements FunctionManager {
return adapter;
}
/**
* Get calling convention name corresponding to existing ID. If id is no longer valid,
* null will be returned.
* @param id
* @return
*/
String getCallingConventionName(byte id) {
if (id == CallingConventionDBAdapter.DEFAULT_CALLING_CONVENTION_ID) {
return Function.DEFAULT_CALLING_CONVENTION_STRING;
}
else if (id == CallingConventionDBAdapter.UNKNOWN_CALLING_CONVENTION_ID) {
return null;
}
String name = callingConventionIDToNameMap.get(id);
if (name != null) {
return name;
}
try {
DBRecord record = callingConventionAdapter.getCallingConventionRecord(id);
if (record == null) {
return null;
}
name = record.getString(CallingConventionDBAdapter.CALLING_CONVENTION_NAME_COL);
CompilerSpec compilerSpec = program.getCompilerSpec();
PrototypeModel callingConvention = compilerSpec.getCallingConvention(name);
if (callingConvention != null) {
callingConventionIDToNameMap.put(id, name);
callingConventionNameToIDMap.put(name, id);
return name;
}
}
catch (IOException e) {
dbError(e);
}
return null;
}
/**
* Get (and assign if needed) the ID associated with the specified calling convention name.
* @param name calling convention name
* @return calling convention ID
* @throws IOException
* @throws InvalidInputException
*/
byte getCallingConventionID(String name) throws InvalidInputException, IOException {
if (name == null || name.equals(Function.UNKNOWN_CALLING_CONVENTION_STRING)) {
return CallingConventionDBAdapter.UNKNOWN_CALLING_CONVENTION_ID;
}
else if (name.equals(Function.DEFAULT_CALLING_CONVENTION_STRING)) {
return CallingConventionDBAdapter.DEFAULT_CALLING_CONVENTION_ID;
}
Byte id = callingConventionNameToIDMap.get(name);
if (id != null) {
return id;
}
CompilerSpec compilerSpec = program.getCompilerSpec();
PrototypeModel callingConvention = compilerSpec.getCallingConvention(name);
if (callingConvention == null) {
throw new InvalidInputException("Invalid calling convention name: " + name);
}
DBRecord record = callingConventionAdapter.getCallingConventionRecord(name);
if (record == null) {
record = callingConventionAdapter.createCallingConventionRecord(name);
}
byte newId = record.getKeyField().getByteValue();
callingConventionIDToNameMap.put(newId, name);
callingConventionNameToIDMap.put(name, newId);
return newId;
}
@Override
public List<String> getCallingConventionNames() {
CompilerSpec compilerSpec = program.getCompilerSpec();
PrototypeModel[] namedCallingConventions = compilerSpec.getCallingConventions();
List<String> names = new ArrayList<>(namedCallingConventions.length + 2);
names.add(Function.UNKNOWN_CALLING_CONVENTION_STRING);
names.add(Function.DEFAULT_CALLING_CONVENTION_STRING);
for (PrototypeModel model : namedCallingConventions) {
names.add(model.getName());
}
return names;
public Collection<String> getCallingConventionNames() {
return dtMgr.getDefinedCallingConventionNames();
}
@Override
public PrototypeModel getDefaultCallingConvention() {
CompilerSpec compilerSpec = program.getCompilerSpec();
if (compilerSpec == null) {
return null;
}
return compilerSpec.getDefaultCallingConvention();
}
@Override
public PrototypeModel getCallingConvention(String name) {
CompilerSpec compilerSpec = program.getCompilerSpec();
if (compilerSpec == null) {
return null;
}
if (Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(name)) {
return null;
}
if (Function.DEFAULT_CALLING_CONVENTION_STRING.equals(name)) {
return getDefaultCallingConvention();
}
PrototypeModel[] models = compilerSpec.getCallingConventions();
for (PrototypeModel model : models) {
String modelName = model.getName();
if (modelName != null && modelName.equals(name)) {
return model;
}
}
return null;
}
@Override
public PrototypeModel[] getCallingConventions() {
CompilerSpec compilerSpec = program.getCompilerSpec();
if (compilerSpec == null) {
return new PrototypeModel[0];
}
ArrayList<PrototypeModel> namedList = new ArrayList<>();
PrototypeModel[] models = compilerSpec.getCallingConventions();
for (PrototypeModel model : models) {
String name = model.getName();
if (name != null && name.length() > 0) {
namedList.add(model);
}
}
return namedList.toArray(new PrototypeModel[namedList.size()]);
return compilerSpec.getCallingConvention(name);
}
/**
@ -751,7 +633,8 @@ public class FunctionManagerDB implements FunctionManager {
this.program = program;
namespaceMgr = program.getNamespaceManager();
codeMgr = program.getCodeManager();
symbolMgr = (SymbolManager) program.getSymbolTable();
dtMgr = program.getDataTypeManager();
symbolMgr = program.getSymbolTable();
globalNamespace = program.getGlobalNamespace();
functionTagManager.setProgram(program);
}
@ -935,8 +818,6 @@ public class FunctionManagerDB implements FunctionManager {
callFixupMap = null;
lastFuncID = -1;
cache.invalidate();
callingConventionIDToNameMap.clear();
callingConventionNameToIDMap.clear();
}
finally {
lock.release();
@ -1037,9 +918,8 @@ public class FunctionManagerDB implements FunctionManager {
}
/**
* Construct a function iterator over all functions residing in memory starting from the specified
* entry point address.
* @param start starting address for iteration
* Construct a function iterator over all functions residing in specified address set.
* @param addrSet address set over which to iterate
* @param forward if true iterate forward from start, otherwise iterate in reverse
*/
FunctionIteratorDB(AddressSetView addrSet, boolean forward) {
@ -1096,9 +976,6 @@ public class FunctionManagerDB implements FunctionManager {
return list.iterator();
}
/**
* Set the new body for the function.
*/
void setFunctionBody(FunctionDB function, AddressSetView newBody)
throws OverlappingFunctionException {

View file

@ -24,6 +24,7 @@ import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import db.*;
import db.util.ErrorHandler;
import ghidra.program.database.*;
import ghidra.program.database.code.CodeManager;
import ghidra.program.database.external.ExternalManagerDB;
@ -63,6 +64,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
private LabelHistoryAdapter historyAdapter;
private DBObjectCache<SymbolDB> cache;
private ErrorHandler errHandler;
private ProgramDB program;
private ReferenceDBManager refManager;
private NamespaceManager namespaceMgr;
@ -81,22 +83,26 @@ public class SymbolManager implements SymbolTable, ManagerDB {
* @param handle the database handler
* @param addrMap the address map.
* @param openMode the open mode.
* @param errHandler database error handler
* @param lock the program synchronization lock
* @param monitor the progress monitor used when upgrading.
* @throws CancelledException if the user cancels the upgrade.
* @throws IOException if a database io error occurs.
* @throws VersionException if the database version doesn't match the current version.
*/
public SymbolManager(DBHandle handle, AddressMap addrMap, int openMode, Lock lock,
TaskMonitor monitor) throws CancelledException, IOException, VersionException {
public SymbolManager(DBHandle handle, AddressMap addrMap, int openMode, ErrorHandler errHandler,
Lock lock, TaskMonitor monitor)
throws CancelledException, IOException, VersionException {
this.addrMap = addrMap;
this.errHandler = errHandler;
this.lock = lock;
dynamicSymbolAddressMap = new AddressMapImpl((byte) 0x40, addrMap.getAddressFactory());
initializeAdapters(handle, openMode, monitor);
cache = new DBObjectCache<>(100);
variableStorageMgr = new VariableStorageManagerDB(handle, addrMap, openMode, lock, monitor);
variableStorageMgr =
new VariableStorageManagerDB(handle, addrMap, openMode, errHandler, lock, monitor);
if (openMode == DBConstants.UPGRADE &&
OldVariableStorageManagerDB.isOldVariableStorageManagerUpgradeRequired(handle)) {
@ -140,7 +146,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
this.program = program;
refManager = program.getReferenceManager();
namespaceMgr = program.getNamespaceManager();
variableStorageMgr.setProgram(program);
variableStorageMgr.setProgramArchitecture(program);
}
@Override
@ -177,6 +183,14 @@ public class SymbolManager implements SymbolTable, ManagerDB {
}
}
/**
* Get the variable storage manager used by this symbol table
* @return varable storage manager
*/
public VariableStorageManager getVariableStorageManager() {
return variableStorageMgr;
}
/**
* Check for and upgrade old namespace symbol addresses which included a namespace ID.
* <p>
@ -1579,7 +1593,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
}
void dbError(IOException e) {
program.dbError(e);
errHandler.dbError(e);
}
void validateSource(String name, Address address, SymbolType symbolType, SourceType source) {

View file

@ -39,6 +39,7 @@ abstract class VariableStorageDBAdapter {
* @param openMode the openmode
* @param addrMap the address map
* @param monitor the progress monitor.
* @return variable storage table adapter
* @throws VersionException if the database table does not match the adapter.
* @throws CancelledException if the user cancels an upgrade.
* @throws IOException if a database io error occurs.
@ -95,4 +96,6 @@ abstract class VariableStorageDBAdapter {
abstract int getRecordCount();
abstract void deleteTable() throws IOException;
}

View file

@ -60,4 +60,9 @@ public class VariableStorageDBAdapterNoTable extends VariableStorageDBAdapter {
int getRecordCount() {
return 0;
}
@Override
void deleteTable() {
// do nothing
}
}

View file

@ -26,10 +26,11 @@ public class VariableStorageDBAdapterV2 extends VariableStorageDBAdapter {
private static final int TABLE_VERSION = 2;
private Table variableStorageTable;
private DBHandle handle;
VariableStorageDBAdapterV2(DBHandle handle, boolean create)
throws VersionException, IOException {
this.handle = handle;
if (create) {
variableStorageTable = handle.createTable(VARIABLE_STORAGE_TABLE_NAME,
VARIABLE_STORAGE_SCHEMA, new int[] { HASH_COL });
@ -49,6 +50,11 @@ public class VariableStorageDBAdapterV2 extends VariableStorageDBAdapter {
}
}
@Override
void deleteTable() throws IOException {
handle.deleteTable(VARIABLE_STORAGE_TABLE_NAME);
}
@Override
long getNextStorageID() {
long nextKey = variableStorageTable.getMaxKey() + 1;

View file

@ -0,0 +1,34 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.database.symbol;
import java.io.IOException;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.VariableStorage;
public interface VariableStorageManager {
/**
* Get a variable address for the given storage specification.
* @param storage variable storage specification
* @param create if true a new variable address will be allocated if needed
* @return variable address which corresponds to the storage specification or null if not found
* and create is false.
* @throws IOException if an IO error occurs
*/
Address getVariableStorageAddress(VariableStorage storage, boolean create) throws IOException;
}

View file

@ -19,10 +19,13 @@ import java.io.IOException;
import java.util.List;
import db.*;
import ghidra.program.database.*;
import db.util.ErrorHandler;
import ghidra.program.database.DBObjectCache;
import ghidra.program.database.DatabaseObject;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.ProgramArchitecture;
import ghidra.program.model.listing.VariableStorage;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.util.LanguageTranslator;
@ -32,11 +35,11 @@ import ghidra.util.datastruct.WeakValueHashMap;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
public class VariableStorageManagerDB {
public class VariableStorageManagerDB implements VariableStorageManager {
private ProgramDB program;
private AddressMap addrMap;
private ProgramArchitecture arch;
private Lock lock;
private ErrorHandler errorHandler;
private VariableStorageDBAdapter adapter;
@ -47,45 +50,55 @@ public class VariableStorageManagerDB {
/**
* Construct a new variable manager.
* @param handle the database handle.
* @param addrMap the address map
* @param addrMap the address map (required for legacy adpter use only)
* @param openMode the open mode
* @param errorHandler database error handler
* @param lock the program synchronization lock
* @param monitor the task monitor.
* @throws IOException if a database error occurs.
* @throws VersionException if the table version is different from this adapter.
* @throws IOException
* @throws IOException if an IO error occurs
* @throws CancelledException if the user cancels the upgrade.
*/
public VariableStorageManagerDB(DBHandle handle, AddressMap addrMap, int openMode, Lock lock,
TaskMonitor monitor) throws VersionException, IOException, CancelledException {
this.addrMap = addrMap;
public VariableStorageManagerDB(DBHandle handle, AddressMap addrMap, int openMode,
ErrorHandler errorHandler, Lock lock, TaskMonitor monitor)
throws VersionException, IOException, CancelledException {
this.errorHandler = errorHandler;
this.lock = lock;
adapter = VariableStorageDBAdapter.getAdapter(handle, openMode, addrMap, monitor);
}
/**
* Set program architecture.
* @param arch program architecture
*/
public void setProgramArchitecture(ProgramArchitecture arch) {
this.arch = arch;
}
/**
* Delete the DB table which correspnds to this variable storage implementation
* @param dbHandle database handle
* @throws IOException if an IO error occurs
*/
public static void delete(DBHandle dbHandle) throws IOException {
dbHandle.deleteTable(VariableStorageDBAdapter.VARIABLE_STORAGE_TABLE_NAME);
}
/**
* Determine if the variable storage manager table already exists
* @param dbHandle database handle
* @return true if storage table exists
*/
public static boolean exists(DBHandle dbHandle) {
return dbHandle.getTable(VariableStorageDBAdapter.VARIABLE_STORAGE_TABLE_NAME) != null;
}
void invalidateCache(boolean all) {
cache.invalidate();
cacheMap.clear();
}
void setProgram(ProgramDB program) {
this.program = program;
}
// private void cacheNamespaceStorage(long namespaceID) throws IOException {
// variableAddrLookupCache.clear();
// storageLookupCache.clear();
// lastNamespaceCacheID = namespaceID;
// Record[] records = adapter.getRecordsForNamespace(namespaceID);
// for (Record rec : records) {
// MyVariableStorage varStore = new MyVariableStorage(rec);
// variableAddrLookupCache.put(varStore.getVariableAddress(), varStore);
// storageLookupCache.put(varStore.getVariableStorage(), varStore);
// }
// }
private MyVariableStorage getMyVariableStorage(Address variableAddr) throws IOException {
if (!variableAddr.isVariableAddress()) {
throw new IllegalArgumentException("Address is not a VariableAddress: " + variableAddr);
@ -103,6 +116,14 @@ public class VariableStorageManagerDB {
return varStore;
}
/**
* Get the list of varnodes associated with the specified variable storage address.
* NOTE: The program architecture and error handler must be set appropriately prior to
* invocation of this method (see {@link #setProgramArchitecture(ProgramArchitecture, ErrorHandler)}.
* @param variableAddr variable storage address
* @return storage varnode list or null if address unknown
* @throws IOException if a database IO error occurs
*/
List<Varnode> getStorageVarnodes(Address variableAddr) throws IOException {
if (!variableAddr.isVariableAddress()) {
throw new IllegalArgumentException();
@ -112,7 +133,7 @@ public class VariableStorageManagerDB {
return null;
}
try {
return VariableStorage.getVarnodes(program.getAddressFactory(),
return VariableStorage.getVarnodes(arch.getAddressFactory(),
rec.getString(VariableStorageDBAdapter.STORAGE_COL));
}
catch (InvalidInputException e) {
@ -121,6 +142,14 @@ public class VariableStorageManagerDB {
return null;
}
/**
* Get the variable storage object associated with the specified variable storage address.
* NOTE: The program architecture and error handler must be set appropriately prior to
* invocation of this method (see {@link #setProgramArchitecture(ProgramArchitecture, ErrorHandler)}.
* @param variableAddr variable storage address
* @return variable storage object or null if address unknown
* @throws IOException if a database IO error occurs
*/
VariableStorage getVariableStorage(Address variableAddr) throws IOException {
MyVariableStorage myStorage = getMyVariableStorage(variableAddr);
if (myStorage != null) {
@ -129,6 +158,17 @@ public class VariableStorageManagerDB {
return null;
}
/**
* Get a variable address for the given storage specification.
* NOTE: The program architecture and error handler must be set appropriately prior to
* invocation of this method (see {@link #setProgramArchitecture(ProgramArchitecture, ErrorHandler)}.
* @param storage variable storage specification
* @param create if true a new variable address will be allocated if needed
* @return variable address which corresponds to the storage specification or null if not found
* and create is false.
* @throws IOException if an IO error occurs
*/
@Override
public Address getVariableStorageAddress(VariableStorage storage, boolean create)
throws IOException {
long hash = storage.getLongHash();
@ -215,7 +255,7 @@ public class VariableStorageManagerDB {
super(cache, record.getKey());
this.record = record;
try {
storage = VariableStorage.deserialize(program,
storage = VariableStorage.deserialize(arch,
record.getString(VariableStorageDBAdapter.STORAGE_COL));
}
catch (InvalidInputException e) {
@ -250,7 +290,7 @@ public class VariableStorageManagerDB {
}
record = rec;
try {
storage = VariableStorage.deserialize(program,
storage = VariableStorage.deserialize(arch,
record.getString(VariableStorageDBAdapter.STORAGE_COL));
}
catch (InvalidInputException e) {
@ -260,7 +300,7 @@ public class VariableStorageManagerDB {
}
}
catch (IOException e) {
program.dbError(e);
errorHandler.dbError(e);
}
finally {
lock.release();
@ -272,10 +312,13 @@ public class VariableStorageManagerDB {
/**
* Perform language translation.
* Following the invocation of this method it is important to ensure that the program
* architecure is adjusted if neccessary.
* Update variable storage specifications to reflect address space and register mappings
* @param translator
* @param monitor
* @throws CancelledException
* @param translator language translator to be used for mapping storage varnodes to new
* architecture.
* @param monitor task monitor
* @throws CancelledException if task is cancelled
*/
public void setLanguage(LanguageTranslator translator, TaskMonitor monitor)
throws CancelledException {
@ -308,7 +351,7 @@ public class VariableStorageManagerDB {
}
}
catch (IOException e) {
program.dbError(e);
errorHandler.dbError(e);
}
finally {
invalidateCache(true);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,6 @@
*/
package ghidra.program.database.util;
import ghidra.program.model.address.Address;
import java.io.IOException;
import db.RecordIterator;
@ -29,11 +26,15 @@ import db.RecordIterator;
public interface DBRecordAdapter {
/**
* Get a record iterator.
* @param start start of iterator
* @param end end of iterator
* @param colIndex index column
* Get a record iterator for all records.
* @return record iterator
* @throws IOException if there was a problem accessing the database
*/
public RecordIterator getRecords(Address start, Address end, int colIndex) throws IOException;
public RecordIterator getRecords() throws IOException;
/**
* Get the number of records in table
* @return total record count
*/
public int getRecordCount();
}

View file

@ -36,7 +36,6 @@ public abstract class AbstractDataType implements DataType {
protected String name;
protected CategoryPath categoryPath;
protected final DataTypeManager dataMgr;
private DataOrganization dataOrganization;
protected AbstractDataType(CategoryPath path, String name, DataTypeManager dataTypeManager) {
if (path == null) {
@ -75,16 +74,8 @@ public abstract class AbstractDataType implements DataType {
@Override
public final DataOrganization getDataOrganization() {
if (dataOrganization != null) {
return dataOrganization;
}
if (dataMgr != null) {
dataOrganization = dataMgr.getDataOrganization();
}
if (dataOrganization == null) {
dataOrganization = DataOrganizationImpl.getDefaultOrganization();
}
return dataOrganization;
return dataMgr != null ? dataMgr.getDataOrganization()
: DataOrganizationImpl.getDefaultOrganization();
}
@Override

View file

@ -56,18 +56,14 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
private static SettingsDefinition[] SETTINGS_DEFS =
{ FormatSettingsDefinition.DEF_HEX, PADDING, ENDIAN, MNEMONIC };
private final boolean signed;
/**
* Constructor
*
* @param name a unique signed/unsigned data-type name (also used as the mnemonic)
* @param signed true if signed, false if unsigned
* @param dtm data-type manager whose data organization should be used
*/
public AbstractIntegerDataType(String name, boolean signed, DataTypeManager dtm) {
public AbstractIntegerDataType(String name, DataTypeManager dtm) {
super(null, name, dtm);
this.signed = signed;
}
/**
@ -86,11 +82,10 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
}
/**
* Determine if this type is signed.
* @return true if this is a signed integer data-type
*/
public boolean isSigned() {
return signed;
}
public abstract boolean isSigned();
@Override
public String getDefaultLabelPrefix() {
@ -134,6 +129,7 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
if (size <= 0) {
return null;
}
boolean signed = isSigned();
DataOrganization dataOrganization = getDataOrganization();
if (size == dataOrganization.getCharSize()) {
return signed ? C_SIGNED_CHAR : C_UNSIGNED_CHAR;
@ -311,7 +307,7 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
boolean negative = bigInt.signum() < 0;
if (negative && (!signed || (format != FormatSettingsDefinition.DECIMAL))) {
if (negative && (!isSigned() || (format != FormatSettingsDefinition.DECIMAL))) {
// force use of unsigned value
bigInt = bigInt.add(BigInteger.valueOf(2).pow(bitLength));
}

View file

@ -0,0 +1,37 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.model.data;
/**
* Base type for unsigned integer data types.
*/
public abstract class AbstractSignedIntegerDataType extends AbstractIntegerDataType {
/**
* Constructor
*
* @param name a signed data-type name (also used as the mnemonic)
* @param dtm data-type manager whose data organization should be used
*/
protected AbstractSignedIntegerDataType(String name, DataTypeManager dtm) {
super(name, dtm);
}
@Override
public final boolean isSigned() {
return true;
}
}

View file

@ -0,0 +1,37 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.model.data;
/**
* Base type for unsigned integer data types.
*/
public abstract class AbstractUnsignedIntegerDataType extends AbstractIntegerDataType {
/**
* Constructor
*
* @param name a unsigned data-type name (also used as the mnemonic)
* @param dtm data-type manager whose data organization should be used
*/
protected AbstractUnsignedIntegerDataType(String name, DataTypeManager dtm) {
super(name, dtm);
}
@Override
public final boolean isSigned() {
return false;
}
}

View file

@ -21,8 +21,8 @@ import org.apache.commons.lang3.StringUtils;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.StringSettingsDefinition;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.ProgramArchitecture;
public class AddressSpaceSettingsDefinition
implements StringSettingsDefinition, TypeDefSettingsDefinition {
@ -118,12 +118,14 @@ public class AddressSpaceSettingsDefinition
@Override
public boolean addPreferredValues(Object settingsOwner, Set<String> set) {
if (settingsOwner instanceof ProgramBasedDataTypeManager) {
ProgramBasedDataTypeManager dtm = (ProgramBasedDataTypeManager) settingsOwner;
AddressFactory addressFactory = dtm.getProgram().getAddressFactory();
for (AddressSpace space : addressFactory.getAllAddressSpaces()) {
if (space.isLoadedMemorySpace()) {
set.add(space.getName());
if (settingsOwner instanceof DataTypeManager) {
DataTypeManager dtm = (DataTypeManager) settingsOwner;
ProgramArchitecture arch = dtm.getProgramArchitecture();
if (arch != null) {
for (AddressSpace space : arch.getAddressFactory().getAllAddressSpaces()) {
if (space.isLoadedMemorySpace()) {
set.add(space.getName());
}
}
}
return true;

View file

@ -20,6 +20,7 @@ import static ghidra.program.model.pcode.ElementId.*;
import java.io.IOException;
import ghidra.program.database.DBStringMapAdapter;
import ghidra.program.model.pcode.Encoder;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
@ -27,9 +28,13 @@ import ghidra.xml.XmlPullParser;
public class BitFieldPackingImpl implements BitFieldPacking {
private boolean useMSConvention = false;
private boolean typeAlignmentEnabled = true;
private int zeroLengthBoundary = 0;
public static final boolean DEFAULT_USE_MS_CONVENTION = false;
public static final boolean DEFAULT_TYPE_ALIGNMENT_ENABLED = true;
public static final int DEFAULT_ZERO_LENGTH_BOUNDARY = 0;
private boolean useMSConvention = DEFAULT_USE_MS_CONVENTION;
private boolean typeAlignmentEnabled = DEFAULT_TYPE_ALIGNMENT_ENABLED;
private int zeroLengthBoundary = DEFAULT_ZERO_LENGTH_BOUNDARY;
@Override
public boolean useMSConvention() {
@ -76,26 +81,81 @@ public class BitFieldPackingImpl implements BitFieldPacking {
}
/**
* Write configuration to a stream as a \<bitfield_packing> element
* @param encoder is the stream encoder
* @throws IOException for errors writing to the underlying stream
* Save the specified bitfield packing options to the specified DB data map.
* @param bitfieldPacking bitfield packing options
* @param dataMap DB data map
* @param keyPrefix key prefix for all map entries
* @throws IOException if an IO error occurs
*/
static void save(BitFieldPacking bitfieldPacking, DBStringMapAdapter dataMap,
String keyPrefix) throws IOException {
boolean useMSConvention = bitfieldPacking.useMSConvention();
if (useMSConvention != DEFAULT_USE_MS_CONVENTION) {
dataMap.put(keyPrefix + "use_MS_convention", Boolean.toString(useMSConvention));
}
boolean typeAlignmentEnabled = bitfieldPacking.isTypeAlignmentEnabled();
if (typeAlignmentEnabled != DEFAULT_TYPE_ALIGNMENT_ENABLED) {
dataMap.put(keyPrefix + "type_alignment_enabled",
Boolean.toString(typeAlignmentEnabled));
}
int zeroLengthBoundary = bitfieldPacking.getZeroLengthBoundary();
if (zeroLengthBoundary != DEFAULT_ZERO_LENGTH_BOUNDARY) {
dataMap.put(keyPrefix + "zero_length_boundary", Integer.toString(zeroLengthBoundary));
}
}
/**
* 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
* @throws IOException if an IO error occurs
*/
static BitFieldPackingImpl restore(DBStringMapAdapter dataMap, String keyPrefix)
throws IOException {
BitFieldPackingImpl bitFieldPacking = new BitFieldPackingImpl();
bitFieldPacking.useMSConvention =
dataMap.getBoolean(keyPrefix + ELEM_USE_MS_CONVENTION.name(),
bitFieldPacking.useMSConvention);
bitFieldPacking.typeAlignmentEnabled = dataMap.getBoolean(
keyPrefix + ELEM_TYPE_ALIGNMENT_ENABLED.name(), bitFieldPacking.typeAlignmentEnabled);
bitFieldPacking.zeroLengthBoundary =
dataMap.getInt(keyPrefix + ELEM_ZERO_LENGTH_BOUNDARY.name(),
bitFieldPacking.zeroLengthBoundary);
return bitFieldPacking;
}
/**
* Output the details of this bitfield packing to a encoded document formatter.
* @param encoder the output document encoder.
* @throws IOException if an IO error occurs while encoding/writing output
*/
public void encode(Encoder encoder) throws IOException {
if (!useMSConvention && typeAlignmentEnabled && zeroLengthBoundary == 0) {
if (useMSConvention == DEFAULT_USE_MS_CONVENTION &&
typeAlignmentEnabled == DEFAULT_TYPE_ALIGNMENT_ENABLED &&
zeroLengthBoundary == DEFAULT_ZERO_LENGTH_BOUNDARY) {
return; // All defaults
}
encoder.openElement(ELEM_BITFIELD_PACKING);
if (useMSConvention) {
if (useMSConvention != DEFAULT_USE_MS_CONVENTION) {
encoder.openElement(ELEM_USE_MS_CONVENTION);
encoder.writeBool(ATTRIB_VALUE, true);
encoder.closeElement(ELEM_USE_MS_CONVENTION);
}
if (!typeAlignmentEnabled) {
if (typeAlignmentEnabled != DEFAULT_TYPE_ALIGNMENT_ENABLED) {
encoder.openElement(ELEM_TYPE_ALIGNMENT_ENABLED);
encoder.writeBool(ATTRIB_VALUE, false);
encoder.closeElement(ELEM_TYPE_ALIGNMENT_ENABLED);
}
if (zeroLengthBoundary != 0) {
if (zeroLengthBoundary != DEFAULT_ZERO_LENGTH_BOUNDARY) {
encoder.openElement(ELEM_ZERO_LENGTH_BOUNDARY);
encoder.writeSignedInteger(ATTRIB_VALUE, zeroLengthBoundary);
encoder.closeElement(ELEM_ZERO_LENGTH_BOUNDARY);
@ -115,13 +175,13 @@ public class BitFieldPackingImpl implements BitFieldPacking {
String name = subel.getName();
String value = subel.getAttribute("value");
if (name.equals("use_MS_convention")) {
if (name.equals(ELEM_USE_MS_CONVENTION.name())) {
useMSConvention = SpecXmlUtils.decodeBoolean(value);
}
else if (name.equals("type_alignment_enabled")) {
else if (name.equals(ELEM_TYPE_ALIGNMENT_ENABLED.name())) {
typeAlignmentEnabled = SpecXmlUtils.decodeBoolean(value);
}
else if (name.equals("zero_length_boundary")) {
else if (name.equals(ELEM_ZERO_LENGTH_BOUNDARY.name())) {
zeroLengthBoundary = SpecXmlUtils.decodeInt(value);
}

View file

@ -26,7 +26,7 @@ import ghidra.program.model.mem.MemoryAccessException;
/**
* Provides a definition of an Ascii byte in a program.
*/
public class BooleanDataType extends AbstractIntegerDataType {
public class BooleanDataType extends AbstractUnsignedIntegerDataType {
private static SettingsDefinition[] SETTINGS_DEFS = {};
@ -40,7 +40,7 @@ public class BooleanDataType extends AbstractIntegerDataType {
}
public BooleanDataType(DataTypeManager dtm) {
super("bool", false, dtm);
super("bool", dtm);
}
@Override

View file

@ -15,24 +15,29 @@
*/
package ghidra.program.model.data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.help.UnsupportedOperationException;
import javax.swing.event.ChangeListener;
import ghidra.framework.ShutdownHookRegistry;
import ghidra.framework.ShutdownPriority;
import ghidra.program.database.symbol.VariableStorageManager;
import ghidra.program.model.lang.ProgramArchitecture;
import ghidra.util.*;
import ghidra.util.classfinder.ClassFilter;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Data type manager for built in types that do not live anywhere except
* in memory.
*/
public class BuiltInDataTypeManager extends StandAloneDataTypeManager {
public final class BuiltInDataTypeManager extends StandAloneDataTypeManager {
// TODO: There appear to be many public methods in DataTypeManagerDB which could potentially modify the
// underlying database - these methods should probably be overridden
@ -64,6 +69,17 @@ public class BuiltInDataTypeManager extends StandAloneDataTypeManager {
initialize();
}
protected final void setProgramArchitecture(ProgramArchitecture programArchitecture,
VariableStorageManager variableStorageMgr, boolean force, TaskMonitor monitor)
throws IOException, CancelledException {
throw new UnsupportedOperationException("program architecture change not permitted");
}
@Override
protected final boolean isArchitectureChangeAllowed() {
return false;
}
@Override
public synchronized int startTransaction(String description) {
if (manager != null) {

View file

@ -20,9 +20,7 @@ import ghidra.program.model.lang.DecompilerLanguage;
/**
* Provides a definition of a Byte within a program.
*/
public class ByteDataType extends AbstractIntegerDataType {
private static final long serialVersionUID = 1L;
public class ByteDataType extends AbstractUnsignedIntegerDataType {
/** A statically defined ByteDataType instance.*/
public final static ByteDataType dataType = new ByteDataType();
@ -32,7 +30,7 @@ public class ByteDataType extends AbstractIntegerDataType {
}
public ByteDataType(DataTypeManager dtm) {
super("byte", false, dtm);
super("byte", dtm);
}
@Override
@ -52,8 +50,9 @@ public class ByteDataType extends AbstractIntegerDataType {
@Override
public String getDecompilerDisplayName(DecompilerLanguage language) {
if (language == DecompilerLanguage.JAVA_LANGUAGE)
if (language == DecompilerLanguage.JAVA_LANGUAGE) {
return "ubyte";
}
return name;
}

View file

@ -26,7 +26,6 @@ import ghidra.util.classfinder.ClassTranslator;
* determined by the data organization of the associated data type manager.
*/
public class CharDataType extends AbstractIntegerDataType implements DataTypeWithCharset {
private final static long serialVersionUID = 1;
static {
ClassTranslator.put("ghidra.program.model.data.AsciiDataType",
@ -54,12 +53,13 @@ public class CharDataType extends AbstractIntegerDataType implements DataTypeWit
this("char", dtm);
}
protected CharDataType(String name, boolean signed, DataTypeManager dtm) {
super(name, signed, dtm);
protected CharDataType(String name, DataTypeManager dtm) {
super(name, dtm);
}
private CharDataType(String name, DataTypeManager dtm) {
super(name, isSignedChar(dtm), dtm);
@Override
public boolean isSigned() {
return getDataOrganization().isSignedChar();
}
@Override
@ -76,12 +76,6 @@ public class CharDataType extends AbstractIntegerDataType implements DataTypeWit
return getLength() != 1;
}
private static boolean isSignedChar(DataTypeManager dtm) {
DataOrganization dataOrganization =
dtm != null ? dtm.getDataOrganization() : DataOrganizationImpl.getDefaultOrganization();
return dataOrganization.isSignedChar();
}
/**
* Returns the C style data-type declaration for this data-type. Null is returned if no
* appropriate declaration exists.

View file

@ -18,7 +18,7 @@ package ghidra.program.model.data;
/**
* Provides a definition of a Double Word within a program.
*/
public class DWordDataType extends AbstractIntegerDataType {
public class DWordDataType extends AbstractUnsignedIntegerDataType {
private static final long serialVersionUID = 1L;
@ -30,7 +30,7 @@ public class DWordDataType extends AbstractIntegerDataType {
}
public DWordDataType(DataTypeManager dtm) {
super("dword", false, dtm);
super("dword", dtm);
}
@Override

View file

@ -164,15 +164,6 @@ public interface DataOrganization {
*/
int getAlignment(DataType dataType);
// /**
// * Determines the offset where the specified data type should be placed to be properly aligned.
// * @param minimumOffset the minimum allowable offset where the data type can be placed.
// * @param dataType the data type
// * @param dtSize the data type's size
// * @return the aligned offset for the data type
// */
// int getAlignmentOffset(int minimumOffset, DataType dataType, int dtSize);
/**
* Determine if this DataOrganization is equivalent to another specific instance
* @param obj is the other instance

View file

@ -21,6 +21,7 @@ import static ghidra.program.model.pcode.ElementId.*;
import java.io.IOException;
import java.util.*;
import ghidra.program.database.DBStringMapAdapter;
import ghidra.program.model.lang.Language;
import ghidra.program.model.pcode.Encoder;
import ghidra.util.exception.NoValueException;
@ -34,26 +35,48 @@ import ghidra.xml.XmlPullParser;
*/
public class DataOrganizationImpl implements DataOrganization {
// NOTE: it is important that defaults match Decompiler defaults
public static final int DEFAULT_MACHINE_ALIGNMENT = 8;
public static final int DEFAULT_DEFAULT_ALIGNMENT = 1;
public static final int DEFAULT_DEFAULT_POINTER_ALIGNMENT = 4;
public static final int DEFAULT_POINTER_SHIFT = 0;
public static final int DEFAULT_POINTER_SIZE = 4;
public static final int DEFAULT_CHAR_SIZE = 1;
public static final boolean DEFAULT_CHAR_IS_SIGNED = true;
public static final int DEFAULT_WIDE_CHAR_SIZE = 2;
public static final int DEFAULT_SHORT_SIZE = 2;
public static final int DEFAULT_INT_SIZE = 4;
public static final int DEFAULT_LONG_SIZE = 4;
public static final int DEFAULT_LONG_LONG_SIZE = 8;
public static final int DEFAULT_FLOAT_SIZE = 4;
public static final int DEFAULT_DOUBLE_SIZE = 8;
public static final int DEFAULT_LONG_DOUBLE_SIZE = 8;
// DBStringMapAdapter save/restore keys
private static final String BIG_ENDIAN_NAME = "big_endian";
private static final String SIGNED_CHAR_TYPE_NAME = "signed_char_type";
private int absoluteMaxAlignment = NO_MAXIMUM_ALIGNMENT;
private int machineAlignment = 8;
private int defaultAlignment = 1;
private int defaultPointerAlignment = 4;
private int machineAlignment = DEFAULT_MACHINE_ALIGNMENT;
private int defaultAlignment = DEFAULT_DEFAULT_ALIGNMENT;
private int defaultPointerAlignment = DEFAULT_DEFAULT_POINTER_ALIGNMENT;
// Default sizes for primitive data types.
private int pointerShift = 0;
private int pointerSize = 4;
private int charSize = 1;
private int wideCharSize = 2;
private int shortSize = 2;
private int integerSize = 4;
private int longSize = 4;
private int longLongSize = 8;
private int floatSize = 4;
private int doubleSize = 8;
private int longDoubleSize = 8;
private int pointerShift = DEFAULT_POINTER_SHIFT;
private int pointerSize = DEFAULT_POINTER_SIZE;
private int charSize = DEFAULT_CHAR_SIZE;
private boolean isSignedChar = DEFAULT_CHAR_IS_SIGNED;
private int wideCharSize = DEFAULT_WIDE_CHAR_SIZE;
private int shortSize = DEFAULT_SHORT_SIZE;
private int integerSize = DEFAULT_INT_SIZE;
private int longSize = DEFAULT_LONG_SIZE;
private int longLongSize = DEFAULT_LONG_LONG_SIZE;
private int floatSize = DEFAULT_FLOAT_SIZE;
private int doubleSize = DEFAULT_DOUBLE_SIZE;
private int longDoubleSize = DEFAULT_LONG_DOUBLE_SIZE;
// Endianess explicitly set and not supported by saveXml/restore
private boolean bigEndian = false;
private boolean isSignedChar = true;
private BitFieldPackingImpl bitFieldPacking = new BitFieldPackingImpl();
@ -86,7 +109,9 @@ public class DataOrganizationImpl implements DataOrganization {
dataOrganization.setSizeAlignment(4, 4);
dataOrganization.setSizeAlignment(8, 4);
if (language != null) {
// NOTE: Ensure that saveXml always saves pointer size
dataOrganization.setPointerSize(language.getDefaultSpace().getPointerSize());
// NOTE: Endianess is not handled by saveXml/restore
dataOrganization.setBigEndian(language.isBigEndian());
}
return dataOrganization;
@ -556,84 +581,300 @@ public class DataOrganizationImpl implements DataOrganization {
return (value2 != 0) ? getGreatestCommonDenominator(value2, value1 % value2) : value1;
}
/**
* Save the specified data organization to the specified DB data map.
* All existing map entries starting with keyPrefix will be removed prior
* to ading the new map entries.
* @param dataOrg data organization
* @param dataMap DB data map
* @param keyPrefix key prefix for all map entries
* @throws IOException if an IO error occurs
*/
public static void save(DataOrganization dataOrg, DBStringMapAdapter dataMap, String keyPrefix)
throws IOException {
for (String key : dataMap.keySet()) {
if (key.startsWith(keyPrefix)) {
dataMap.delete(key);
}
}
if (dataOrg.isBigEndian()) { // default is little-endian
dataMap.put(keyPrefix + BIG_ENDIAN_NAME, Boolean.TRUE.toString());
}
int absoluteMaxAlignment = dataOrg.getAbsoluteMaxAlignment();
if (absoluteMaxAlignment != NO_MAXIMUM_ALIGNMENT) {
dataMap.put(keyPrefix + ELEM_ABSOLUTE_MAX_ALIGNMENT.name(),
Integer.toString(absoluteMaxAlignment));
}
int machineAlignment = dataOrg.getMachineAlignment();
if (machineAlignment != DEFAULT_MACHINE_ALIGNMENT) {
dataMap.put(keyPrefix + ELEM_MACHINE_ALIGNMENT.name(),
Integer.toString(machineAlignment));
}
int defaultAlignment = dataOrg.getDefaultAlignment();
if (defaultAlignment != DEFAULT_DEFAULT_ALIGNMENT) {
dataMap.put(keyPrefix + ELEM_DEFAULT_ALIGNMENT.name(),
Integer.toString(defaultAlignment));
}
int defaultPointerAlignment = dataOrg.getDefaultPointerAlignment();
if (defaultPointerAlignment != DEFAULT_DEFAULT_POINTER_ALIGNMENT) {
dataMap.put(keyPrefix + ELEM_DEFAULT_POINTER_ALIGNMENT.name(),
Integer.toString(defaultPointerAlignment));
}
int pointerSize = dataOrg.getPointerSize();
if (pointerSize != DEFAULT_POINTER_SIZE) {
dataMap.put(keyPrefix + ELEM_POINTER_SIZE.name(), Integer.toString(pointerSize));
}
int pointerShift = dataOrg.getPointerShift();
if (pointerShift != DEFAULT_POINTER_SHIFT) {
dataMap.put(keyPrefix + ELEM_POINTER_SHIFT.name(), Integer.toString(pointerShift));
}
boolean isSignedChar = dataOrg.isSignedChar();
if (!isSignedChar) {
// NOTE: This differs from XML element name
dataMap.put(keyPrefix + SIGNED_CHAR_TYPE_NAME, Boolean.toString(isSignedChar));
}
int charSize = dataOrg.getCharSize();
if (charSize != DEFAULT_CHAR_SIZE) {
dataMap.put(keyPrefix + ELEM_CHAR_SIZE.name(), Integer.toString(charSize));
}
int wideCharSize = dataOrg.getWideCharSize();
if (wideCharSize != DEFAULT_WIDE_CHAR_SIZE) {
dataMap.put(keyPrefix + ELEM_WCHAR_SIZE.name(), Integer.toString(wideCharSize));
}
int shortSize = dataOrg.getShortSize();
if (shortSize != DEFAULT_SHORT_SIZE) {
dataMap.put(keyPrefix + ELEM_SHORT_SIZE.name(), Integer.toString(shortSize));
}
int integerSize = dataOrg.getIntegerSize();
if (integerSize != DEFAULT_INT_SIZE) {
dataMap.put(keyPrefix + ELEM_INTEGER_SIZE.name(), Integer.toString(integerSize));
}
int longSize = dataOrg.getLongSize();
if (longSize != DEFAULT_LONG_SIZE) {
dataMap.put(keyPrefix + ELEM_LONG_SIZE.name(), Integer.toString(longSize));
}
int longLongSize = dataOrg.getLongLongSize();
if (longLongSize != DEFAULT_LONG_LONG_SIZE) {
dataMap.put(keyPrefix + ELEM_LONG_LONG_SIZE.name(), Integer.toString(longLongSize));
}
int floatSize = dataOrg.getFloatSize();
if (floatSize != DEFAULT_FLOAT_SIZE) {
dataMap.put(keyPrefix + ELEM_FLOAT_SIZE.name(), Integer.toString(floatSize));
}
int doubleSize = dataOrg.getDoubleSize();
if (doubleSize != DEFAULT_DOUBLE_SIZE) {
dataMap.put(keyPrefix + ELEM_DOUBLE_SIZE.name(), Integer.toString(doubleSize));
}
int longDoubleSize = dataOrg.getLongDoubleSize();
if (longDoubleSize != DEFAULT_LONG_DOUBLE_SIZE) {
dataMap.put(keyPrefix + ELEM_LONG_DOUBLE_SIZE.name(), Integer.toString(longDoubleSize));
}
for (int size : dataOrg.getSizes()) {
try {
String key = keyPrefix + ELEM_SIZE_ALIGNMENT_MAP.name() + "." + size;
dataMap.put(key, Integer.toString(dataOrg.getSizeAlignment(size)));
}
catch (NoValueException e) {
// skip entry
}
}
BitFieldPackingImpl.save(dataOrg.getBitFieldPacking(), dataMap,
keyPrefix + ELEM_BITFIELD_PACKING.name() + ".");
}
/**
* 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
* @throws IOException if an IO error occurs
*/
public static DataOrganizationImpl restore(DBStringMapAdapter dataMap, String keyPrefix)
throws IOException {
DataOrganizationImpl dataOrg = new DataOrganizationImpl();
dataOrg.bigEndian = dataMap.getBoolean(BIG_ENDIAN_NAME, false);
dataOrg.absoluteMaxAlignment =
dataMap.getInt(keyPrefix + ELEM_ABSOLUTE_MAX_ALIGNMENT.name(),
dataOrg.absoluteMaxAlignment);
dataOrg.machineAlignment =
dataMap.getInt(keyPrefix + ELEM_MACHINE_ALIGNMENT.name(), dataOrg.machineAlignment);
dataOrg.defaultAlignment =
dataMap.getInt(keyPrefix + ELEM_DEFAULT_ALIGNMENT.name(), dataOrg.defaultAlignment);
dataOrg.defaultPointerAlignment =
dataMap.getInt(keyPrefix + ELEM_DEFAULT_POINTER_ALIGNMENT.name(),
dataOrg.defaultPointerAlignment);
dataOrg.pointerSize =
dataMap.getInt(keyPrefix + ELEM_POINTER_SIZE.name(), dataOrg.pointerSize);
dataOrg.pointerShift =
dataMap.getInt(keyPrefix + ELEM_POINTER_SHIFT.name(), dataOrg.pointerShift);
dataOrg.isSignedChar =
dataMap.getBoolean(keyPrefix + SIGNED_CHAR_TYPE_NAME, dataOrg.isSignedChar);
dataOrg.charSize = dataMap.getInt(keyPrefix + ELEM_CHAR_SIZE.name(), dataOrg.charSize);
dataOrg.wideCharSize =
dataMap.getInt(keyPrefix + ELEM_WCHAR_SIZE.name(), dataOrg.wideCharSize);
dataOrg.shortSize = dataMap.getInt(keyPrefix + ELEM_SHORT_SIZE.name(), dataOrg.shortSize);
dataOrg.integerSize =
dataMap.getInt(keyPrefix + ELEM_INTEGER_SIZE.name(), dataOrg.integerSize);
dataOrg.longSize = dataMap.getInt(keyPrefix + ELEM_LONG_SIZE.name(), dataOrg.longSize);
dataOrg.longLongSize =
dataMap.getInt(keyPrefix + ELEM_LONG_LONG_SIZE.name(), dataOrg.longLongSize);
dataOrg.floatSize = dataMap.getInt(keyPrefix + ELEM_FLOAT_SIZE.name(), dataOrg.floatSize);
dataOrg.doubleSize =
dataMap.getInt(keyPrefix + ELEM_DOUBLE_SIZE.name(), dataOrg.doubleSize);
dataOrg.longDoubleSize =
dataMap.getInt(keyPrefix + ELEM_LONG_DOUBLE_SIZE.name(), dataOrg.longDoubleSize);
boolean firstEntry = true;
String alignmentMapKeyPrefix = keyPrefix + ELEM_SIZE_ALIGNMENT_MAP.name() + ".";
for (String key : dataMap.keySet()) {
if (!key.startsWith(alignmentMapKeyPrefix)) {
continue;
}
try {
int size = Integer.valueOf(key.substring(alignmentMapKeyPrefix.length()));
int alignment = Integer.valueOf(dataMap.get(key));
if (firstEntry) {
dataOrg.sizeAlignmentMap.clear();
firstEntry = false;
}
dataOrg.sizeAlignmentMap.put(size, alignment);
}
catch (NumberFormatException e) {
// ignore
}
}
dataOrg.bitFieldPacking =
BitFieldPackingImpl.restore(dataMap, keyPrefix + ELEM_BITFIELD_PACKING.name() + ".");
return dataOrg;
}
/**
* Output the details of this data organization to a encoded document formatter.
* @param encoder the output document encoder.
* @throws IOException if an IO error occurs while encoding/writing output
*/
public void encode(Encoder encoder) throws IOException {
encoder.openElement(ELEM_DATA_ORGANIZATION);
// NOTE: endianess intentionally omitted from output
if (absoluteMaxAlignment != NO_MAXIMUM_ALIGNMENT) {
encoder.openElement(ELEM_ABSOLUTE_MAX_ALIGNMENT);
encoder.writeSignedInteger(ATTRIB_VALUE, absoluteMaxAlignment);
encoder.closeElement(ELEM_ABSOLUTE_MAX_ALIGNMENT);
}
if (machineAlignment != 8) {
if (machineAlignment != DEFAULT_MACHINE_ALIGNMENT) {
encoder.openElement(ELEM_MACHINE_ALIGNMENT);
encoder.writeSignedInteger(ATTRIB_VALUE, machineAlignment);
encoder.closeElement(ELEM_MACHINE_ALIGNMENT);
}
if (defaultAlignment != 1) {
if (defaultAlignment != DEFAULT_DEFAULT_ALIGNMENT) {
encoder.openElement(ELEM_DEFAULT_ALIGNMENT);
encoder.writeSignedInteger(ATTRIB_VALUE, defaultAlignment);
encoder.closeElement(ELEM_DEFAULT_ALIGNMENT);
}
if (defaultPointerAlignment != 4) {
if (defaultPointerAlignment != DEFAULT_DEFAULT_POINTER_ALIGNMENT) {
encoder.openElement(ELEM_DEFAULT_POINTER_ALIGNMENT);
encoder.writeSignedInteger(ATTRIB_VALUE, defaultPointerAlignment);
encoder.closeElement(ELEM_DEFAULT_POINTER_ALIGNMENT);
}
if (pointerSize != 0) {
encoder.openElement(ELEM_POINTER_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, pointerSize);
encoder.closeElement(ELEM_POINTER_SIZE);
}
if (pointerShift != 0) {
// Always output pointer size
encoder.openElement(ELEM_POINTER_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, pointerSize);
encoder.closeElement(ELEM_POINTER_SIZE);
if (pointerShift != DEFAULT_POINTER_SHIFT) {
encoder.openElement(ELEM_POINTER_SHIFT);
encoder.writeSignedInteger(ATTRIB_VALUE, pointerShift);
encoder.closeElement(ELEM_POINTER_SHIFT);
}
if (!isSignedChar) {
if (isSignedChar != DEFAULT_CHAR_IS_SIGNED) {
encoder.openElement(ELEM_CHAR_TYPE);
encoder.writeBool(ATTRIB_SIGNED, false);
encoder.writeBool(ATTRIB_SIGNED, isSignedChar);
encoder.closeElement(ELEM_CHAR_TYPE);
}
if (charSize != 1) {
if (charSize != DEFAULT_CHAR_SIZE) {
encoder.openElement(ELEM_CHAR_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, charSize);
encoder.closeElement(ELEM_CHAR_SIZE);
}
if (wideCharSize != 2) {
if (wideCharSize != DEFAULT_WIDE_CHAR_SIZE) {
encoder.openElement(ELEM_WCHAR_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, wideCharSize);
encoder.closeElement(ELEM_WCHAR_SIZE);
}
if (shortSize != 2) {
if (shortSize != DEFAULT_SHORT_SIZE) {
encoder.openElement(ELEM_SHORT_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, shortSize);
encoder.closeElement(ELEM_SHORT_SIZE);
}
if (integerSize != 4) {
if (integerSize != DEFAULT_INT_SIZE) {
encoder.openElement(ELEM_INTEGER_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, integerSize);
encoder.closeElement(ELEM_INTEGER_SIZE);
}
if (longSize != 4) {
if (longSize != DEFAULT_LONG_SIZE) {
encoder.openElement(ELEM_LONG_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, longSize);
encoder.closeElement(ELEM_LONG_SIZE);
}
if (longLongSize != 8) {
if (longLongSize != DEFAULT_LONG_LONG_SIZE) {
encoder.openElement(ELEM_LONG_LONG_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, longLongSize);
encoder.closeElement(ELEM_LONG_LONG_SIZE);
}
if (floatSize != 4) {
if (floatSize != DEFAULT_FLOAT_SIZE) {
encoder.openElement(ELEM_FLOAT_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, floatSize);
encoder.closeElement(ELEM_FLOAT_SIZE);
}
if (doubleSize != 8) {
if (doubleSize != DEFAULT_DOUBLE_SIZE) {
encoder.openElement(ELEM_DOUBLE_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, doubleSize);
encoder.closeElement(ELEM_DOUBLE_SIZE);
}
if (longDoubleSize != 8) {
if (longDoubleSize != DEFAULT_LONG_DOUBLE_SIZE) {
encoder.openElement(ELEM_LONG_DOUBLE_SIZE);
encoder.writeSignedInteger(ATTRIB_VALUE, longDoubleSize);
encoder.closeElement(ELEM_LONG_DOUBLE_SIZE);
@ -654,33 +895,39 @@ public class DataOrganizationImpl implements DataOrganization {
}
/**
* Restore settings from an XML stream. This expects to see a \<data_organization> tag.
* The XML is designed to override existing default settings. So this object needs to
* be pre-populated with defaults, typically via getDefaultOrganization().
* Restore settings from an XML stream. This expects to see parser positioned on the
* &lt;data_organization&gt; start tag. The XML is designed to override existing language-specific
* default settings which are pre-populated with {@link #getDefaultOrganization(Language)}. This
* will will ensure that the endianess setting is properly established since it is not included
* in the XML.
* @param parser is the XML stream
*/
public void restoreXml(XmlPullParser parser) {
// NOTE: endianess intentionally omitted from XML.
parser.start();
while (parser.peek().isStart()) {
String name = parser.peek().getName();
if (name.equals("char_type")) {
if (name.equals(ELEM_CHAR_TYPE.name())) {
XmlElement subel = parser.start();
String boolStr = subel.getAttribute("signed");
isSignedChar = SpecXmlUtils.decodeBoolean(boolStr);
String boolStr = subel.getAttribute(ATTRIB_SIGNED.name());
isSignedChar = SpecXmlUtils.decodeBoolean(boolStr, isSignedChar);
parser.end(subel);
continue;
}
else if (name.equals("bitfield_packing")) {
else if (name.equals(ELEM_BITFIELD_PACKING.name())) {
bitFieldPacking.restoreXml(parser);
continue;
}
else if (name.equals("size_alignment_map")) {
else if (name.equals(ELEM_SIZE_ALIGNMENT_MAP.name())) {
XmlElement subel = parser.start();
while (parser.peek().isStart()) {
XmlElement subsubel = parser.start();
int size = SpecXmlUtils.decodeInt(subsubel.getAttribute("size"));
int alignment = SpecXmlUtils.decodeInt(subsubel.getAttribute("alignment"));
int size = SpecXmlUtils.decodeInt(subsubel.getAttribute(ATTRIB_SIZE.name()));
int alignment =
SpecXmlUtils.decodeInt(subsubel.getAttribute(ATTRIB_ALIGNMENT.name()));
sizeAlignmentMap.put(size, alignment);
parser.end(subsubel);
}
@ -689,51 +936,51 @@ public class DataOrganizationImpl implements DataOrganization {
}
XmlElement subel = parser.start();
String value = subel.getAttribute("value");
String value = subel.getAttribute(ATTRIB_VALUE.name());
if (name.equals("absolute_max_alignment")) {
if (name.equals(ELEM_ABSOLUTE_MAX_ALIGNMENT.name())) {
absoluteMaxAlignment = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("machine_alignment")) {
else if (name.equals(ELEM_MACHINE_ALIGNMENT.name())) {
machineAlignment = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("default_alignment")) {
else if (name.equals(ELEM_DEFAULT_ALIGNMENT.name())) {
defaultAlignment = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("default_pointer_alignment")) {
else if (name.equals(ELEM_DEFAULT_POINTER_ALIGNMENT.name())) {
defaultPointerAlignment = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("pointer_size")) {
else if (name.equals(ELEM_POINTER_SIZE.name())) {
pointerSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("pointer_shift")) {
else if (name.equals(ELEM_POINTER_SHIFT.name())) {
pointerShift = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("char_size")) {
else if (name.equals(ELEM_CHAR_SIZE.name())) {
charSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("wchar_size")) {
else if (name.equals(ELEM_WCHAR_SIZE.name())) {
wideCharSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("short_size")) {
else if (name.equals(ELEM_SHORT_SIZE.name())) {
shortSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("integer_size")) {
else if (name.equals(ELEM_INTEGER_SIZE.name())) {
integerSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("long_size")) {
else if (name.equals(ELEM_LONG_SIZE.name())) {
longSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("long_long_size")) {
else if (name.equals(ELEM_LONG_LONG_SIZE.name())) {
longLongSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("float_size")) {
else if (name.equals(ELEM_FLOAT_SIZE.name())) {
floatSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("double_size")) {
else if (name.equals(ELEM_DOUBLE_SIZE.name())) {
doubleSize = SpecXmlUtils.decodeInt(value);
}
else if (name.equals("long_double_size")) {
else if (name.equals(ELEM_LONG_DOUBLE_SIZE.name())) {
longDoubleSize = SpecXmlUtils.decodeInt(value);
}
parser.end(subel);

View file

@ -39,6 +39,7 @@ public class DataTypeArchiveIdDumper implements GhidraLaunchable {
FileWriter writer = new FileWriter(outputFile);
FileDataTypeManager archive = FileDataTypeManager.openFileArchive(archiveFile, false);
archive.reportWarning();
UniversalID universalID2 = archive.getUniversalID();
writer.write("FILE_ID: " + Long.toHexString(universalID2.getValue()));
writer.write("\n");

View file

@ -18,6 +18,11 @@ package ghidra.program.model.data;
import java.util.*;
import db.Transaction;
import ghidra.program.database.SpecExtension;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program;
import ghidra.util.InvalidNameException;
import ghidra.util.UniversalID;
import ghidra.util.exception.CancelledException;
@ -59,6 +64,21 @@ public interface DataTypeManager {
*/
public UniversalID getUniversalID();
/**
* Get the optional program architecture details associated with this archive
* @return program architecture details or null if none
*/
public ProgramArchitecture getProgramArchitecture();
/**
* Get the program architecture information which has been associated with this
* datatype manager. If {@link #getProgramArchitecture()} returns null this method
* may still return information if the program architecture was set on an archive but unable
* to properly instantiate.
* @return program architecture summary if it has been set
*/
public String getProgramArchitectureSummary();
/**
* Returns true if the given category path exists in this datatype manager
* @param path the path
@ -138,6 +158,12 @@ public interface DataTypeManager {
*/
public Iterator<Composite> getAllComposites();
/**
* Returns an iterator over all function definition data types in this manager
* @return the iterator
*/
public Iterator<FunctionDefinition> getAllFunctionDefinitions();
/**
* Begin searching at the root category for all data types with the
* given name. Places all the data types in this data type manager
@ -522,6 +548,13 @@ public interface DataTypeManager {
*/
public DataOrganization getDataOrganization();
/**
* Returns the associated AddressMap used by this datatype manager.
* @return the AddressMap used by this datatype manager or null if
* one has not be established.
*/
public AddressMap getAddressMap();
/**
* Returns a list of source archives not including the builtin or the program's archive.
* @return a list of source archives not including the builtin or the program's archive.
@ -568,4 +601,49 @@ public interface DataTypeManager {
* @return true if BuiltIn Settings are permitted
*/
public boolean allowsDefaultComponentSettings();
/**
* Get the ordered list of known calling convention names. The reserved names
* "unknown" and "default" are not included. The returned collection will include all names
* ever used or resolved by associated {@link Function} and {@link FunctionDefinition} objects,
* even if not currently defined by the associated {@link CompilerSpec} or {@link Program}
* {@link SpecExtension}. To get only those calling conventions formally defined, the method
* {@link CompilerSpec#getCallingConventions()} should be used.
*
* @return all known calling convention names.
*/
public Collection<String> getKnownCallingConventionNames();
/**
* Get the ordered list of defined calling convention names. The reserved names
* "unknown" and "default" are not included. The returned collection may not include all names
* referenced by various functions and function-definitions. This set is generally limited to
* those defined by the associated compiler specification. If this instance does not have an
* assigned architecture the {@link GenericCallingConvention} names will be returned.
* <p>
* For a set of all known names (including those that are not defined by compiler spec)
* see {@link #getKnownCallingConventionNames()}.
*
* @return the set of defined calling convention names.
*/
public Collection<String> getDefinedCallingConventionNames();
/**
* Get the default calling convention's prototype model in this datatype manager if known.
*
* @return the default calling convention prototype model or null.
*/
public PrototypeModel getDefaultCallingConvention();
/**
* Get the prototype model of the calling convention with the specified name from the
* associated compiler specification. If an architecture has not been established this method
* will return null. If {@link Function#DEFAULT_CALLING_CONVENTION_STRING}
* is specified {@link #getDefaultCallingConvention()} will be returned.
*
* @param name the calling convention name
* @return the named function calling convention prototype model or null.
*/
public PrototypeModel getCallingConvention(String name);
}

View file

@ -123,4 +123,11 @@ public interface DataTypeManagerChangeListener {
*/
public void sourceArchiveAdded(final DataTypeManager dataTypeManager,
final SourceArchive sourceArchive);
/**
* Notification that the program architecture associated with the specified
* dataTypeManager has changed.
* @param dataTypeManager data type manager referring to the given source information.
*/
public void programArchitectureChanged(DataTypeManager dataTypeManager);
}

View file

@ -73,4 +73,8 @@ public class DataTypeManagerChangeListenerAdapter implements DataTypeManagerChan
public void sourceArchiveChanged(DataTypeManager dataTypeManager, SourceArchive dataTypeSource) {
}
@Override
public void programArchitectureChanged(DataTypeManager dataTypeManager) {
}
}

View file

@ -15,18 +15,20 @@
*/
package ghidra.program.model.data;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import java.io.IOException;
import java.io.ObjectInputStream;
import javax.swing.SwingUtilities;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
/**
*
* Default implementation for a category change listener that sends out the
* events to its own list of category change listeners.
* Default implementation for a {@link DataTypeManagerChangeListener} that sends out the
* events to its own list of listeners.
*
* NOTE: all listener notifications must be asynchronous within a different thread.
*
*/
public class DataTypeManagerChangeListenerHandler implements DataTypeManagerChangeListener {
@ -51,158 +53,122 @@ public class DataTypeManagerChangeListenerHandler implements DataTypeManagerChan
}
@Override
public void categoryAdded(final DataTypeManager dtm, final CategoryPath path) {
public void categoryAdded(DataTypeManager dtm, CategoryPath path) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryAdded(dtm, path);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryAdded(dtm, path);
}
};
invokeRunnable(r);
});
}
@Override
public void categoryMoved(final DataTypeManager dtm, final CategoryPath oldPath,
final CategoryPath newPath) {
public void categoryMoved(DataTypeManager dtm, CategoryPath oldPath,
CategoryPath newPath) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryMoved(dtm, oldPath, newPath);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryMoved(dtm, oldPath, newPath);
}
};
invokeRunnable(r);
});
}
@Override
public void categoryRemoved(final DataTypeManager dtm, final CategoryPath path) {
public void categoryRemoved(DataTypeManager dtm, CategoryPath path) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryRemoved(dtm, path);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryRemoved(dtm, path);
}
};
invokeRunnable(r);
});
}
@Override
public void categoryRenamed(final DataTypeManager dtm, final CategoryPath oldPath,
final CategoryPath newPath) {
public void categoryRenamed(DataTypeManager dtm, CategoryPath oldPath,
CategoryPath newPath) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryRenamed(dtm, oldPath, newPath);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.categoryRenamed(dtm, oldPath, newPath);
}
};
invokeRunnable(r);
});
}
@Override
public void dataTypeAdded(final DataTypeManager dtm, final DataTypePath path) {
public void dataTypeAdded(DataTypeManager dtm, DataTypePath path) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeAdded(dtm, path);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeAdded(dtm, path);
}
};
invokeRunnable(r);
});
}
@Override
public void dataTypeChanged(final DataTypeManager dtm, final DataTypePath path) {
public void dataTypeChanged(DataTypeManager dtm, DataTypePath path) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeChanged(dtm, path);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeChanged(dtm, path);
}
};
invokeRunnable(r);
});
}
@Override
public void dataTypeMoved(final DataTypeManager dtm, final DataTypePath oldPath,
final DataTypePath newPath) {
public void dataTypeMoved(DataTypeManager dtm, DataTypePath oldPath,
DataTypePath newPath) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeMoved(dtm, oldPath, newPath);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeMoved(dtm, oldPath, newPath);
}
};
invokeRunnable(r);
});
}
@Override
public void dataTypeRemoved(final DataTypeManager dtm, final DataTypePath path) {
public void dataTypeRemoved(DataTypeManager dtm, DataTypePath path) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeRemoved(dtm, path);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeRemoved(dtm, path);
}
};
invokeRunnable(r);
});
}
@Override
public void dataTypeRenamed(final DataTypeManager dtm, final DataTypePath oldPath,
final DataTypePath newPath) {
public void dataTypeRenamed(DataTypeManager dtm, DataTypePath oldPath,
DataTypePath newPath) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeRenamed(dtm, oldPath, newPath);
listener.favoritesChanged(dtm, oldPath, false);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeRenamed(dtm, oldPath, newPath);
listener.favoritesChanged(dtm, oldPath, false);
}
};
invokeRunnable(r);
});
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
@ -220,73 +186,67 @@ public class DataTypeManagerChangeListenerHandler implements DataTypeManagerChan
}
@Override
public void dataTypeReplaced(final DataTypeManager dtm, final DataTypePath oldPath,
final DataTypePath newPath, final DataType newDataType) {
public void dataTypeReplaced(DataTypeManager dtm, DataTypePath oldPath,
DataTypePath newPath, DataType newDataType) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeReplaced(dtm, oldPath, newPath, newDataType);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.dataTypeReplaced(dtm, oldPath, newPath, newDataType);
}
};
invokeRunnable(r);
});
}
@Override
public void favoritesChanged(final DataTypeManager dtm, final DataTypePath path,
final boolean isFavorite) {
public void favoritesChanged(DataTypeManager dtm, DataTypePath path, boolean isFavorite) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.favoritesChanged(dtm, path, isFavorite);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.favoritesChanged(dtm, path, isFavorite);
}
};
invokeRunnable(r);
});
}
@Override
public void sourceArchiveChanged(final DataTypeManager dataTypeManager,
final SourceArchive dataTypeSource) {
public void sourceArchiveChanged(DataTypeManager dataTypeManager,
SourceArchive dataTypeSource) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.sourceArchiveChanged(dataTypeManager, dataTypeSource);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.sourceArchiveChanged(dataTypeManager, dataTypeSource);
}
};
invokeRunnable(r);
});
}
@Override
public void sourceArchiveAdded(final DataTypeManager dataTypeManager,
final SourceArchive dataTypeSource) {
public void sourceArchiveAdded(DataTypeManager dataTypeManager,
SourceArchive dataTypeSource) {
if (listenerList.isEmpty()) {
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.sourceArchiveAdded(dataTypeManager, dataTypeSource);
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.sourceArchiveAdded(dataTypeManager, dataTypeSource);
}
};
invokeRunnable(r);
});
}
public void programArchitectureChanged(DataTypeManager dataTypeManager) {
if (listenerList.isEmpty()) {
return;
}
invokeRunnable(() -> {
for (DataTypeManagerChangeListener listener : listenerList) {
listener.programArchitectureChanged(dataTypeManager);
}
});
}
}

View file

@ -22,6 +22,8 @@ import db.DBConstants;
import generic.jar.ResourceFile;
import ghidra.framework.store.db.PackedDBHandle;
import ghidra.framework.store.db.PackedDatabase;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.Language;
import ghidra.util.InvalidNameException;
import ghidra.util.UniversalID;
import ghidra.util.exception.*;
@ -48,15 +50,21 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
/**
* Construct a new DataTypeFileManager using the default data organization.
* <p>
* <B>NOTE:</B> it may be appropriate to {@link #getWarning() check for warnings} after
* opening an existing archive file prior to use. While an archive will remain useable
* 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
* @throws IOException
* @throws IOException if an IO error occurs
*/
private FileDataTypeManager(ResourceFile packedDbfile, int openMode) throws IOException {
super(validateFilename(packedDbfile), openMode);
file = packedDbfile;
name = getRootName(file.getName());
packedDB = ((PackedDBHandle) dbHandle).getPackedDatabase();
reportWarning();
}
private static ResourceFile validateFilename(ResourceFile packedDbfile) {
@ -70,18 +78,27 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
* Create a new data-type file archive using the default data organization
* @param packedDbfile archive file (filename must end with DataTypeFileManager.SUFFIX)
* @return data-type manager backed by specified packedDbFile
* @throws IOException
* @throws IOException if an IO error occurs
*/
public static FileDataTypeManager createFileArchive(File packedDbfile) throws IOException {
return new FileDataTypeManager(new ResourceFile(packedDbfile), DBConstants.CREATE);
}
/**
* Open an existing data-type file archive using the default data organization
* Open an existing data-type file archive using the default data organization.
* <p>
* <B>NOTE:</B> If archive has an assigned architecture, issues may arise due to a revised or
* missing {@link Language}/{@link CompilerSpec} which will result in a warning but not
* prevent the archive from being opened. Such a warning condition will ne logged and may
* result in missing or stale information for existing datatypes which have architecture related
* data. In some case it may be appropriate to
* {@link FileDataTypeManager#getWarning() check for warnings} on the returned archive
* object prior to its use.
*
* @param packedDbfile archive file (filename must end with DataTypeFileManager.SUFFIX)
* @param openForUpdate if true archive will be open for update
* @return data-type manager backed by specified packedDbFile
* @throws IOException
* @throws IOException if an IO error occurs
*/
public static FileDataTypeManager openFileArchive(File packedDbfile, boolean openForUpdate)
throws IOException {
@ -89,11 +106,20 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
}
/**
* Open an existing data-type file archive using the default data organization
* Open an existing data-type file archive using the default data organization.
* <p>
* <B>NOTE:</B> If archive has an assigned architecture, issues may arise due to a revised or
* missing {@link Language}/{@link CompilerSpec} which will result in a warning but not
* prevent the archive from being opened. Such a warning condition will ne logged and may
* result in missing or stale information for existing datatypes which have architecture related
* data. In some case it may be appropriate to
* {@link FileDataTypeManager#getWarning() check for warnings} on the returned archive
* object prior to its use.
*
* @param packedDbfile archive file (filename must end with DataTypeFileManager.SUFFIX)
* @param openForUpdate if true archive will be open for update
* @return data-type manager backed by specified packedDbFile
* @throws IOException
* @throws IOException if an IO error occurs
*/
public static FileDataTypeManager openFileArchive(ResourceFile packedDbfile,
boolean openForUpdate) throws IOException {

View file

@ -16,7 +16,9 @@
package ghidra.program.model.data;
import ghidra.program.model.listing.FunctionSignature;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.exception.InvalidInputException;
/**
* Defines a function signature for things like function pointers.
@ -49,12 +51,44 @@ public interface FunctionDefinition extends DataType, FunctionSignature {
*/
public void setVarArgs(boolean hasVarArgs);
/**
* Set whether or not this function has a return.
*
* @param hasNoReturn true if this function does not return.
*/
public void setNoReturn(boolean hasNoReturn);
/**
* Set the generic calling convention associated with this function definition.
* <br>
* The total number of unique calling convention names used within a given {@link Program}
* or {@link DataTypeManager} may be limited (e.g., 127). When this limit is exceeded an error
* will be logged and this setting ignored.
*
* @param genericCallingConvention generic calling convention
* @deprecated Use of {@link GenericCallingConvention} is deprecated since arbitrary calling
* convention names are now supported. {@link #setCallingConvention(String)} should be used.
*/
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention);
/**
* Set the calling convention associated with this function definition.
* <br>
* The total number of unique calling convention names used within a given {@link Program}
* or {@link DataTypeManager} may be limited (e.g., 127). When this limit is exceeded an error
* will be logged and this setting ignored.
*
* @param conventionName calling convention name or null. This name is restricted to those
* defined by {@link GenericCallingConvention}, the associated compiler specification.
* The prototype model declaration name form (e.g., "__stdcall") should be specified as it
* appears in a compiler specification (*.cspec). The special "unknown" and "default" names
* are also allowed.
* @throws InvalidInputException if specified conventionName is not defined by
* {@link GenericCallingConvention} or the associated compiler specification if
* datatype manager has an associated program architecture.
*/
public void setCallingConvention(String conventionName) throws InvalidInputException;
/**
* Replace the given argument with another data type
*

View file

@ -19,11 +19,12 @@ import java.util.ArrayList;
import ghidra.docking.settings.Settings;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.lang.PrototypeModel;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.UniversalID;
import ghidra.util.exception.InvalidInputException;
/**
* Definition of a function for things like function pointers.
@ -34,7 +35,8 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
private ParameterDefinition[] params;
private String comment;
private boolean hasVarArgs;
private GenericCallingConvention genericCallingConvention = GenericCallingConvention.unknown;
private boolean hasNoReturn;
private String callingConventionName = CompilerSpec.CALLING_CONVENTION_unknown;
public FunctionDefinitionDataType(String name) {
this(CategoryPath.ROOT, name, null, null);
@ -108,15 +110,9 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
params = paramList.toArray(new ParameterDefinition[paramList.size()]);
hasVarArgs = function.hasVarArgs();
hasNoReturn = function.hasNoReturn();
PrototypeModel prototypeModel = function.getCallingConvention();
if (prototypeModel == null) {
genericCallingConvention = GenericCallingConvention.unknown;
}
else {
genericCallingConvention = prototypeModel.getGenericCallingConvention();
}
callingConventionName = function.getCallingConventionName();
}
private ParameterDefinition getParameterDefinition(Parameter param, boolean useFormalType,
@ -140,7 +136,8 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
setReturnType(rtnType.clone(getDataTypeManager()));
setArguments(sig.getArguments());
hasVarArgs = sig.hasVarArgs();
genericCallingConvention = sig.getGenericCallingConvention();
hasNoReturn = sig.hasNoReturn();
callingConventionName = sig.getCallingConventionName();
}
@Override
@ -169,14 +166,58 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
}
@Override
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention) {
this.genericCallingConvention = genericCallingConvention;
public void setNoReturn(boolean hasNoReturn) {
this.hasNoReturn = hasNoReturn;
}
@Override
public GenericCallingConvention getGenericCallingConvention() {
return genericCallingConvention != null ? genericCallingConvention
: GenericCallingConvention.unknown;
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention) {
this.callingConventionName = genericCallingConvention.getDeclarationName();
}
@Override
public void setCallingConvention(String conventionName) throws InvalidInputException {
if (conventionName == null ||
CompilerSpec.CALLING_CONVENTION_unknown.equals(conventionName)) {
this.callingConventionName = CompilerSpec.CALLING_CONVENTION_unknown;
return;
}
if (CompilerSpec.CALLING_CONVENTION_default.equals(conventionName)) {
this.callingConventionName = CompilerSpec.CALLING_CONVENTION_default;
return;
}
if (GenericCallingConvention
.getGenericCallingConvention(conventionName) != GenericCallingConvention.unknown) {
ProgramArchitecture arch = dataMgr != null ? dataMgr.getProgramArchitecture() : null;
if (arch != null) {
CompilerSpec compilerSpec = arch.getCompilerSpec();
PrototypeModel callingConvention =
compilerSpec.getCallingConvention(conventionName);
if (callingConvention == null) {
throw new InvalidInputException(
"Invalid calling convention name: " + conventionName);
}
}
}
this.callingConventionName = conventionName;
}
@Override
public PrototypeModel getCallingConvention() {
ProgramArchitecture arch = dataMgr != null ? dataMgr.getProgramArchitecture() : null;
if (arch == null) {
return null;
}
CompilerSpec compilerSpec = arch.getCompilerSpec();
return compilerSpec.getCallingConvention(callingConventionName);
}
@Override
public String getCallingConventionName() {
return callingConventionName;
}
@Override
@ -227,11 +268,15 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
@Override
public String getPrototypeString(boolean includeCallingConvention) {
StringBuffer buf = new StringBuffer();
if (includeCallingConvention && hasNoReturn) {
buf.append(NORETURN_DISPLAY_STRING);
buf.append(" ");
}
buf.append((returnType != null ? returnType.getDisplayName() : "void"));
buf.append(" ");
if (includeCallingConvention &&
genericCallingConvention != GenericCallingConvention.unknown) {
buf.append(genericCallingConvention.name());
!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConventionName)) {
buf.append(callingConventionName);
buf.append(" ");
}
buf.append(name);
@ -279,6 +324,11 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
return hasVarArgs;
}
@Override
public boolean hasNoReturn() {
return hasNoReturn;
}
/**
* Compare the comment of the given function signature to my comment.
*
@ -316,7 +366,8 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
(DataTypeUtilities.isSameOrEquivalentDataType(signature.getReturnType(),
this.returnType)) &&
(hasVarArgs == signature.hasVarArgs()) &&
(genericCallingConvention == signature.getGenericCallingConvention())) {
(hasNoReturn == signature.hasNoReturn()) &&
callingConventionName.equals(signature.getCallingConventionName())) {
ParameterDefinition[] args = signature.getArguments();
if (args.length == this.params.length) {
for (int i = 0; i < args.length; i++) {

View file

@ -21,6 +21,10 @@ import ghidra.program.model.lang.CompilerSpec;
* <code>GenericCallingConvention</code> identifies the generic calling convention
* associated with a specific function definition. This can be used to help identify
* the appropriate compiler-specific function prototype (i.e., calling convention).
*
* @deprecated Calling convention name strings should be used instead of this class.
* {@link CompilerSpec} provides constants for those included in this enumeration and other
* setter/getter methods exist for using the string form.
*/
public enum GenericCallingConvention {
@ -76,14 +80,11 @@ public enum GenericCallingConvention {
/**
* Returns the GenericCallingConvention corresponding to the specified
* type string or unknown. Case and underscore prefix is ignored.
* @param callingConvention calling convention name
* @return GenericCallingConvention
* type string or unknown if name is not defined.
* @param callingConvention calling convention declaration name (e.g., "__stdcall")
* @return GenericCallingConvention or {@link #unknown} if not found.
*/
public static GenericCallingConvention getGenericCallingConvention(String callingConvention) {
while (callingConvention.startsWith("_")) {
callingConvention = callingConvention.substring(1);
}
for (GenericCallingConvention value : GenericCallingConvention.values()) {
if (value.name().equalsIgnoreCase(callingConvention)) {
return value;
@ -92,28 +93,6 @@ public enum GenericCallingConvention {
return unknown;
}
/**
* Returns the GenericCallingConvention which is likely to correspond with the
* specified prototype name.
* @param callingConvention compiler specific calling convention name
* @return GenericCallingConvention
*/
public static GenericCallingConvention guessFromName(String callingConvention) {
if (callingConvention == null) {
return unknown;
}
callingConvention = callingConvention.toLowerCase();
for (GenericCallingConvention value : GenericCallingConvention.values()) {
if (value == unknown) {
continue;
}
if (callingConvention.contains(value.name())) {
return value;
}
}
return unknown;
}
/**
* Returns the GenericCallingConvention corresponding to the specified
* ordinal.

View file

@ -18,9 +18,7 @@ package ghidra.program.model.data;
/**
* A fixed size 16 byte signed integer (commonly referred to in C as int128_t)
*/
public class Integer16DataType extends AbstractIntegerDataType {
private static final long serialVersionUID = 1L;
public class Integer16DataType extends AbstractSignedIntegerDataType {
/** A statically defined Integer16DataType instance.*/
public final static Integer16DataType dataType = new Integer16DataType();
@ -30,7 +28,7 @@ public class Integer16DataType extends AbstractIntegerDataType {
}
public Integer16DataType(DataTypeManager dtm) {
super("int16", true, dtm);
super("int16", dtm);
}
@Override

View file

@ -15,9 +15,7 @@
*/
package ghidra.program.model.data;
public class Integer3DataType extends AbstractIntegerDataType {
private static final long serialVersionUID = 1L;
public class Integer3DataType extends AbstractSignedIntegerDataType {
/** A statically defined Integer3DataType instance.*/
public final static Integer3DataType dataType = new Integer3DataType();
@ -27,7 +25,7 @@ public class Integer3DataType extends AbstractIntegerDataType {
}
public Integer3DataType(DataTypeManager dtm) {
super("int3", true, dtm);
super("int3", dtm);
}
@Override

View file

@ -15,9 +15,7 @@
*/
package ghidra.program.model.data;
public class Integer5DataType extends AbstractIntegerDataType {
private static final long serialVersionUID = 1L;
public class Integer5DataType extends AbstractSignedIntegerDataType {
/** A statically defined Integer5DataType instance.*/
public final static Integer5DataType dataType = new Integer5DataType();
@ -27,7 +25,7 @@ public class Integer5DataType extends AbstractIntegerDataType {
}
public Integer5DataType(DataTypeManager dtm) {
super("int5", true, dtm);
super("int5", dtm);
}
@Override

View file

@ -15,9 +15,7 @@
*/
package ghidra.program.model.data;
public class Integer6DataType extends AbstractIntegerDataType {
private static final long serialVersionUID = 1L;
public class Integer6DataType extends AbstractSignedIntegerDataType {
/** A statically defined Integer6DataType instance.*/
public final static Integer6DataType dataType = new Integer6DataType();
@ -27,7 +25,7 @@ public class Integer6DataType extends AbstractIntegerDataType {
}
public Integer6DataType(DataTypeManager dtm) {
super("int6", true, dtm);
super("int6", dtm);
}
@Override

View file

@ -15,9 +15,7 @@
*/
package ghidra.program.model.data;
public class Integer7DataType extends AbstractIntegerDataType {
private static final long serialVersionUID = 1L;
public class Integer7DataType extends AbstractSignedIntegerDataType {
/** A statically defined Integer7DataType instance.*/
public final static Integer7DataType dataType = new Integer7DataType();
@ -27,7 +25,7 @@ public class Integer7DataType extends AbstractIntegerDataType {
}
public Integer7DataType(DataTypeManager dtm) {
super("int7", true, dtm);
super("int7", dtm);
}
@Override

Some files were not shown because too many files have changed in this diff Show more