GP-616: Fix 32-bit pointer placement in WoW64 targets.

This commit is contained in:
Dan 2025-04-09 13:27:49 +00:00
parent c75c852001
commit ed48b0e452
37 changed files with 754 additions and 311 deletions

View file

@ -4,9 +4,9 @@
* 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.
@ -335,10 +335,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
}
@DependentService
protected DBTraceDataTypeManager createDataTypeManager()
protected DBTraceDataTypeManager createDataTypeManager(DBTracePlatformManager platformManager)
throws CancelledException, IOException {
return createTraceManager("Data Type Manager", (openMode,
monitor) -> new DBTraceDataTypeManager(dbh, openMode, rwLock, monitor, this));
monitor) -> new DBTraceDataTypeManager(dbh, openMode, rwLock, monitor, this,
platformManager.getHostPlatform()));
}
@DependentService
@ -352,7 +353,7 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
@DependentService
protected DBTracePlatformManager createPlatformManager()
throws CancelledException, IOException {
return createTraceManager("Language Manager",
return createTraceManager("Platform Manager",
(openMode, monitor) -> new DBTracePlatformManager(dbh, openMode, rwLock, monitor,
baseCompilerSpec, this));
}
@ -514,7 +515,7 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
}
@Override
public DBTraceDataTypeManager getDataTypeManager() {
public DBTraceDataTypeManager getBaseDataTypeManager() {
return dataTypeManager;
}
@ -761,8 +762,6 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
}
}
// TODO: Platform option?
public void setExecutablePath(String path) {
getOptions(TRACE_INFO).setString(EXECUTABLE_PATH, path);
}

View file

@ -4,9 +4,9 @@
* 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.
@ -26,11 +26,12 @@ import ghidra.framework.data.OpenMode;
import ghidra.framework.model.DomainFile;
import ghidra.program.database.data.ProgramBasedDataTypeManagerDB;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceManager;
import ghidra.trace.database.guest.DBTraceGuestPlatform;
import ghidra.trace.database.guest.DBTracePlatformManager.DBTraceHostPlatform;
import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.util.InvalidNameException;
import ghidra.util.UniversalID;
@ -41,35 +42,37 @@ import ghidra.util.task.TaskMonitor;
public class DBTraceDataTypeManager extends ProgramBasedDataTypeManagerDB
implements TraceBasedDataTypeManager, DBTraceManager {
protected final ReadWriteLock lock; // TODO: This lock object is not used
/**
* NOTE: This "read-write" lock is actually just a compatibility wrapper around the
* {@link ghidra.util.Lock} for the entire trace database. There was a time when I dreamed of
* using an actual read-write lock (though it's not known if that'd actually achieve any
* appreciable speed up); however, inheriting the existing DataTypeManager implementation
* required its lock to be used throughout the database. Rather than convert all my code (and
* lose the distinction of where I need write vs. read locks), I just wrapped the API. So no,
* this code does not refer to the wrapper, but it does still use the lock. I keep a reference
* to it here in case I ever need it.
*/
protected final ReadWriteLock lock;
protected final DBTrace trace;
protected final InternalTracePlatform platform;
private static final String INSTANCE_TABLE_PREFIX = null; // placeholder only
private static String computePrefix(InternalTracePlatform platform) {
return switch (platform) {
case DBTraceHostPlatform host -> null;
case DBTraceGuestPlatform guest -> "Guest%d_".formatted(guest.getIntKey());
default -> throw new AssertionError();
};
}
public DBTraceDataTypeManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock,
TaskMonitor monitor, DBTrace trace)
TaskMonitor monitor, DBTrace trace, InternalTracePlatform platform)
throws CancelledException, VersionException, IOException {
super(dbh, null, openMode, INSTANCE_TABLE_PREFIX, trace, trace.getLock(), monitor);
super(dbh, null, openMode, computePrefix(platform), trace, trace.getLock(), monitor);
this.lock = lock; // TODO: nothing uses this local lock - not sure what its purpose is
this.trace = trace;
this.platform = platform;
setProgramArchitecture(new ProgramArchitecture() {
@Override
public Language getLanguage() {
return trace.getBaseLanguage();
}
@Override
public CompilerSpec getCompilerSpec() {
return trace.getBaseCompilerSpec();
}
@Override
public AddressFactory getAddressFactory() {
return trace.getBaseAddressFactory();
}
}, null, false, monitor);
setProgramArchitecture(platform, null, false, monitor);
if (openMode == OpenMode.CREATE) {
saveDataOrganization();
@ -106,6 +109,11 @@ public class DBTraceDataTypeManager extends ProgramBasedDataTypeManagerDB
categoryRenamed(CategoryPath.ROOT, getCategory(CategoryPath.ROOT));
}
@Override
public InternalTracePlatform getPlatform() {
return platform;
}
@Override
public void sourceArchiveChanged(UniversalID sourceArchiveID) {
super.sourceArchiveChanged(sourceArchiveID);

View file

@ -22,7 +22,9 @@ import java.util.Map.Entry;
import org.apache.commons.lang3.tuple.Pair;
import db.DBRecord;
import generic.jar.ResourceFile;
import ghidra.app.util.PseudoInstruction;
import ghidra.framework.data.OpenMode;
import ghidra.lifecycle.Internal;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
@ -32,8 +34,10 @@ import ghidra.program.model.mem.MemBuffer;
import ghidra.program.util.DefaultLanguageService;
import ghidra.trace.database.DBTraceUtils.CompilerSpecIDDBFieldCodec;
import ghidra.trace.database.DBTraceUtils.LanguageIDDBFieldCodec;
import ghidra.trace.database.data.DBTraceDataTypeManager;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.guest.TraceGuestPlatform;
import ghidra.trace.model.guest.TraceGuestPlatformMappedRange;
import ghidra.trace.util.*;
@ -156,6 +160,8 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject
new TreeMap<>();
protected final AddressSet guestAddressSet = new AddressSet();
protected DBTraceDataTypeManager dataTypeManager;
public DBTraceGuestPlatform(DBTracePlatformManager manager, DBCachedObjectStore<?> store,
DBRecord record) {
super(store, record);
@ -187,6 +193,12 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject
}
}
protected void loadDataTypeManager(OpenMode openMode, TaskMonitor monitor)
throws CancelledException, VersionException, IOException {
this.dataTypeManager = new DBTraceDataTypeManager(manager.dbh, openMode, manager.lock,
monitor, manager.trace, this);
}
@Override
public Trace getTrace() {
return manager.trace;
@ -235,6 +247,11 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject
return compilerSpec;
}
@Override
public TraceBasedDataTypeManager getDataTypeManager() {
return dataTypeManager;
}
@Override
public void delete(TaskMonitor monitor) throws CancelledException {
manager.deleteGuestPlatform(this, monitor);
@ -284,6 +301,12 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject
return next.getMaxAddress().add(1);
}
private static ResourceFile getSlaFile(Language language) {
SleighLanguageDescription desc =
(SleighLanguageDescription) language.getLanguageDescription();
return desc.getSlaFile();
}
@Override
public TraceGuestPlatformMappedRange addMappedRegisterRange()
throws AddressOverflowException {
@ -292,8 +315,24 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject
if (guestRange == null) {
return null; // No registers, so we're mapped!
}
Address hostMin = manager.computeNextRegisterMin();
long size = guestRange.getLength();
/**
* If the two languages are really the same (have the same .sla file), then map
* registers identically. Such languages differ only in their default contextreg values.
*/
ResourceFile hostSla = getSlaFile(manager.hostPlatform.getLanguage());
ResourceFile guestSla = getSlaFile(getLanguage());
Address hostMin;
if (Objects.equals(hostSla, guestSla)) {
hostMin = manager.hostPlatform.getAddressFactory()
.getRegisterSpace()
.getAddress(guestRange.getMinAddress().getOffset());
}
else {
hostMin = manager.computeNextRegisterMin();
}
return addMappedRange(hostMin, guestRange.getMinAddress(), size);
}
}

View file

@ -29,6 +29,7 @@ import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceManager;
import ghidra.trace.database.guest.DBTraceGuestPlatform.DBTraceGuestLanguage;
import ghidra.trace.model.Trace;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.guest.*;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.trace.util.TraceEvents;
@ -61,7 +62,8 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
protected final DBCachedObjectStore<DBTraceGuestPlatformMappedRange> rangeMappingStore;
protected final InternalTracePlatform hostPlatform = new InternalTracePlatform() {
@Internal
public class DBTraceHostPlatform implements InternalTracePlatform {
@Override
public Trace getTrace() {
return trace;
@ -97,6 +99,11 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
return trace.getBaseAddressFactory();
}
@Override
public TraceBasedDataTypeManager getDataTypeManager() {
return trace.getBaseDataTypeManager();
}
@Override
public AddressSetView getHostAddressSet() {
return trace.getBaseAddressFactory().getAddressSet();
@ -146,11 +153,13 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
public InstructionSet mapGuestInstructionAddressesToHost(InstructionSet set) {
return set;
}
};
}
protected final InternalTracePlatform hostPlatform = new DBTraceHostPlatform();
public DBTracePlatformManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock,
TaskMonitor monitor, CompilerSpec baseCompilerSpec, DBTrace trace)
throws VersionException, IOException {
throws VersionException, IOException, CancelledException {
this.dbh = dbh;
this.lock = lock;
this.baseLanguage = baseCompilerSpec.getLanguage();
@ -169,7 +178,7 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
(s, r) -> new DBTraceGuestPlatformMappedRange(this, s, r), true);
loadLanguages();
loadPlatforms();
loadPlatforms(openMode, monitor);
loadPlatformMappings();
}
@ -179,9 +188,10 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
}
}
protected void loadPlatforms()
throws LanguageNotFoundException, CompilerSpecNotFoundException, VersionException {
protected void loadPlatforms(OpenMode openMode, TaskMonitor monitor)
throws VersionException, CancelledException, IOException {
for (DBTraceGuestPlatform platformEntry : platformStore.asMap().values()) {
platformEntry.loadDataTypeManager(openMode, monitor);
platformsByCompiler.put(platformEntry.getCompilerSpec(), platformEntry);
}
}
@ -263,10 +273,11 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
platformsByCompiler.clear();
try {
loadLanguages();
loadPlatforms();
// TODO: Or IMMUTABLE, if that was the original, and supported
loadPlatforms(OpenMode.UPDATE, TaskMonitor.DUMMY);
loadPlatformMappings();
}
catch (LanguageNotFoundException | CompilerSpecNotFoundException | VersionException e) {
catch (IOException | VersionException | CancelledException e) {
throw new AssertionError(e);
}
}
@ -300,6 +311,12 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
protected DBTraceGuestPlatform doAddGuestPlatform(CompilerSpec compilerSpec) {
DBTraceGuestPlatform platformEntry = platformStore.create();
platformEntry.set(compilerSpec);
try {
platformEntry.loadDataTypeManager(OpenMode.CREATE, TaskMonitor.DUMMY);
}
catch (CancelledException | VersionException | IOException e) {
throw new AssertionError(e);
}
platformsByCompiler.put(compilerSpec, platformEntry);
return platformEntry;
}
@ -330,12 +347,11 @@ public class DBTracePlatformManager implements DBTraceManager, TracePlatformMana
@Override
public InternalTracePlatform getOrAddPlatform(CompilerSpec compilerSpec) {
if (compilerSpec.getCompilerSpecID()
.equals(trace.getBaseCompilerSpec().getCompilerSpecID())) {
return hostPlatform;
}
DBTraceGuestPlatform platform;
try (LockHold hold = LockHold.lock(lock.writeLock())) {
if (trace.getBaseCompilerSpec() == compilerSpec) {
return hostPlatform;
}
DBTraceGuestPlatform exists = platformsByCompiler.get(compilerSpec);
if (exists != null) {
return exists;

View file

@ -18,8 +18,7 @@ package ghidra.trace.database.guest;
import java.util.*;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.*;
import ghidra.program.model.symbol.SourceType;
import ghidra.trace.database.guest.DBTraceGuestPlatform.DBTraceGuestLanguage;
import ghidra.trace.model.guest.TracePlatform;
@ -34,7 +33,7 @@ import ghidra.util.LockHold;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
public interface InternalTracePlatform extends TracePlatform {
public interface InternalTracePlatform extends TracePlatform, ProgramArchitecture {
String REG_MAP_BE = "__reg_map_be__";
String REG_MAP_LE = "__reg_map_le__";
@ -51,6 +50,11 @@ public interface InternalTracePlatform extends TracePlatform {
DBTraceGuestLanguage getLanguageEntry();
@Override
default AddressFactory getAddressFactory() {
return TracePlatform.super.getAddressFactory();
}
@Override
default AddressRange getConventionalRegisterRange(AddressSpace space, Register register) {
AddressRange result = mapGuestToHost(TraceRegisterUtils.rangeForRegister(register));

View file

@ -4,9 +4,9 @@
* 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.
@ -28,8 +28,8 @@ import ghidra.program.model.lang.Language;
import ghidra.program.model.mem.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.data.DBTraceDataTypeManager;
import ghidra.trace.database.guest.DBTraceGuestPlatform;
import ghidra.trace.database.guest.DBTracePlatformManager;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
@ -63,7 +63,7 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
protected final ReadWriteLock lock;
protected final Language baseLanguage;
protected final DBTrace trace;
protected final DBTraceDataTypeManager dataTypeManager;
protected final DBTracePlatformManager platformManager;
protected final DBTraceReferenceManager referenceManager;
protected final AddressRange all;
@ -99,7 +99,7 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace();
this.dataTypeManager = manager.dataTypeManager;
this.platformManager = manager.platformManager;
this.referenceManager = manager.referenceManager;
this.all = new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress());
@ -335,7 +335,7 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
if (reApply) {
try {
definedData.create(Lifespan.span(unitStartSnap, unitEndSnap),
unit.getAddress(), dataType, unit.getLength());
unit.getAddress(), unit.getPlatform(), dataType, unit.getLength());
}
catch (CodeUnitInsertionException e) {
throw new AssertionError(e);

View file

@ -4,9 +4,9 @@
* 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.
@ -92,7 +92,7 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
if (platform == null) {
throw new IOException("Data table is corrupt. Missing platform: " + platformKey);
}
dataType = space.dataTypeManager.getDataType(dataTypeID);
dataType = platform.getDataTypeManager().getDataType(dataTypeID);
if (dataType == null) {
throw new IOException("Data table is corrupt. Missing datatype: " + dataTypeID);
}
@ -128,7 +128,7 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
this.platform = platform;
// Use the stored dataType, not the given one, in case it's different
this.dataType = space.dataTypeManager.getDataType(dataTypeID);
this.dataType = platform.getDataTypeManager().getDataType(dataTypeID);
assert this.dataType != null;
this.defaultSettings = this.dataType.getDefaultSettings();
this.baseDataType = getBaseDataType(this.dataType);

View file

@ -4,9 +4,9 @@
* 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.
@ -20,6 +20,7 @@ import ghidra.program.model.address.AddressRange;
import ghidra.program.model.data.DataType;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -52,15 +53,16 @@ public class DBTraceDefinedDataMemoryView
}
@Override
public DBTraceDataAdapter create(Lifespan lifespan, Address address, DataType dataType,
int length) throws CodeUnitInsertionException {
public DBTraceDataAdapter create(Lifespan lifespan, Address address, TracePlatform platform,
DataType dataType, int length) throws CodeUnitInsertionException {
return delegateWrite(address.getAddressSpace(),
m -> m.create(lifespan, address, dataType, length));
m -> m.create(lifespan, address, platform, dataType, length));
}
@Override
public DBTraceDataAdapter create(Lifespan lifespan, Address address, DataType dataType)
throws CodeUnitInsertionException {
return delegateWrite(address.getAddressSpace(), m -> m.create(lifespan, address, dataType));
public DBTraceDataAdapter create(Lifespan lifespan, Address address, TracePlatform platform,
DataType dataType) throws CodeUnitInsertionException {
return delegateWrite(address.getAddressSpace(),
m -> m.create(lifespan, address, platform, dataType));
}
}

View file

@ -4,9 +4,9 @@
* 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.
@ -19,8 +19,10 @@ import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.model.*;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.trace.util.TraceEvents;
@ -41,9 +43,9 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
}
@Override // NOTE: "Adapter" because using DataType.DEFAULT gives UndefinedDBTraceData
public DBTraceDataAdapter create(Lifespan lifespan, Address address, DataType dataType)
throws CodeUnitInsertionException {
return create(lifespan, address, dataType, dataType.getLength());
public DBTraceDataAdapter create(Lifespan lifespan, Address address, TracePlatform platform,
DataType dataType) throws CodeUnitInsertionException {
return create(lifespan, address, platform, dataType, dataType.getLength());
}
/**
@ -67,9 +69,12 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
}
@Override
// TODO: Probably add language parameter....
public DBTraceDataAdapter create(Lifespan lifespan, Address address, DataType origType,
int origLength) throws CodeUnitInsertionException {
public DBTraceDataAdapter create(Lifespan lifespan, Address address, TracePlatform platform,
DataType origType, int origLength) throws CodeUnitInsertionException {
if (platform.getTrace() != getTrace() ||
!(platform instanceof InternalTracePlatform iPlatform)) {
throw new IllegalArgumentException("Platform is not part of this trace");
}
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
DBTraceMemorySpace memSpace = space.trace.getMemoryManager().get(space, true);
// NOTE: User-given length could be ignored....
@ -97,12 +102,11 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
if (dataType == null) {
throw new CodeUnitInsertionException("Failed to resolve data type");
}
// TODO: This clone may need to be sensitive to the unit's language.
dataType = dataType.clone(space.dataTypeManager);
DataTypeManager dtm = platform.getDataTypeManager();
dataType = dataType.clone(dtm);
if (isFunctionDefinition(dataType)) {
// TODO: This pointer will need to be sensitive to the unit's language.
dataType = new PointerDataType(dataType, dataType.getDataTypeManager());
dataType = new PointerDataType(dataType, dtm);
length = dataType.getLength();
}
else if (dataType instanceof Dynamic) {
@ -112,8 +116,6 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
MemBuffer buffer = memSpace.getBufferAt(startSnap, address);
length = dyn.getLength(buffer, length);
}
// TODO: Do I need to check for Pointer type here?
// Seems purpose is to adjust for language, but I think clone does that already
else {
length = dataType.getLength();
}
@ -143,10 +145,9 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
return space.undefinedData.getAt(startSnap, address);
}
long dataTypeID = space.dataTypeManager.getResolvedID(dataType);
long dataTypeID = dtm.getResolvedID(dataType);
DBTraceData created = mapSpace.put(tasr, null);
// TODO: data units with a guest platform
created.set(space.trace.getPlatformManager().getHostPlatform(), dataTypeID);
created.set(iPlatform, dataTypeID);
// TODO: Explicitly remove undefined from cache, or let weak refs take care of it?
cacheForContaining.notifyNewEntry(tasr.getLifespan(), createdRange, created);

View file

@ -4,9 +4,9 @@
* 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.
@ -15,24 +15,60 @@
*/
package ghidra.trace.database.listing;
import ghidra.lifecycle.Internal;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.Register;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceData;
import ghidra.trace.model.listing.TraceDefinedDataView;
import ghidra.trace.util.TraceRegisterUtils;
@Internal
public interface InternalTraceDefinedDataView
extends TraceDefinedDataView, InternalTraceBaseDefinedUnitsView<TraceData> {
default TracePlatform getPlatformOf(DataType type) {
if (type.getDataTypeManager() instanceof TraceBasedDataTypeManager dtm &&
dtm.getTrace() == getTrace()) {
return dtm.getPlatform();
}
/**
* TODO: Could we seek a nearest match in terms of data organization? Eh. Maybe not, because
* we'd also have to be concerned with whether there's a mapping at the desired address.
*/
return getTrace().getPlatformManager().getHostPlatform();
}
@Override
default TraceData create(TracePlatform platform, Lifespan lifespan, Register register,
DBTraceDataAdapter create(Lifespan lifespan, Address address, TracePlatform platform,
DataType dataType) throws CodeUnitInsertionException;
@Override
DBTraceDataAdapter create(Lifespan lifespan, Address address, TracePlatform platform,
DataType dataType, int length) throws CodeUnitInsertionException;
@Override
default DBTraceDataAdapter create(Lifespan lifespan, Address address, DataType dataType,
int length) throws CodeUnitInsertionException {
return create(lifespan, address, getPlatformOf(dataType), dataType, length);
}
@Override
default DBTraceDataAdapter create(Lifespan lifespan, Address address, DataType dataType)
throws CodeUnitInsertionException {
return create(lifespan, address, getPlatformOf(dataType), dataType);
}
@Override
default DBTraceDataAdapter create(TracePlatform platform, Lifespan lifespan, Register register,
DataType dataType) throws CodeUnitInsertionException {
TraceRegisterUtils.requireByteBound(register);
AddressRange range = platform.getConventionalRegisterRange(getSpace(), register);
return create(lifespan, range.getMinAddress(), dataType, (int) range.getLength());
return create(lifespan, range.getMinAddress(), platform, dataType, (int) range.getLength());
}
}

View file

@ -35,7 +35,6 @@ import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.program.model.util.PropertyMap;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.database.listing.UndefinedDBTraceData;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.database.program.DBTraceProgramViewMemory.RegionEntry;
@ -77,7 +76,6 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
protected final DBTraceProgramView program;
protected final TraceCodeOperations codeOperations;
protected final InternalTracePlatform platform;
protected final DBTraceProgramViewRootModule rootModule;
protected final Map<TraceMemoryRegion, DBTraceProgramViewFragment> fragmentsByRegion =
@ -90,8 +88,7 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
TraceCodeOperations codeOperations) {
this.program = program;
this.codeOperations = codeOperations;
// TODO: Guest platform views?
this.platform = program.trace.getPlatformManager().getHostPlatform();
// TODO: Map addresses when platform is guest?
this.rootModule = new DBTraceProgramViewRootModule(this);
}
@ -751,7 +748,7 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
range, s -> s == TraceMemoryState.KNOWN);
long snap = mostRecent == null ? program.snap : mostRecent.getKey().getY2();
return codeOperations.instructions()
.create(Lifespan.nowOn(snap), addr, platform, prototype, context,
.create(Lifespan.nowOn(snap), addr, program.platform, prototype, context,
forcedLengthOverride);
}
@ -759,7 +756,7 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
public AddressSetView addInstructions(InstructionSet instructionSet, boolean overwrite)
throws CodeUnitInsertionException {
return codeOperations.instructions()
.addInstructionSet(Lifespan.nowOn(program.snap), platform, instructionSet,
.addInstructionSet(Lifespan.nowOn(program.snap), program.platform, instructionSet,
overwrite);
}
@ -767,12 +764,13 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
public Data createData(Address addr, DataType dataType, int length)
throws CodeUnitInsertionException {
return codeOperations.definedData()
.create(Lifespan.nowOn(program.snap), addr, dataType, length);
.create(Lifespan.nowOn(program.snap), addr, program.platform, dataType, length);
}
@Override
public Data createData(Address addr, DataType dataType) throws CodeUnitInsertionException {
return codeOperations.definedData().create(Lifespan.nowOn(program.snap), addr, dataType);
return codeOperations.definedData()
.create(Lifespan.nowOn(program.snap), addr, program.platform, dataType);
}
@Override

View file

@ -45,6 +45,7 @@ import ghidra.program.model.util.AddressSetPropertyMap;
import ghidra.program.model.util.PropertyMapManager;
import ghidra.program.util.*;
import ghidra.trace.database.*;
import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.database.listing.DBTraceDefinedUnitsView;
import ghidra.trace.database.memory.DBTraceMemorySpace;
@ -333,40 +334,40 @@ public class DBTraceProgramView implements TraceProgramView {
range.getX1(), range.getX1(), null, null, null));
}
private void commentChanged(int commentType, TraceAddressSpace space,
private void commentChanged(CommentType commentType, TraceAddressSpace space,
TraceAddressSnapRange range, String oldValue, String newValue) {
DomainObjectEventQueues queues = isVisible(space, range);
if (queues == null) {
return;
}
queues.fireEvent(
new CommentChangeRecord(commentType, range.getX1(), oldValue, newValue));
new CommentChangeRecord(commentType.ordinal(), range.getX1(), oldValue, newValue));
}
private void commentEolChanged(TraceAddressSpace space, TraceAddressSnapRange range,
String oldValue, String newValue) {
commentChanged(CodeUnit.EOL_COMMENT, space, range, oldValue, newValue);
commentChanged(CommentType.EOL, space, range, oldValue, newValue);
}
private void commentPlateChanged(TraceAddressSpace space, TraceAddressSnapRange range,
String oldValue, String newValue) {
commentChanged(CodeUnit.PLATE_COMMENT, space, range, oldValue, newValue);
commentChanged(CommentType.PLATE, space, range, oldValue, newValue);
}
private void commentPostChanged(TraceAddressSpace space, TraceAddressSnapRange range,
String oldValue, String newValue) {
commentChanged(CodeUnit.POST_COMMENT, space, range, oldValue, newValue);
commentChanged(CommentType.POST, space, range, oldValue, newValue);
}
private void commentPreChanged(TraceAddressSpace space, TraceAddressSnapRange range,
String oldValue, String newValue) {
commentChanged(CodeUnit.PRE_COMMENT, space, range, oldValue, newValue);
commentChanged(CommentType.PRE, space, range, oldValue, newValue);
}
private void commentRepeatableChanged(TraceAddressSpace space, TraceAddressSnapRange range,
String oldValue, String newValue) {
// TODO: The "repeatable" semantics are not implemented, yet.
commentChanged(CodeUnit.REPEATABLE_COMMENT, space, range, oldValue, newValue);
commentChanged(CommentType.REPEATABLE, space, range, oldValue, newValue);
}
private void compositeDataAdded(TraceAddressSpace space, TraceAddressSnapRange range,
@ -697,6 +698,7 @@ public class DBTraceProgramView implements TraceProgramView {
protected final Map<TraceThread, DBTraceProgramViewRegisters> regViewsByThread;
protected long snap;
protected InternalTracePlatform platform;
protected final DBTraceTimeViewport viewport;
protected final Runnable viewportChangeListener = this::viewportChanged;
@ -715,6 +717,9 @@ public class DBTraceProgramView implements TraceProgramView {
this.viewport = trace.createTimeViewport();
this.viewport.setSnap(snap);
// TODO: Initialize guest platform for fixed views?
this.platform = trace.getPlatformManager().getHostPlatform();
this.eventQueues = new DomainObjectEventQueues(this, TIME_INTERVAL, trace.getLock());
this.regViewsByThread = new WeakValueHashMap<>();
@ -833,7 +838,7 @@ public class DBTraceProgramView implements TraceProgramView {
@Override
public TraceBasedDataTypeManager getDataTypeManager() {
return trace.getDataTypeManager();
return platform.getDataTypeManager();
}
@Override

View file

@ -4,9 +4,9 @@
* 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.
@ -18,6 +18,8 @@ package ghidra.trace.database.program;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.listing.CodeUnit;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.program.TraceVariableSnapProgramView;
/**
@ -48,4 +50,13 @@ public class DBTraceVariableSnapProgramView extends DBTraceProgramView
// TODO: I could be more particular, but this seems to work fast enough, now.
fireObjectRestored();
}
@Override
public void setPlatform(TracePlatform platform) {
if (!(platform instanceof InternalTracePlatform iPlatform) ||
platform.getTrace() != trace) {
throw new IllegalArgumentException("Platform is not in this trace");
}
this.platform = iPlatform;
}
}

View file

@ -4,9 +4,9 @@
* 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.
@ -22,6 +22,7 @@ import javax.swing.Icon;
import generic.theme.GIcon;
import ghidra.lifecycle.Transitional;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.DataTypeManagerDomainObject;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.Language;
@ -31,6 +32,7 @@ import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointManager;
import ghidra.trace.model.context.TraceRegisterContextManager;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.guest.TracePlatformManager;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceCodeUnit;
@ -95,8 +97,19 @@ public interface Trace extends DataTypeManagerDomainObject {
TraceCodeManager getCodeManager();
/**
* {@inheritDoc}
*
* <p>
* For traces, this gets the "base" or "host" {@link DataTypeManager}. For platform-specific
* managers, see {@link TracePlatform#getDataTypeManager()}.
*/
@Override
TraceBasedDataTypeManager getDataTypeManager();
default TraceBasedDataTypeManager getDataTypeManager() {
return getBaseDataTypeManager();
}
TraceBasedDataTypeManager getBaseDataTypeManager();
TraceEquateManager getEquateManager();

View file

@ -17,6 +17,7 @@ package ghidra.trace.model.data;
import ghidra.program.model.data.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.program.TraceProgramView;
/**
@ -36,6 +37,13 @@ public interface TraceBasedDataTypeManager extends ProgramBasedDataTypeManager {
*/
Trace getTrace();
/**
* Get the platform for which this data type manager is provided
*
* @return the platform
*/
TracePlatform getPlatform();
/**
* TODO: Petition to have this replace
* {@link TraceBasedDataTypeManager#resolve(DataType, DataTypeConflictHandler)}

View file

@ -21,6 +21,7 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.mem.MemBuffer;
import ghidra.trace.model.Trace;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.memory.TraceObjectRegister;
import ghidra.trace.model.symbol.TraceLabelSymbol;
import ghidra.trace.model.target.TraceObject;
@ -83,10 +84,17 @@ public interface TracePlatform {
/**
* Get the compiler of the guest platform
*
* @return the compiler spec
* @return the compiler specification
*/
CompilerSpec getCompilerSpec();
/**
* Get the data type manager for this platform.
*
* @return the data type manager
*/
TraceBasedDataTypeManager getDataTypeManager();
/**
* Get the addresses in the host which are mapped to somewhere in the guest
*

View file

@ -4,9 +4,9 @@
* 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.
@ -16,6 +16,7 @@
package ghidra.trace.model.listing;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataOrganization;
import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.Register;
import ghidra.program.model.util.CodeUnitInsertionException;
@ -29,9 +30,14 @@ import ghidra.trace.model.guest.TracePlatform;
* This view excludes instructions and default / undefined data units.
*/
public interface TraceDefinedDataView extends TraceBaseDefinedUnitsView<TraceData> {
/**
* Create a data unit starting at the given address
*
* <p>
* If the given type is already part of this trace, its platform is used as is. If not, then it
* is resolved to the host platform.
*
* @param lifespan the span for which the unit is effective
* @param address the starting address
* @param dataType the data type for the unit
@ -42,12 +48,31 @@ public interface TraceDefinedDataView extends TraceBaseDefinedUnitsView<TraceDat
TraceData create(Lifespan lifespan, Address address, DataType dataType, int length)
throws CodeUnitInsertionException;
/**
* Create a data unit starting at the given address
*
* <p>
* The given type is resolved to the given platform, even if the type already exists in the
* trace by another platform.
*
* @param lifespan the span for which the unit is effective
* @param address the starting address
* @param platform the platform for the type's {@link DataOrganization}
* @param dataType the data type for the unit
* @param length the length of the unit, -1 for unspecified
* @return the new data unit
* @throws CodeUnitInsertionException if there's a conflict
*/
TraceData create(Lifespan lifespan, Address address, TracePlatform platform, DataType dataType,
int length) throws CodeUnitInsertionException;
/**
* Create a data unit of unspecified length starting at the given address
*
* <p>
* The length will be determined by the data type, possibly by examining the bytes, e.g., a
* null-terminated UTF-8 string.
* null-terminated UTF-8 string. If the given type is already part of this trace, its platform
* is used as is. If not, then it is resolved to the host platform.
*
* @param lifespan the span for which the unit is effective
* @param address the starting address
@ -58,12 +83,31 @@ public interface TraceDefinedDataView extends TraceBaseDefinedUnitsView<TraceDat
TraceData create(Lifespan lifespan, Address address, DataType dataType)
throws CodeUnitInsertionException;
/**
* Create a data unit of unspecified length starting at the given address
*
* <p>
* The length will be determined by the data type, possibly by examining the bytes, e.g., a
* null-terminated UTF-8 string. The given type is resolved to the given platform, even if the
* type already exists in the trace by another platform.
*
* @param lifespan the span for which the unit is effective
* @param address the starting address
* @param platform the platform for the type's {@link DataOrganization}
* @param dataType the data type for the unit
* @return the new data unit
* @throws CodeUnitInsertionException if there's a conflict
*/
TraceData create(Lifespan lifespan, Address address, TracePlatform platform, DataType dataType)
throws CodeUnitInsertionException;
/**
* Create a data unit on the given register
*
* <p>
* If the register is memory mapped, this will delegate to the appropriate space. In those
* cases, the assignment affects all threads.
* cases, the assignment affects all threads. The type is resolved to the host platform, even if
* it already exists in the trace by another platform.
*
* @param lifespan the span for which the unit is effective
* @param register the register to assign a data type
@ -82,7 +126,8 @@ public interface TraceDefinedDataView extends TraceBaseDefinedUnitsView<TraceDat
*
* <p>
* If the register is memory mapped, this will delegate to the appropriate space. In those
* cases, the assignment affects all threads.
* cases, the assignment affects all threads. The type is resolved to the given platform, even
* if it already exists in the trace by another platform.
*
* @param platform the platform whose language defines the register
* @param lifespan the span for which the unit is effective

View file

@ -4,9 +4,9 @@
* 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.
@ -15,11 +15,13 @@
*/
package ghidra.trace.model.program;
import ghidra.trace.model.guest.TracePlatform;
public interface TraceVariableSnapProgramView extends TraceProgramView {
/**
* Seek to a particular snap
*
* @param snap
* @param snap the snap
*/
void setSnap(long snap);
@ -29,4 +31,11 @@ public interface TraceVariableSnapProgramView extends TraceProgramView {
default void seekLatest() {
setSnap(getMaxSnap());
}
/**
* Set the current platform, so that actions have context
*
* @param platform the platform
*/
void setPlatform(TracePlatform platform);
}

View file

@ -549,6 +549,23 @@ public class ToyDBTraceBuilder implements AutoCloseable {
return code.definedData().create(Lifespan.nowOn(snap), start, type, length);
}
/**
* Create a data unit
*
* @param snap the starting snap
* @param start the min address
* @param platform the platform for data organization
* @param type the data type of the unit
* @param length the length, or -1 for the type's default
* @return the new data unit
* @throws CodeUnitInsertionException if the unit cannot be created
*/
public DBTraceDataAdapter addData(long snap, Address start, TracePlatform platform,
DataType type, int length) throws CodeUnitInsertionException {
DBTraceCodeManager code = trace.getCodeManager();
return code.definedData().create(Lifespan.nowOn(snap), start, platform, type, length);
}
/**
* Create a data unit, first placing the given bytes
*
@ -569,6 +586,27 @@ public class ToyDBTraceBuilder implements AutoCloseable {
return data;
}
/**
* Create a data unit, first placing the given bytes
*
* @param snap the starting snap
* @param start the min address
* @param platform the platform for data organization
* @param type the data type of the unit
* @param buf the bytes to place, which will become the unit's bytes
* @return the new data unit
* @throws CodeUnitInsertionException if the unit cannot be created
*/
public DBTraceDataAdapter addData(long snap, Address start, TracePlatform platform,
DataType type, ByteBuffer buf) throws CodeUnitInsertionException {
int length = buf.remaining();
DBTraceMemoryManager memory = trace.getMemoryManager();
memory.putBytes(snap, start, buf);
DBTraceDataAdapter data = addData(snap, start, platform, type, length);
assertEquals(length, data.getLength());
return data;
}
/**
* Create an instruction unit by disassembling existing bytes
*
@ -838,6 +876,7 @@ public class ToyDBTraceBuilder implements AutoCloseable {
* Get an object by its path pattern intersecting the given lifespan
*
* @param path the path pattern
* @param span the lifespan to search
* @return the object or null
*/
public TraceObject objAny(String path, Lifespan span) {

View file

@ -4,9 +4,9 @@
* 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.
@ -46,7 +46,7 @@ public class DBTraceDataTypeManagerTest extends AbstractGhidraHeadlessIntegratio
.getLanguage(
new LanguageID("Toy:BE:64:default"));
trace = new DBTrace("Testing", toyLanguage.getDefaultCompilerSpec(), this);
dtm = trace.getDataTypeManager();
dtm = trace.getBaseDataTypeManager();
}
@After

View file

@ -1830,7 +1830,7 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
@Test
public void testAddGuestInstructionThenRemoveAndDelete() throws AddressOverflowException,
CodeUnitInsertionException, IOException, CancelledException {
DBTracePlatformManager langMan = b.trace.getPlatformManager();
DBTracePlatformManager platMan = b.trace.getPlatformManager();
Language x86 = getSLEIGH_X86_LANGUAGE();
DBTraceGuestPlatform guest;
DBTraceGuestPlatformMappedRange mappedRange;
@ -1839,7 +1839,7 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
TraceInstruction i4001;
TraceData d4003;
try (Transaction tx = b.startTransaction()) {
guest = langMan.addGuestPlatform(x86.getDefaultCompilerSpec());
guest = platMan.addGuestPlatform(x86.getDefaultCompilerSpec());
mappedRange = guest.addMappedRange(b.addr(0x0000), b.addr(guest, 0x0000), 1L << 32);
g4000 = b.addInstruction(0, b.addr(0x4000), guest, b.buf(0x90));
i4001 = b.addInstruction(0, b.addr(0x4001), b.host, b.buf(0xf4, 0));
@ -1857,7 +1857,6 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
b.trace.undo();
// NB. The range deletion also deletes the guest unit, so it'll have a new identity
// TODO: Related to GP-479?
g4000 = manager.instructions().getAt(0, b.addr(0x4000));
assertNotNull(g4000);
assertEquals(guest, g4000.getPlatform());
@ -1865,13 +1864,66 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes
guest.delete(new ConsoleTaskMonitor());
}
assertUndefinedWithAddr(b.addr(0x4000), manager.codeUnits().getAt(0, b.addr(0x4000)));
// TODO: Definitely part of GP-479. These should be able to keep their identities.
//assertEquals(i4001, manager.codeUnits().getAt(0, b.addr(0x4001)));
//assertEquals(d4003, manager.codeUnits().getAt(0, b.addr(0x4003)));
assertEquals(i4001, manager.codeUnits().getAt(0, b.addr(0x4001)));
assertEquals(d4003, manager.codeUnits().getAt(0, b.addr(0x4003)));
assertNotNull(manager.instructions().getAt(0, b.addr(0x4001)));
assertNotNull(manager.definedData().getAt(0, b.addr(0x4003)));
}
@Test
public void testAddGuestDataThenRemoveAndDelete() throws Exception {
DBTracePlatformManager platMan = b.trace.getPlatformManager();
Language x86 = getSLEIGH_X86_LANGUAGE();
DBTraceGuestPlatform guest;
DBTraceGuestPlatformMappedRange mappedRange;
TraceData hd4000;
TraceData gd4008;
TraceData gd400c;
try (Transaction tx = b.startTransaction()) {
guest = platMan.addGuestPlatform(x86.getDefaultCompilerSpec());
mappedRange = guest.addMappedRange(b.addr(0x0000), b.addr(guest, 0x0000), 1L << 32);
hd4000 = b.addData(0, b.addr(0x4000), PointerDataType.dataType,
b.buf(0, 0, 0, 0, 0, 0, 0x40, 0x80));
gd4008 = b.addData(0, b.addr(0x4008), guest, PointerDataType.dataType,
b.buf(0x81, 0x40, 0, 0));
gd400c = b.addData(0, b.addr(0x400c), gd4008.getDataType(), b.buf(0x82, 0x40, 0, 0));
}
assertEquals(b.host, hd4000.getPlatform());
assertEquals(8, hd4000.getLength());
assertEquals(guest, gd4008.getPlatform());
assertEquals(4, gd4008.getLength());
assertEquals(guest, gd400c.getPlatform());
assertEquals(4, gd400c.getLength());
assertEquals(gd4008, manager.codeUnits().getAt(0, b.addr(0x4008)));
assertEquals(gd400c, manager.codeUnits().getAt(0, b.addr(0x400c)));
try (Transaction tx = b.startTransaction()) {
mappedRange.delete(new ConsoleTaskMonitor());
}
assertEquals(hd4000, manager.codeUnits().getAt(0, b.addr(0x4000)));
assertUndefinedWithAddr(b.addr(0x4008), manager.codeUnits().getAt(0, b.addr(0x4008)));
assertUndefinedWithAddr(b.addr(0x400c), manager.codeUnits().getAt(0, b.addr(0x400c)));
b.trace.undo();
// NB. The range deletion also deletes the guest units, so they'll have new identities
gd4008 = manager.definedData().getAt(0, b.addr(0x4008));
gd400c = manager.definedData().getAt(0, b.addr(0x400c));
assertNotNull(gd4008);
assertNotNull(gd400c);
assertEquals(guest, gd4008.getPlatform());
assertEquals(guest, gd400c.getPlatform());
try (Transaction tx = b.startTransaction()) {
guest.delete(new ConsoleTaskMonitor());
}
assertEquals(hd4000, manager.codeUnits().getAt(0, b.addr(0x4000)));
assertUndefinedWithAddr(b.addr(0x4008), manager.codeUnits().getAt(0, b.addr(0x4008)));
assertUndefinedWithAddr(b.addr(0x400c), manager.codeUnits().getAt(0, b.addr(0x400c)));
assertNotNull(manager.definedData().getAt(0, b.addr(0x4000)));
}
@Test
public void testSaveAndLoad() throws Exception {
try (Transaction tx = b.startTransaction()) {