mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-484: Added overlay spaces to Trace
This commit is contained in:
parent
edf3a85c2d
commit
1c56c454e1
28 changed files with 1269 additions and 616 deletions
|
@ -27,11 +27,12 @@ import generic.depends.DependentService;
|
|||
import generic.depends.err.ServiceConstructionException;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.program.database.ProgramAddressFactory;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.util.DefaultLanguageService;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.address.TraceAddressFactory;
|
||||
import ghidra.trace.database.bookmark.DBTraceBookmarkManager;
|
||||
import ghidra.trace.database.breakpoint.DBTraceBreakpointManager;
|
||||
import ghidra.trace.database.context.DBTraceRegisterContextManager;
|
||||
|
@ -103,6 +104,8 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
@DependentService
|
||||
protected DBTraceModuleManager moduleManager;
|
||||
@DependentService
|
||||
protected DBTraceOverlaySpaceAdapter overlaySpaceAdapter;
|
||||
@DependentService
|
||||
protected DBTraceReferenceManager referenceManager;
|
||||
@DependentService
|
||||
protected DBTraceRegisterContextManager registerContextManager;
|
||||
|
@ -121,7 +124,7 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
|
||||
protected Language baseLanguage;
|
||||
protected CompilerSpec baseCompilerSpec;
|
||||
protected AddressFactory baseAddressFactory;
|
||||
protected TraceAddressFactory baseAddressFactory;
|
||||
|
||||
protected DBTraceChangeSet traceChangeSet;
|
||||
protected boolean recordChanges = false;
|
||||
|
@ -142,7 +145,7 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
this.baseCompilerSpec =
|
||||
baseLanguage.getCompilerSpecByID(baseCompilerSpec.getCompilerSpecID());
|
||||
this.baseAddressFactory =
|
||||
new ProgramAddressFactory(this.baseLanguage, this.baseCompilerSpec);
|
||||
new TraceAddressFactory(this.baseLanguage, this.baseCompilerSpec);
|
||||
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(this, "Create", false)) {
|
||||
initOptions(DBOpenMode.CREATE);
|
||||
|
@ -197,7 +200,7 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
new LanguageID(traceInfo.getString(BASE_LANGUAGE, null)));
|
||||
baseCompilerSpec = baseLanguage.getCompilerSpecByID(
|
||||
new CompilerSpecID(traceInfo.getString(BASE_COMPILER, null)));
|
||||
baseAddressFactory = new ProgramAddressFactory(baseLanguage, baseCompilerSpec);
|
||||
baseAddressFactory = new TraceAddressFactory(baseLanguage, baseCompilerSpec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,9 +221,10 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
if (as == AddressSpace.OTHER_SPACE) {
|
||||
return;
|
||||
}
|
||||
if (baseLanguage.getAddressFactory().getAddressSpace(as.getSpaceID()) != as) {
|
||||
if (baseAddressFactory.getAddressSpace(as.getSpaceID()) != as) {
|
||||
throw new IllegalArgumentException(
|
||||
"AddressSpace '" + as + "' is not in this language: " + getBaseLanguage());
|
||||
"AddressSpace '" + as + "' is not in this trace (language=" + getBaseLanguage() +
|
||||
")");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +251,6 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceAddressPropertyManager createAddressPropertyManager(
|
||||
DBTraceThreadManager threadManager) throws CancelledException, IOException {
|
||||
return createTraceManager("Address Property Manager",
|
||||
|
@ -256,7 +259,6 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceBookmarkManager createBookmarkManager(DBTraceThreadManager threadManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Bookmark Manager",
|
||||
|
@ -265,7 +267,6 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceBreakpointManager createBreakpointManager(DBTraceThreadManager threadManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Breakpoint Manager",
|
||||
|
@ -274,18 +275,17 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceCodeManager createCodeManager(DBTraceThreadManager threadManager,
|
||||
DBTraceLanguageManager languageManager, DBTraceDataTypeManager dataTypeManager,
|
||||
DBTraceReferenceManager referenceManager) throws CancelledException, IOException {
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter, DBTraceReferenceManager referenceManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Code Manager",
|
||||
(openMode, monitor) -> new DBTraceCodeManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this, threadManager, languageManager, dataTypeManager,
|
||||
baseLanguage, this, threadManager, languageManager, dataTypeManager, overlayAdapter,
|
||||
referenceManager));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceCommentAdapter createCommentAdapter(DBTraceThreadManager threadManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Comment Adapter",
|
||||
|
@ -294,7 +294,6 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceDataSettingsAdapter createDataSettingsAdapter(
|
||||
DBTraceThreadManager threadManager) throws CancelledException, IOException {
|
||||
return createTraceManager("Data Settings Adapter",
|
||||
|
@ -311,8 +310,7 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
protected DBTraceEquateManager createEquateManager(
|
||||
@SuppressWarnings("hiding") DBTraceThreadManager threadManager)
|
||||
protected DBTraceEquateManager createEquateManager(DBTraceThreadManager threadManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Equate Manager",
|
||||
(openMode, monitor) -> new DBTraceEquateManager(dbh, openMode, rwLock, monitor,
|
||||
|
@ -328,12 +326,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceMemoryManager createMemoryManager(DBTraceThreadManager threadManager)
|
||||
throws IOException, CancelledException {
|
||||
protected DBTraceMemoryManager createMemoryManager(DBTraceThreadManager threadManager,
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter) throws IOException, CancelledException {
|
||||
return createTraceManager("Memory Manager",
|
||||
(openMode, monitor) -> new DBTraceMemoryManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this, threadManager));
|
||||
baseLanguage, this, threadManager, overlayAdapter));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
|
@ -344,16 +341,22 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceReferenceManager createReferenceManager(DBTraceThreadManager threadManager)
|
||||
protected DBTraceOverlaySpaceAdapter createOverlaySpaceAdapter()
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Reference Manager",
|
||||
(openMode, monitor) -> new DBTraceReferenceManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this, threadManager));
|
||||
return createTraceManager("Overlay Space Adapter",
|
||||
(openMode, monitor) -> new DBTraceOverlaySpaceAdapter(dbh, openMode, rwLock, monitor,
|
||||
this));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
protected DBTraceReferenceManager createReferenceManager(DBTraceThreadManager threadManager,
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter) throws CancelledException, IOException {
|
||||
return createTraceManager("Reference Manager",
|
||||
(openMode, monitor) -> new DBTraceReferenceManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this, threadManager, overlayAdapter));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceRegisterContextManager createRegisterContextManager(
|
||||
DBTraceThreadManager threadManager, DBTraceLanguageManager languageManager)
|
||||
throws CancelledException, IOException {
|
||||
|
@ -363,28 +366,28 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceStackManager createStackManager(DBTraceThreadManager threadManager)
|
||||
throws CancelledException, IOException {
|
||||
protected DBTraceStackManager createStackManager(DBTraceThreadManager threadManager,
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter) throws CancelledException, IOException {
|
||||
return createTraceManager("Stack Manager",
|
||||
(openMode, monitor) -> new DBTraceStackManager(dbh, openMode, rwLock, monitor, this,
|
||||
threadManager));
|
||||
threadManager, overlayAdapter));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
protected DBTraceStaticMappingManager createStaticMappingManager()
|
||||
throws CancelledException, IOException {
|
||||
protected DBTraceStaticMappingManager createStaticMappingManager(
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter) throws CancelledException, IOException {
|
||||
return createTraceManager("Static Mapping Manager", (openMode,
|
||||
monitor) -> new DBTraceStaticMappingManager(dbh, openMode, rwLock, monitor, this));
|
||||
monitor) -> new DBTraceStaticMappingManager(dbh, openMode, rwLock, monitor, this,
|
||||
overlayAdapter));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceSymbolManager createSymbolManager(DBTraceThreadManager threadManager,
|
||||
DBTraceDataTypeManager dataTypeManager) throws CancelledException, IOException {
|
||||
DBTraceDataTypeManager dataTypeManager, DBTraceOverlaySpaceAdapter overlayAdapter)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Symbol Manager",
|
||||
(openMode, monitor) -> new DBTraceSymbolManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this, threadManager, dataTypeManager));
|
||||
baseLanguage, this, threadManager, dataTypeManager, overlayAdapter));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
|
@ -394,7 +397,6 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
@SuppressWarnings("hiding")
|
||||
protected DBTraceTimeManager createTimeManager(DBTraceThreadManager threadManager)
|
||||
throws IOException, CancelledException {
|
||||
return createTraceManager("Time Manager",
|
||||
|
@ -432,7 +434,12 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
return baseAddressFactory;
|
||||
}
|
||||
|
||||
// Internal
|
||||
@Internal
|
||||
public TraceAddressFactory getInternalAddressFactory() {
|
||||
return baseAddressFactory;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public DBTraceAddressPropertyManager getAddressPropertyManager() {
|
||||
return addressPropertyManager;
|
||||
}
|
||||
|
@ -452,12 +459,12 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
return codeManager;
|
||||
}
|
||||
|
||||
// Internal
|
||||
@Internal
|
||||
public DBTraceCommentAdapter getCommentAdapter() {
|
||||
return commentAdapter;
|
||||
}
|
||||
|
||||
// Internal
|
||||
@Internal
|
||||
public DBTraceDataSettingsAdapter getDataSettingsAdapter() {
|
||||
return dataSettingsAdapter;
|
||||
}
|
||||
|
@ -487,6 +494,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
return moduleManager;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() {
|
||||
return overlaySpaceAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceReferenceManager getReferenceManager() {
|
||||
return referenceManager;
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.lang.reflect.Field;
|
|||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -38,9 +39,6 @@ import ghidra.util.database.DBCachedObjectStoreFactory.AbstractDBFieldCodec;
|
|||
|
||||
public enum DBTraceUtils {
|
||||
;
|
||||
public interface DecodesAddresses {
|
||||
Address decodeAddress(int space, long offset);
|
||||
}
|
||||
|
||||
public static class OffsetSnap {
|
||||
public final long offset;
|
||||
|
@ -123,52 +121,6 @@ public enum DBTraceUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static class AddressDBFieldCodec<OT extends DBAnnotatedObject & DecodesAddresses>
|
||||
extends AbstractDBFieldCodec<Address, OT, BinaryField> {
|
||||
|
||||
public AddressDBFieldCodec(Class<OT> objectType, Field field, int column) {
|
||||
super(Address.class, objectType, BinaryField.class, field, column);
|
||||
}
|
||||
|
||||
protected byte[] encode(Address address) {
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
ByteBuffer buf = ByteBuffer.allocate(10);
|
||||
short space = (short) address.getAddressSpace().getSpaceID();
|
||||
buf.putShort(space);
|
||||
long offset = address.getOffset();
|
||||
buf.putLong(offset);
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Address value, BinaryField f) {
|
||||
f.setBinaryData(encode(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStore(OT obj, DBRecord record)
|
||||
throws IllegalArgumentException, IllegalAccessException {
|
||||
record.setBinaryData(column, encode(getValue(obj)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoad(OT obj, DBRecord record)
|
||||
throws IllegalArgumentException, IllegalAccessException {
|
||||
byte[] data = record.getBinaryData(column);
|
||||
if (data == null) {
|
||||
setValue(obj, null);
|
||||
}
|
||||
else {
|
||||
ByteBuffer buf = ByteBuffer.wrap(data);
|
||||
short space = buf.getShort();
|
||||
long offset = buf.getLong();
|
||||
setValue(obj, obj.decodeAddress(space, offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LanguageIDDBFieldCodec<OT extends DBAnnotatedObject>
|
||||
extends AbstractDBFieldCodec<LanguageID, OT, StringField> {
|
||||
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
/* ###
|
||||
* 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.trace.database.address;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceManager;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.database.*;
|
||||
import ghidra.util.database.DBCachedObjectStoreFactory.AbstractDBFieldCodec;
|
||||
import ghidra.util.database.annot.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
|
||||
|
||||
/**
|
||||
* An interface required for any object having a field using {@link AddressDBFieldCodec}.
|
||||
*/
|
||||
public interface DecodesAddresses {
|
||||
/**
|
||||
* Get the space adapter for the trace containing the object
|
||||
*
|
||||
* @return the adapter
|
||||
*/
|
||||
DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for objects having an {@link Address} field.
|
||||
*
|
||||
* <p>
|
||||
* Most managers storing things by address will actually have a table per space, so the address
|
||||
* is encoded only as an offset. However, any other {@link Address} field (not constrained to
|
||||
* the same space) will need to encode the space information as well. This codec can do that.
|
||||
* The object will need to return its trace's space adapter, though.
|
||||
*
|
||||
* @param <OT> the type of object containing the field
|
||||
*/
|
||||
public static class AddressDBFieldCodec<OT extends DBAnnotatedObject & DecodesAddresses>
|
||||
extends AbstractDBFieldCodec<Address, OT, BinaryField> {
|
||||
static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
public AddressDBFieldCodec(Class<OT> objectType, Field field, int column) {
|
||||
super(Address.class, objectType, BinaryField.class, field, column);
|
||||
}
|
||||
|
||||
protected byte[] encode(Address address) {
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
AddressSpace as = address.getAddressSpace();
|
||||
ByteBuffer buf = ByteBuffer.allocate(Byte.BYTES + Short.BYTES + Long.BYTES);
|
||||
if (as instanceof OverlayAddressSpace) {
|
||||
buf.put((byte) 1);
|
||||
OverlayAddressSpace os = (OverlayAddressSpace) as;
|
||||
buf.putShort((short) os.getDatabaseKey());
|
||||
}
|
||||
else {
|
||||
buf.put((byte) 0);
|
||||
buf.putShort((short) as.getSpaceID());
|
||||
}
|
||||
buf.putLong(address.getOffset());
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Address value, BinaryField f) {
|
||||
f.setBinaryData(encode(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStore(OT obj, DBRecord record)
|
||||
throws IllegalArgumentException, IllegalAccessException {
|
||||
record.setBinaryData(column, encode(getValue(obj)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoad(OT obj, DBRecord record)
|
||||
throws IllegalArgumentException, IllegalAccessException {
|
||||
byte[] data = record.getBinaryData(column);
|
||||
if (data == null) {
|
||||
setValue(obj, null);
|
||||
}
|
||||
else {
|
||||
ByteBuffer buf = ByteBuffer.wrap(data);
|
||||
byte overlay = buf.get();
|
||||
final AddressSpace as;
|
||||
if (overlay == 1) {
|
||||
short key = buf.getShort();
|
||||
as = obj.getOverlaySpaceAdapter().spacesByKey.get(key & 0xffffL);
|
||||
}
|
||||
else {
|
||||
short id = buf.getShort();
|
||||
as = obj.getOverlaySpaceAdapter().trace.getInternalAddressFactory()
|
||||
.getAddressSpace(id);
|
||||
}
|
||||
long offset = buf.getLong();
|
||||
setValue(obj, as.getAddress(offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
protected static class DBTraceOverlaySpaceEntry extends DBAnnotatedObject {
|
||||
|
||||
static final String TABLE_NAME = "AddressSpaces";
|
||||
|
||||
static final String NAME_COLUMN_NAME = "Name";
|
||||
static final String BASE_COLUMN_NAME = "Base";
|
||||
|
||||
// NOTE: I don't care to record min/max limit
|
||||
|
||||
@DBAnnotatedColumn(NAME_COLUMN_NAME)
|
||||
static DBObjectColumn NAME_COLUMN;
|
||||
@DBAnnotatedColumn(BASE_COLUMN_NAME)
|
||||
static DBObjectColumn BASE_COLUMN;
|
||||
|
||||
@DBAnnotatedField(column = NAME_COLUMN_NAME, indexed = true)
|
||||
String name;
|
||||
@DBAnnotatedField(column = BASE_COLUMN_NAME)
|
||||
String baseSpace;
|
||||
|
||||
public DBTraceOverlaySpaceEntry(DBCachedObjectStore<?> store, DBRecord record) {
|
||||
super(store, record);
|
||||
}
|
||||
|
||||
void set(String name, String baseSpace) {
|
||||
this.name = name;
|
||||
this.baseSpace = baseSpace;
|
||||
update(NAME_COLUMN, BASE_COLUMN);
|
||||
}
|
||||
}
|
||||
|
||||
protected final DBHandle dbh;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTrace trace;
|
||||
|
||||
protected final DBCachedObjectStore<DBTraceOverlaySpaceEntry> overlayStore;
|
||||
protected final DBCachedObjectIndex<String, DBTraceOverlaySpaceEntry> overlaysByName;
|
||||
|
||||
private final Map<Long, AddressSpace> spacesByKey = new HashMap<>();
|
||||
|
||||
public DBTraceOverlaySpaceAdapter(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, DBTrace trace) throws VersionException, IOException {
|
||||
this.dbh = dbh;
|
||||
this.lock = lock;
|
||||
this.trace = trace;
|
||||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
|
||||
overlayStore = factory.getOrCreateCachedStore(DBTraceOverlaySpaceEntry.TABLE_NAME,
|
||||
DBTraceOverlaySpaceEntry.class, DBTraceOverlaySpaceEntry::new, true);
|
||||
overlaysByName = overlayStore.getIndex(String.class, DBTraceOverlaySpaceEntry.NAME_COLUMN);
|
||||
resyncAddressFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dbError(IOException e) {
|
||||
trace.dbError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCache(boolean all) {
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
overlayStore.invalidateCache();
|
||||
resyncAddressFactory();
|
||||
}
|
||||
}
|
||||
|
||||
protected void resyncAddressFactory() {
|
||||
TraceAddressFactory factory = trace.getInternalAddressFactory();
|
||||
resyncAddressFactory(factory);
|
||||
}
|
||||
|
||||
protected void resyncAddressFactory(TraceAddressFactory factory) {
|
||||
// Clean and rename existing overlays, first
|
||||
for (AddressSpace space : factory.getAllAddressSpaces()) {
|
||||
if (!(space instanceof OverlayAddressSpace)) {
|
||||
continue;
|
||||
}
|
||||
OverlayAddressSpace os = (OverlayAddressSpace) space;
|
||||
DBTraceOverlaySpaceEntry ent = overlayStore.getObjectAt(os.getDatabaseKey());
|
||||
if (ent == null) {
|
||||
spacesByKey.remove(os.getDatabaseKey());
|
||||
factory.removeOverlaySpace(os.getName());
|
||||
}
|
||||
else if (!os.getName().equals(ent.name)) {
|
||||
factory.removeOverlaySpace(os.getName());
|
||||
os.setName(ent.name);
|
||||
try {
|
||||
factory.addOverlayAddressSpace(os);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
throw new AssertionError(); // I just removed it
|
||||
}
|
||||
}
|
||||
// else it's already in sync
|
||||
}
|
||||
// Add missing overlays
|
||||
for (DBTraceOverlaySpaceEntry ent : overlayStore.asMap().values()) {
|
||||
AddressSpace exists = factory.getAddressSpace(ent.name);
|
||||
if (exists != null) {
|
||||
// it's already in sync and/or its a physical space
|
||||
continue;
|
||||
}
|
||||
AddressSpace baseSpace = factory.getAddressSpace(ent.baseSpace);
|
||||
try {
|
||||
OverlayAddressSpace space = factory.addOverlayAddressSpace(ent.name, true,
|
||||
baseSpace, baseSpace.getMinAddress().getOffset(),
|
||||
baseSpace.getMaxAddress().getOffset());
|
||||
space.setDatabaseKey(ent.getKey());
|
||||
spacesByKey.put(space.getDatabaseKey(), space);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new AssertionError(); // Name should be validated already, no?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AddressSpace createOverlayAddressSpace(String name, AddressSpace base)
|
||||
throws DuplicateNameException {
|
||||
// TODO: Exclusive lock?
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
TraceAddressFactory factory = trace.getInternalAddressFactory();
|
||||
if (factory.getAddressSpace(name) != null) {
|
||||
throw new DuplicateNameException("Address space " + name + " already exists.");
|
||||
}
|
||||
|
||||
OverlayAddressSpace space =
|
||||
factory.addOverlayAddressSpace(name, true, base, base.getMinAddress().getOffset(),
|
||||
base.getMaxAddress().getOffset());
|
||||
// Only if it succeeds do we store the record
|
||||
DBTraceOverlaySpaceEntry ent = overlayStore.create();
|
||||
ent.set(space.getName(), base.getName());
|
||||
return space;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteOverlayAddressSpace(String name) {
|
||||
// TODO: Exclusive lock?
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
DBTraceOverlaySpaceEntry exists = overlaysByName.getOne(name);
|
||||
if (exists == null) {
|
||||
throw new NoSuchElementException(name);
|
||||
}
|
||||
overlayStore.delete(exists);
|
||||
TraceAddressFactory factory = trace.getInternalAddressFactory();
|
||||
factory.removeOverlaySpace(name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* ###
|
||||
* 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.trace.database.address;
|
||||
|
||||
import ghidra.program.database.ProgramAddressFactory;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.address.OverlayAddressSpace;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class TraceAddressFactory extends ProgramAddressFactory {
|
||||
|
||||
public TraceAddressFactory(Language language, CompilerSpec compilerSpec) {
|
||||
super(language, compilerSpec);
|
||||
}
|
||||
|
||||
@Override // for peer access
|
||||
protected OverlayAddressSpace addOverlayAddressSpace(String name, boolean preserveName,
|
||||
AddressSpace originalSpace, long minOffset, long maxOffset) {
|
||||
return super.addOverlayAddressSpace(name, preserveName, originalSpace, minOffset,
|
||||
maxOffset);
|
||||
}
|
||||
|
||||
@Override // for peer access
|
||||
protected void addOverlayAddressSpace(OverlayAddressSpace ovSpace)
|
||||
throws DuplicateNameException {
|
||||
super.addOverlayAddressSpace(ovSpace);
|
||||
}
|
||||
|
||||
@Override // for peer access
|
||||
protected void removeOverlaySpace(String name) {
|
||||
super.removeOverlaySpace(name);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.trace.database.listing;
|
||||
|
||||
import static ghidra.lifecycle.Unfinished.*;
|
||||
import static ghidra.lifecycle.Unfinished.TODO;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
@ -37,8 +37,9 @@ import ghidra.program.model.mem.ByteMemBufferImpl;
|
|||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.util.ProgramContextImpl;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.DBTraceUtils.DecodesAddresses;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.database.data.DBTraceDataTypeManager;
|
||||
import ghidra.trace.database.language.DBTraceLanguageManager;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
|
||||
|
@ -109,13 +110,8 @@ public class DBTraceCodeManager
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int space, long offset) {
|
||||
Language lang = manager.languageManager.getLanguageByKey(langKey);
|
||||
if (lang == null) {
|
||||
throw new AssertionError(
|
||||
"Database is corrupt. Missing language with key: " + langKey);
|
||||
}
|
||||
return manager.baseLanguage.getAddressFactory().getAddress(space, offset);
|
||||
public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() {
|
||||
return manager.overlayAdapter;
|
||||
}
|
||||
|
||||
void set(int langKey, byte[] bytes, byte[] context, Address address, boolean delaySlot) {
|
||||
|
@ -175,6 +171,7 @@ public class DBTraceCodeManager
|
|||
|
||||
protected final DBTraceLanguageManager languageManager;
|
||||
protected final DBTraceDataTypeManager dataTypeManager;
|
||||
protected final DBTraceOverlaySpaceAdapter overlayAdapter;
|
||||
protected final DBTraceReferenceManager referenceManager;
|
||||
|
||||
protected final DBCachedObjectStore<DBTraceCodePrototypeEntry> protoStore;
|
||||
|
@ -201,11 +198,12 @@ public class DBTraceCodeManager
|
|||
public DBTraceCodeManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
|
||||
DBTraceThreadManager threadManager, DBTraceLanguageManager languageManager,
|
||||
DBTraceDataTypeManager dataTypeManager, DBTraceReferenceManager referenceManager)
|
||||
throws IOException, VersionException {
|
||||
DBTraceDataTypeManager dataTypeManager, DBTraceOverlaySpaceAdapter overlayAdapter,
|
||||
DBTraceReferenceManager referenceManager) throws IOException, VersionException {
|
||||
super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager);
|
||||
this.languageManager = languageManager;
|
||||
this.dataTypeManager = dataTypeManager;
|
||||
this.overlayAdapter = overlayAdapter;
|
||||
this.referenceManager = referenceManager;
|
||||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
|
|
|
@ -32,6 +32,7 @@ import ghidra.program.model.address.*;
|
|||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
|
||||
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager;
|
||||
import ghidra.trace.database.space.DBTraceDelegatingManager;
|
||||
|
@ -50,16 +51,32 @@ import ghidra.util.task.TaskMonitor;
|
|||
public class DBTraceMemoryManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace, DBTraceMemoryRegisterSpace>
|
||||
implements TraceMemoryManager, DBTraceDelegatingManager<DBTraceMemorySpace> {
|
||||
|
||||
protected static final String NAME = "Memory";
|
||||
|
||||
protected final DBTraceOverlaySpaceAdapter overlayAdapter;
|
||||
|
||||
public DBTraceMemoryManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
|
||||
DBTraceThreadManager threadManager) throws IOException, VersionException {
|
||||
DBTraceThreadManager threadManager, DBTraceOverlaySpaceAdapter overlayAdapter)
|
||||
throws IOException, VersionException {
|
||||
super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager);
|
||||
this.overlayAdapter = overlayAdapter;
|
||||
|
||||
loadSpaces();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressSpace createOverlayAddressSpace(String name, AddressSpace base)
|
||||
throws DuplicateNameException {
|
||||
return overlayAdapter.createOverlayAddressSpace(name, base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteOverlayAddressSpace(String name) {
|
||||
overlayAdapter.deleteOverlayAddressSpace(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceMemorySpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
|
|
|
@ -24,7 +24,10 @@ import com.google.common.collect.Range;
|
|||
import db.DBRecord;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.DBTraceUtils.*;
|
||||
import ghidra.trace.database.DBTraceUtils.URLDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.modules.TraceStaticMapping;
|
||||
import ghidra.util.LockHold;
|
||||
|
@ -73,7 +76,10 @@ public class DBTraceStaticMapping extends DBAnnotatedObject
|
|||
@DBAnnotatedColumn(STATIC_ADDRESS_COLUMN_NAME)
|
||||
static DBObjectColumn STATIC_ADDRESS_COLUMN;
|
||||
|
||||
@DBAnnotatedField(column = TRACE_ADDRESS_COLUMN_NAME, indexed = true, codec = AddressDBFieldCodec.class)
|
||||
@DBAnnotatedField(
|
||||
column = TRACE_ADDRESS_COLUMN_NAME,
|
||||
indexed = true,
|
||||
codec = AddressDBFieldCodec.class)
|
||||
private Address traceAddress;
|
||||
@DBAnnotatedField(column = LENGTH_COLUMN_NAME)
|
||||
private long length;
|
||||
|
@ -134,8 +140,8 @@ public class DBTraceStaticMapping extends DBAnnotatedObject
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int space, long offset) {
|
||||
return manager.trace.getBaseAddressFactory().getAddress(space, offset);
|
||||
public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() {
|
||||
return manager.overlayAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,6 +27,7 @@ import db.DBHandle;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.database.*;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.model.Trace.TraceStaticMappingChangeType;
|
||||
import ghidra.trace.model.modules.TraceConflictedMappingException;
|
||||
import ghidra.trace.model.modules.TraceStaticMappingManager;
|
||||
|
@ -40,6 +41,7 @@ public class DBTraceStaticMappingManager implements TraceStaticMappingManager, D
|
|||
protected final DBHandle dbh;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTrace trace;
|
||||
protected final DBTraceOverlaySpaceAdapter overlayAdapter;
|
||||
|
||||
// TODO: Why doesn't this use the R*-Tree-based store like the others?
|
||||
// Perhaps I thought it was overkill.... Probably should change over.
|
||||
|
@ -49,11 +51,14 @@ public class DBTraceStaticMappingManager implements TraceStaticMappingManager, D
|
|||
protected final Collection<DBTraceStaticMapping> view;
|
||||
|
||||
public DBTraceStaticMappingManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, DBTrace trace) throws VersionException, IOException {
|
||||
TaskMonitor monitor, DBTrace trace, DBTraceOverlaySpaceAdapter overlayAdapter)
|
||||
throws VersionException, IOException {
|
||||
this.dbh = dbh;
|
||||
this.lock = lock;
|
||||
this.trace = trace;
|
||||
|
||||
this.overlayAdapter = overlayAdapter;
|
||||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
mappingStore = factory.getOrCreateCachedStore(DBTraceStaticMapping.TABLE_NAME,
|
||||
DBTraceStaticMapping.class, (s, r) -> new DBTraceStaticMapping(this, s, r), true);
|
||||
|
|
|
@ -58,7 +58,6 @@ import ghidra.trace.model.listing.*;
|
|||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.program.TraceProgramViewMemory;
|
||||
import ghidra.trace.model.symbol.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.*;
|
||||
|
@ -1036,7 +1035,7 @@ public class DBTraceProgramView implements TraceProgramView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TraceProgramViewMemory getMemory() {
|
||||
public DBTraceProgramViewMemory getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ public class DBTraceAddressPropertyManager implements TraceAddressPropertyManage
|
|||
void set(String name, Class<?> valueClass) {
|
||||
this.name = name;
|
||||
this.type = valueClass.getName();
|
||||
update(NAME_COLUMN, TYPE_COLUMN);
|
||||
}
|
||||
|
||||
Class<?> getValueClass() throws ClassNotFoundException {
|
||||
|
@ -189,7 +190,7 @@ public class DBTraceAddressPropertyManager implements TraceAddressPropertyManage
|
|||
}
|
||||
if (valueClass != map.getValueClass()) {
|
||||
throw new TypeMismatchException("Property " + name + " has type " +
|
||||
map.getValueClass() + ", not " + valueClass);
|
||||
map.getValueClass() + ", not " + valueClass);
|
||||
}
|
||||
return (AbstractDBTracePropertyMap<T, ?>) map;
|
||||
}
|
||||
|
@ -222,7 +223,7 @@ public class DBTraceAddressPropertyManager implements TraceAddressPropertyManage
|
|||
}
|
||||
if (!valueClass.isAssignableFrom(map.getValueClass())) {
|
||||
throw new TypeMismatchException("Property " + name + " has type " +
|
||||
map.getValueClass() + ", which does not extend " + valueClass);
|
||||
map.getValueClass() + ", which does not extend " + valueClass);
|
||||
}
|
||||
return (TracePropertyMap<? extends T>) map;
|
||||
}
|
||||
|
@ -245,7 +246,7 @@ public class DBTraceAddressPropertyManager implements TraceAddressPropertyManage
|
|||
}
|
||||
if (!map.getValueClass().isAssignableFrom(valueClass)) {
|
||||
throw new TypeMismatchException("Property " + name + " has type " +
|
||||
map.getValueClass() + ", which is not a super-type of " + valueClass);
|
||||
map.getValueClass() + ", which is not a super-type of " + valueClass);
|
||||
}
|
||||
return (TracePropertyMap<T>) map;
|
||||
}
|
||||
|
|
|
@ -127,11 +127,11 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
|||
@SuppressWarnings("unchecked")
|
||||
protected void loadSpaces() throws VersionException, IOException {
|
||||
for (DBTraceSpaceEntry ent : spaceStore.asMap().values()) {
|
||||
AddressFactory addressFactory = baseLanguage.getAddressFactory();
|
||||
AddressFactory addressFactory = trace.getBaseAddressFactory();
|
||||
AddressSpace space = addressFactory.getAddressSpace(ent.spaceName);
|
||||
if (space == null) {
|
||||
Msg.error(this, "Space " + ent.spaceName + " does not exist in " + baseLanguage +
|
||||
". Perhaps the language changed.");
|
||||
Msg.error(this, "Space " + ent.spaceName + " does not exist in trace (language=" +
|
||||
baseLanguage + ").");
|
||||
}
|
||||
else if (space.isRegisterSpace()) {
|
||||
DBTraceThread thread = threadManager.getThread(ent.threadKey);
|
||||
|
|
|
@ -21,8 +21,10 @@ import java.util.Objects;
|
|||
import db.DBRecord;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.trace.database.DBTraceUtils.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.DBTraceUtils.DecodesAddresses;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.model.Trace.TraceStackChangeType;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
|
@ -69,8 +71,8 @@ public class DBTraceStackFrame extends DBAnnotatedObject
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int space, long offset) {
|
||||
return manager.trace.getBaseAddressFactory().getAddress(space, offset);
|
||||
public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() {
|
||||
return manager.overlayAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,6 +24,7 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceManager;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.stack.DBTraceStack.ThreadSnap;
|
||||
import ghidra.trace.database.thread.DBTraceThread;
|
||||
import ghidra.trace.database.thread.DBTraceThreadManager;
|
||||
|
@ -44,6 +45,7 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager {
|
|||
protected final DBTrace trace;
|
||||
|
||||
protected final DBTraceThreadManager threadManager;
|
||||
protected final DBTraceOverlaySpaceAdapter overlayAdapter;
|
||||
|
||||
protected final DBCachedObjectStore<DBTraceStack> stackStore;
|
||||
protected final DBCachedObjectIndex<ThreadSnap, DBTraceStack> stacksByThreadSnap;
|
||||
|
@ -51,12 +53,14 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager {
|
|||
protected final DBCachedObjectIndex<Address, DBTraceStackFrame> framesByPC;
|
||||
|
||||
public DBTraceStackManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, DBTrace trace, DBTraceThreadManager threadManager)
|
||||
TaskMonitor monitor, DBTrace trace, DBTraceThreadManager threadManager,
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter)
|
||||
throws VersionException, IOException {
|
||||
this.dbh = dbh;
|
||||
this.lock = lock;
|
||||
this.trace = trace;
|
||||
this.threadManager = threadManager;
|
||||
this.overlayAdapter = overlayAdapter;
|
||||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ import ghidra.program.model.symbol.*;
|
|||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.DBTraceUtils.DecodesAddresses;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.database.program.DBTraceProgramView;
|
||||
import ghidra.trace.database.symbol.DBTraceSymbolManager.DBTraceSymbolIDEntry;
|
||||
import ghidra.trace.database.symbol.DBTraceSymbolManager.MySymbolTypes;
|
||||
|
@ -160,8 +161,8 @@ public abstract class AbstractDBTraceSymbol extends DBAnnotatedObject
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int spaceId, long offset) {
|
||||
return manager.trace.getBaseAddressFactory().getAddress(spaceId, offset);
|
||||
public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() {
|
||||
return manager.overlayAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,8 +34,8 @@ import ghidra.program.model.listing.*;
|
|||
import ghidra.program.model.listing.VariableUtilities.VariableConflictHandler;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.DBTraceUtils.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.DBTraceUtils.DecodesAddresses;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.database.bookmark.DBTraceBookmarkType;
|
||||
import ghidra.trace.database.listing.DBTraceCommentAdapter;
|
||||
import ghidra.trace.database.listing.DBTraceData;
|
||||
|
@ -152,11 +152,6 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
thunked = thunkedKey == -1 ? null : manager.functionStore.getObjectAt(thunkedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int spaceId, long offset) {
|
||||
return manager.trace.getBaseAddressFactory().getAddress(spaceId, offset);
|
||||
}
|
||||
|
||||
protected void set(Range<Long> lifespan, Address entryPoint, String name,
|
||||
DBTraceFunctionSymbol thunked, DBTraceNamespaceSymbol parent, SourceType source) {
|
||||
// Recall: Signature source and symbol source are different fields
|
||||
|
|
|
@ -24,8 +24,8 @@ import ghidra.program.model.address.*;
|
|||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.symbol.SymbolType;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.DBTraceUtils.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.DBTraceUtils.DecodesAddresses;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.database.listing.*;
|
||||
import ghidra.trace.database.space.DBTraceSpaceKey;
|
||||
import ghidra.trace.database.thread.DBTraceThread;
|
||||
|
@ -107,11 +107,6 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol
|
|||
this.lifespan = lifespan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int spaceId, long offset) {
|
||||
return manager.trace.getBaseAddressFactory().getAddress(spaceId, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Long> getLifespan() {
|
||||
return lifespan;
|
||||
|
|
|
@ -30,6 +30,7 @@ import ghidra.program.model.lang.Language;
|
|||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager;
|
||||
import ghidra.trace.database.space.DBTraceDelegatingManager;
|
||||
import ghidra.trace.database.symbol.DBTraceReferenceSpace.DBTraceReferenceEntry;
|
||||
|
@ -49,10 +50,14 @@ public class DBTraceReferenceManager extends
|
|||
implements TraceReferenceManager, DBTraceDelegatingManager<DBTraceReferenceSpace> {
|
||||
public static final String NAME = "Reference";
|
||||
|
||||
protected final DBTraceOverlaySpaceAdapter overlayAdapter;
|
||||
|
||||
public DBTraceReferenceManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
|
||||
DBTraceThreadManager threadManager) throws VersionException, IOException {
|
||||
DBTraceThreadManager threadManager, DBTraceOverlaySpaceAdapter overlayAdapter)
|
||||
throws VersionException, IOException {
|
||||
super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager);
|
||||
this.overlayAdapter = overlayAdapter;
|
||||
|
||||
loadSpaces();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,10 @@ import ghidra.program.model.lang.Register;
|
|||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.DBTraceUtils.*;
|
||||
import ghidra.trace.database.DBTraceUtils.RefTypeDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.database.map.*;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
|
||||
|
@ -121,7 +124,10 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
|||
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel);
|
||||
}
|
||||
|
||||
@DBAnnotatedField(column = TO_ADDR_COLUMN_NAME, indexed = true, codec = AddressDBFieldCodec.class)
|
||||
@DBAnnotatedField(
|
||||
column = TO_ADDR_COLUMN_NAME,
|
||||
indexed = true,
|
||||
codec = AddressDBFieldCodec.class)
|
||||
protected Address toAddress;
|
||||
@DBAnnotatedField(column = SYMBOL_ID_COLUMN_NAME, indexed = true)
|
||||
protected long symbolId; // TODO: Is this at the from or to address? I think TO...
|
||||
|
@ -146,8 +152,8 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address decodeAddress(int spaceId, long offset) {
|
||||
return this.space.baseLanguage.getAddressFactory().getAddress(spaceId, offset);
|
||||
public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() {
|
||||
return this.space.manager.overlayAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,6 +30,7 @@ import ghidra.program.model.listing.*;
|
|||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceManager;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter;
|
||||
import ghidra.trace.database.data.DBTraceDataTypeManager;
|
||||
import ghidra.trace.database.map.*;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData;
|
||||
|
@ -426,6 +427,7 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
protected final ReadWriteLock lock;
|
||||
protected final DBTraceThreadManager threadManager;
|
||||
protected final DBTraceDataTypeManager dataTypeManager;
|
||||
protected final DBTraceOverlaySpaceAdapter overlayAdapter;
|
||||
|
||||
protected final DBTraceAddressSnapRangePropertyMap<Long, DBTraceSymbolIDEntry> idMap;
|
||||
|
||||
|
@ -473,12 +475,14 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
|
||||
public DBTraceSymbolManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
|
||||
DBTraceThreadManager threadManager, DBTraceDataTypeManager dataTypeManager)
|
||||
DBTraceThreadManager threadManager, DBTraceDataTypeManager dataTypeManager,
|
||||
DBTraceOverlaySpaceAdapter overlayAdapter)
|
||||
throws VersionException, IOException {
|
||||
this.trace = trace;
|
||||
this.lock = lock;
|
||||
this.threadManager = threadManager;
|
||||
this.dataTypeManager = dataTypeManager;
|
||||
this.overlayAdapter = overlayAdapter;
|
||||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import ghidra.program.model.address.AddressSpace;
|
|||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* A store of memory observations over time in a trace
|
||||
|
@ -33,6 +34,41 @@ import ghidra.trace.model.thread.TraceThread;
|
|||
*/
|
||||
public interface TraceMemoryManager extends TraceMemoryOperations {
|
||||
|
||||
/**
|
||||
* Create a new address space with the given name based upon the given space
|
||||
*
|
||||
* <p>
|
||||
* The purpose of overlay spaces in traces is often to store bytes for things other than memory
|
||||
* or registers. Some targets may expose other byte-based storage, or provide alternative views
|
||||
* of memory.
|
||||
*
|
||||
* <p>
|
||||
* NOTE: This also provides a transitional piece for recording a model (sub)tree directly into a
|
||||
* trace, without mapping to a Ghidra language first. As we experiment with that mode, we will
|
||||
* likely instantiate traces with the "DATA:BE:64:default" language and generate an overlay
|
||||
* space named after the path of each memory being recorded. Of course, the mapping still needs
|
||||
* to occur between the trace and parts of the display and during emulation.
|
||||
*
|
||||
* @param name the name of the new address space
|
||||
* @param base the space after which this is modeled
|
||||
* @return the create space
|
||||
* @throws DuplicateNameException if an address space with the name already exists
|
||||
*/
|
||||
AddressSpace createOverlayAddressSpace(String name, AddressSpace base)
|
||||
throws DuplicateNameException;
|
||||
|
||||
/**
|
||||
* Delete an overlay address space
|
||||
*
|
||||
* <p>
|
||||
* TODO: At the moment, this will not destroy manager spaces created for the deleted address
|
||||
* space. We should assess this behavior, esp. wrt. re-creating the address space later, and
|
||||
* decide whether or not to clean up.
|
||||
*
|
||||
* @param name the name of the address space to delete
|
||||
*/
|
||||
void deleteOverlayAddressSpace(String name);
|
||||
|
||||
/**
|
||||
* Obtain a memory space bound to a particular address space
|
||||
*
|
||||
|
|
|
@ -76,40 +76,72 @@ public class ToyDBTraceBuilder implements AutoCloseable {
|
|||
this.trace = new DBTrace(name, language.getDefaultCompilerSpec(), this);
|
||||
}
|
||||
|
||||
public Address addr(long offset) {
|
||||
return language.getDefaultSpace().getAddress(offset);
|
||||
public Address addr(AddressSpace space, long offset) {
|
||||
return space.getAddress(offset);
|
||||
}
|
||||
|
||||
public Address data(long offset) {
|
||||
return language.getDefaultDataSpace().getAddress(offset);
|
||||
public Address addr(Language lang, long offset) {
|
||||
return addr(lang.getDefaultSpace(), offset);
|
||||
}
|
||||
|
||||
public Address addr(long offset) {
|
||||
return addr(language, offset);
|
||||
}
|
||||
|
||||
public Address addr(TraceGuestLanguage lang, long offset) {
|
||||
return lang.getLanguage().getDefaultSpace().getAddress(offset);
|
||||
}
|
||||
|
||||
public Address data(Language lang, long offset) {
|
||||
return addr(lang.getDefaultDataSpace(), offset);
|
||||
}
|
||||
|
||||
public Address data(long offset) {
|
||||
return data(language, offset);
|
||||
}
|
||||
|
||||
public Address data(TraceGuestLanguage lang, long offset) {
|
||||
return lang.getLanguage().getDefaultDataSpace().getAddress(offset);
|
||||
return data(lang.getLanguage(), offset);
|
||||
}
|
||||
|
||||
public AddressRange range(Address start, Address end) {
|
||||
return new AddressRangeImpl(start, end);
|
||||
}
|
||||
|
||||
public AddressRange range(AddressSpace space, long start, long end) {
|
||||
return range(addr(space, start), addr(space, end));
|
||||
}
|
||||
|
||||
public AddressRange range(Language lang, long start, long end) {
|
||||
return range(lang.getDefaultSpace(), start, end);
|
||||
}
|
||||
|
||||
public AddressRange range(long start, long end) {
|
||||
return new AddressRangeImpl(addr(start), addr(end));
|
||||
return range(language, start, end);
|
||||
}
|
||||
|
||||
public AddressRange range(long singleton) {
|
||||
return range(singleton, singleton);
|
||||
}
|
||||
|
||||
public TraceAddressSnapRange srange(long snap, long start, long end) {
|
||||
return new ImmutableTraceAddressSnapRange(addr(start), addr(end), snap, snap);
|
||||
}
|
||||
|
||||
public AddressRange drng(Language lang, long start, long end) {
|
||||
return range(language.getDefaultDataSpace(), start, end);
|
||||
}
|
||||
|
||||
public AddressRange drng(long start, long end) {
|
||||
return new AddressRangeImpl(data(start), data(end));
|
||||
return drng(language, start, end);
|
||||
}
|
||||
|
||||
public AddressRange range(TraceGuestLanguage lang, long start, long end) {
|
||||
return new AddressRangeImpl(addr(lang, start), addr(lang, end));
|
||||
return range(lang.getLanguage(), start, end);
|
||||
}
|
||||
|
||||
public AddressRange drng(TraceGuestLanguage lang, long start, long end) {
|
||||
return new AddressRangeImpl(data(lang, start), data(lang, end));
|
||||
return drng(lang.getLanguage(), start, end);
|
||||
}
|
||||
|
||||
public AddressSetView set(AddressRange... ranges) {
|
||||
|
|
|
@ -32,6 +32,7 @@ import ghidra.lifecycle.Unfinished;
|
|||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.ContextChangeException;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
|
@ -1823,6 +1824,23 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
|
|||
assertEquals(4, data.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverlaySpaces() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
AddressSpace os = b.trace.getMemoryManager()
|
||||
.createOverlayAddressSpace("test",
|
||||
b.trace.getBaseAddressFactory().getDefaultAddressSpace());
|
||||
DBTraceCodeSpace space = manager.getCodeSpace(os, true);
|
||||
|
||||
b.addInstruction(0, os.getAddress(0x4004), b.language, b.buf(0xf4, 0));
|
||||
|
||||
List<CodeUnit> all = new ArrayList<>();
|
||||
space.definedUnits().get(0, true).forEach(all::add);
|
||||
assertEquals(1, all.size());
|
||||
assertEquals(os, all.get(0).getAddress().getAddressSpace());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test using a context-sensitive language
|
||||
// TODO: Test using delay-slotted instructions (DBTraceCodemanager#instructionMax)
|
||||
// TODO: How are lifespans of delay-slotted instructions bound to thatof the jump?
|
||||
|
|
|
@ -1118,4 +1118,23 @@ public abstract class AbstractDBTraceMemoryManagerTest
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverlaySpaces() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
AddressSpace os = memory.createOverlayAddressSpace("test",
|
||||
b.trace.getBaseAddressFactory().getDefaultAddressSpace());
|
||||
DBTraceMemorySpace space = memory.getMemorySpace(os, true);
|
||||
assertEquals(4, space.putBytes(0, os.getAddress(0x4000), buf(1, 2, 3, 4)));
|
||||
|
||||
ByteBuffer read = ByteBuffer.allocate(4);
|
||||
// This is from original space, not overlay, so should be 0s
|
||||
assertEquals(4, memory.getBytes(0, b.addr(0x4000), read));
|
||||
assertArrayEquals(arr(0, 0, 0, 0), read.array());
|
||||
read.clear();
|
||||
|
||||
assertEquals(4, space.getBytes(0, os.getAddress(0x4000), read));
|
||||
assertArrayEquals(arr(1, 2, 3, 4), read.array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,89 @@
|
|||
/* ###
|
||||
* 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.trace.database.program;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.LanguageNotFoundException;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceOverlappedRegionException;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class DBTraceProgramViewMemoryTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
|
||||
ToyDBTraceBuilder b;
|
||||
|
||||
DBTraceProgramView view;
|
||||
DBTraceProgramViewMemory vmem;
|
||||
DBTraceMemoryManager memory;
|
||||
|
||||
@Before
|
||||
public void setUpTraceProgramViewMemoryTest() throws LanguageNotFoundException, IOException {
|
||||
b = new ToyDBTraceBuilder("Testing", ProgramBuilder._TOY64_BE);
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
b.trace.getTimeManager().createSnapshot("Created");
|
||||
}
|
||||
memory = b.trace.getMemoryManager();
|
||||
// NOTE: First snap has to exist first
|
||||
view = b.trace.getProgramView();
|
||||
vmem = view.getMemory();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDownTraceProgramViewListingTest() {
|
||||
if (b != null) {
|
||||
b.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockInOverlay() throws DuplicateNameException, TraceOverlappedRegionException,
|
||||
AddressOutOfBoundsException {
|
||||
AddressSpace os;
|
||||
DBTraceMemoryRegion io;
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
os = memory.createOverlayAddressSpace("test",
|
||||
b.trace.getBaseAddressFactory().getDefaultAddressSpace());
|
||||
io = (DBTraceMemoryRegion) memory.createRegion(".io", 0, b.range(os, 0x1000, 0x1fff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE, TraceMemoryFlag.VOLATILE);
|
||||
}
|
||||
|
||||
AddressSet asSet = new AddressSet(vmem);
|
||||
assertEquals(b.set(b.range(os, 0x1000, 0x1fff)), asSet);
|
||||
|
||||
MemoryBlock[] blocks = vmem.getBlocks();
|
||||
assertEquals(1, blocks.length);
|
||||
|
||||
MemoryBlock blk = blocks[0];
|
||||
assertSame(blk, vmem.getBlock(io));
|
||||
assertEquals(".io", blk.getName());
|
||||
assertEquals(b.addr(os, 0x1000), blk.getStart());
|
||||
assertEquals(b.addr(os, 0x1fff), blk.getEnd());
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import org.junit.*;
|
|||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
|
@ -555,4 +556,58 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
|||
|
||||
assertEquals(3, manager.getReferenceCountFrom(0, b.addr(0x4000)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverlaySpaces() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
AddressSpace os = b.trace.getMemoryManager()
|
||||
.createOverlayAddressSpace("test",
|
||||
b.trace.getBaseAddressFactory().getDefaultAddressSpace());
|
||||
|
||||
b.addMemoryReference(0, os.getAddress(0x4000), os.getAddress(0x5000));
|
||||
b.addMemoryReference(0, os.getAddress(0x4001), b.addr(0x5001));
|
||||
b.addMemoryReference(0, b.addr(0x4002), os.getAddress(0x5002));
|
||||
}
|
||||
|
||||
File saved = b.save();
|
||||
|
||||
try (@SuppressWarnings("hiding") // On purpose
|
||||
ToyDBTraceBuilder b = new ToyDBTraceBuilder(saved)) {
|
||||
@SuppressWarnings("hiding") // On purpose
|
||||
DBTraceReferenceManager manager = b.trace.getReferenceManager();
|
||||
|
||||
AddressSpace ds = b.trace.getBaseAddressFactory().getDefaultAddressSpace();
|
||||
AddressSpace os = b.trace.getBaseAddressFactory().getAddressSpace("test");
|
||||
assertNotNull(os);
|
||||
|
||||
DBTraceReference ref;
|
||||
|
||||
ref = manager.getReference(0, os.getAddress(0x4000), os.getAddress(0x5000), -1);
|
||||
assertNotNull(ref);
|
||||
assertEquals(os, ref.getFromAddress().getAddressSpace());
|
||||
assertEquals(os, ref.getToAddress().getAddressSpace());
|
||||
|
||||
ref = manager.getReference(0, os.getAddress(0x4001), b.addr(0x5001), -1);
|
||||
assertNotNull(ref);
|
||||
assertEquals(os, ref.getFromAddress().getAddressSpace());
|
||||
assertEquals(ds, ref.getToAddress().getAddressSpace());
|
||||
|
||||
ref = manager.getReference(0, b.addr(0x4002), os.getAddress(0x5002), -1);
|
||||
assertNotNull(ref);
|
||||
assertEquals(ds, ref.getFromAddress().getAddressSpace());
|
||||
assertEquals(os, ref.getToAddress().getAddressSpace());
|
||||
|
||||
assertEquals(0, manager.getReferenceCountFrom(0, b.addr(0x4001)));
|
||||
assertEquals(1, manager.getReferenceCountFrom(0, os.getAddress(0x4001)));
|
||||
|
||||
assertEquals(0, manager.getReferenceCountFrom(0, os.getAddress(0x4002)));
|
||||
assertEquals(1, manager.getReferenceCountFrom(0, b.addr(0x4002)));
|
||||
|
||||
assertEquals(0, manager.getReferenceCountTo(0, os.getAddress(0x5001)));
|
||||
assertEquals(1, manager.getReferenceCountTo(0, b.addr(0x5001)));
|
||||
|
||||
assertEquals(0, manager.getReferenceCountTo(0, b.addr(0x5002)));
|
||||
assertEquals(1, manager.getReferenceCountTo(0, os.getAddress(0x5002)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue