GP-2479: Remove register-specific space interfaces from Trace API

This commit is contained in:
Dan 2022-08-23 11:15:21 -04:00
parent 1eb2e71734
commit 0459d93508
146 changed files with 2030 additions and 1949 deletions

View File

@ -300,7 +300,7 @@ public class PopulateTraceLocal extends GhidraScript {
Collection<? extends TraceThread> liveThreads = threads.getLiveThreads(snap);
for (TraceThread thread : liveThreads) {
TraceMemoryRegisterSpace regspace = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regspace = memory.getMemoryRegisterSpace(thread, true);
ModelObject modelThread = modelThreadMap.get("0x" + thread.getName());
if (modelThread != null) {
Map<String, ModelObject> registers =

View File

@ -34,7 +34,7 @@ import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.program.util.DefaultLanguageService;
import ghidra.trace.database.DBTrace;
import ghidra.trace.model.Trace;
import ghidra.trace.model.listing.TraceCodeRegisterSpace;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.memory.*;
import ghidra.trace.model.symbol.TraceLabelSymbol;
import ghidra.trace.model.symbol.TraceNamespaceSymbol;
@ -149,13 +149,13 @@ public class PopulateDemoTrace extends GhidraScript {
* Fields to store the handle to the first (main) thread and its registers
*/
private TraceThread thread1;
private TraceMemoryRegisterSpace regs1;
private TraceMemorySpace regs1;
/**
* Fields to store the handle to the second (cloned) thread and its registers
*/
private TraceThread thread2;
private TraceMemoryRegisterSpace regs2;
private TraceMemorySpace regs2;
/**
* Create an address in the processor's (x86_64) default space.
@ -195,7 +195,7 @@ public class PopulateDemoTrace extends GhidraScript {
* @param regs the register space for a given thread
* @param ins the instructions
*/
protected void putRIP(long tick, TraceMemoryRegisterSpace regs, Instruction ins) {
protected void putRIP(long tick, TraceMemorySpace regs, Instruction ins) {
regs.setValue(tick,
new RegisterValue(reg("RIP"), ins.getAddress().getOffsetAsBigInteger()));
}
@ -224,7 +224,7 @@ public class PopulateDemoTrace extends GhidraScript {
// NOTE: This is compensating for a TODO in the memory and code managers
// TODO: Consider convenience methods TraceThread#getMemorySpace(boolean), etc
TraceMemoryRegisterSpace mem =
TraceMemorySpace mem =
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, true);
// First check if the value was set at all
if (mem.getState(tick, reg) != TraceMemoryState.KNOWN) {
@ -237,7 +237,7 @@ public class PopulateDemoTrace extends GhidraScript {
return;
}
TraceCodeRegisterSpace code =
TraceCodeSpace code =
thread.getTrace().getCodeManager().getCodeRegisterSpace(thread, true);
code.definedUnits().clear(Range.atLeast(tick), reg, TaskMonitor.DUMMY);
code.definedData().create(Range.atLeast(tick), reg, PointerDataType.dataType);

View File

@ -22,7 +22,7 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.thread.TraceThread;
@ -58,7 +58,7 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
if (!thread.getLifespan().contains(snap)) {
return null;
}
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, frame, false);
if (regs == null) {
return null;

View File

@ -71,7 +71,7 @@ import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace.*;
import ghidra.trace.model.listing.*;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.thread.TraceThread;
@ -281,7 +281,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
}
private void refreshRange(AddressRange range) {
TraceMemoryRegisterSpace space = getRegisterMemorySpace(false);
TraceMemorySpace space = getRegisterMemorySpace(false);
// ... If I got an event for it, it ought to exist.
assert space != null;
@ -857,7 +857,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
}
BigInteger getRegisterValue(Register register) {
TraceMemoryRegisterSpace regs = getRegisterMemorySpace(false);
TraceMemorySpace regs = getRegisterMemorySpace(false);
if (regs == null) {
return BigInteger.ZERO;
}
@ -901,7 +901,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
}
private RegisterValue combineWithTraceBaseRegisterValue(RegisterValue rv) {
TraceMemoryRegisterSpace regs = getRegisterMemorySpace(false);
TraceMemorySpace regs = getRegisterMemorySpace(false);
long snap = current.getViewSnap();
return TraceRegisterUtils.combineWithTraceBaseRegisterValue(rv, snap, regs, true);
}
@ -914,7 +914,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
void writeRegisterDataType(Register register, DataType dataType) {
try (UndoableTransaction tid =
UndoableTransaction.start(current.getTrace(), "Edit Register Type")) {
TraceCodeRegisterSpace space = getRegisterMemorySpace(true).getCodeSpace(true);
TraceCodeSpace space = getRegisterMemorySpace(true).getCodeSpace(true);
long snap = current.getViewSnap();
space.definedUnits().clear(Range.closed(snap, snap), register, TaskMonitor.DUMMY);
if (dataType != null) {
@ -927,7 +927,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
}
TraceData getRegisterData(Register register) {
TraceCodeRegisterSpace space = getRegisterCodeSpace(false);
TraceCodeSpace space = getRegisterCodeSpace(false);
if (space == null) {
return null;
}
@ -985,7 +985,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
viewKnown = null;
return;
}
TraceMemoryRegisterSpace regs = getRegisterMemorySpace(false);
TraceMemorySpace regs = getRegisterMemorySpace(false);
TraceProgramView view = current.getView();
if (regs == null || view == null) {
viewKnown = null;
@ -1014,8 +1014,8 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
if (!isRegisterKnown(register)) {
return false;
}
TraceMemoryRegisterSpace curSpace = getRegisterMemorySpace(current, false);
TraceMemoryRegisterSpace prevSpace = getRegisterMemorySpace(previous, false);
TraceMemorySpace curSpace = getRegisterMemorySpace(current, false);
TraceMemorySpace prevSpace = getRegisterMemorySpace(previous, false);
if (prevSpace == null) {
return false;
}
@ -1104,7 +1104,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
return viewKnown;
}
protected static TraceMemoryRegisterSpace getRegisterMemorySpace(DebuggerCoordinates coords,
protected static TraceMemorySpace getRegisterMemorySpace(DebuggerCoordinates coords,
boolean createIfAbsent) {
TraceThread thread = coords.getThread();
if (thread == null) {
@ -1115,11 +1115,11 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
.getMemoryRegisterSpace(thread, coords.getFrame(), createIfAbsent);
}
protected TraceMemoryRegisterSpace getRegisterMemorySpace(boolean createIfAbsent) {
protected TraceMemorySpace getRegisterMemorySpace(boolean createIfAbsent) {
return getRegisterMemorySpace(current, createIfAbsent);
}
protected TraceCodeRegisterSpace getRegisterCodeSpace(boolean createIfAbsent) {
protected TraceCodeSpace getRegisterCodeSpace(boolean createIfAbsent) {
TraceThread curThread = current.getThread();
if (curThread == null) {
return null;
@ -1132,7 +1132,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
protected Set<Register> collectBaseRegistersWithKnownValues(TraceThread thread) {
// TODO: Other registers may acquire known values.
// TODO: How to best alert the user? Just add to view?
TraceMemoryRegisterSpace mem =
TraceMemorySpace mem =
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, false);
Set<Register> result = new LinkedHashSet<>();
if (mem == null) {

View File

@ -45,7 +45,7 @@ import ghidra.program.model.listing.Program;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace.TraceMemoryBytesChangeType;
import ghidra.trace.model.Trace.TraceStackChangeType;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread;
@ -194,7 +194,7 @@ public class DebuggerStackProvider extends ComponentProviderAdapter {
if (!TraceRegisterUtils.rangeForRegister(pc).intersects(range.getRange())) {
return;
}
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(curThread, false);
RegisterValue value = regs.getViewValue(current.getViewSnap(), pc);
Address address = trace.getBaseLanguage()
@ -427,7 +427,7 @@ public class DebuggerStackProvider extends ComponentProviderAdapter {
currentStack = null;
Trace curTrace = current.getTrace();
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
curTrace.getMemoryManager().getMemoryRegisterSpace(current.getThread(), false);
if (regs == null) {
contextChanged();

View File

@ -24,7 +24,7 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.lang.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.Msg;
@ -78,8 +78,7 @@ public class ArmDisassemblyInject implements DisassemblyInject {
return;
}
TraceMemoryRegisterSpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
/**
* Some variants (particularly Cortex-M) are missing cpsr. This seems to indicate it only
* supports THUMB. There is an epsr (xpsr in gdb), but we don't have it in our models, and

View File

@ -216,7 +216,7 @@ public enum ProgramEmulationUtils {
*/
public static void initializeRegisters(Trace trace, long snap, TraceThread thread,
Program program, Address tracePc, Address programPc, TraceMemoryRegion stack) {
TraceMemoryRegisterSpace space =
TraceMemorySpace space =
trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
if (program != null) {
ProgramContext ctx = program.getProgramContext();

View File

@ -266,11 +266,11 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
TimedMsg.debug(this, "Reg values changed: " + updates.keySet());
recorder.parTx.execute("Registers " + path + " changed", () -> {
TraceCodeManager codeManager = trace.getCodeManager();
TraceCodeRegisterSpace codeRegisterSpace =
TraceCodeSpace codeRegisterSpace =
codeManager.getCodeRegisterSpace(traceThread, false);
TraceDefinedDataRegisterView definedData =
TraceDefinedDataView definedData =
codeRegisterSpace == null ? null : codeRegisterSpace.definedData();
TraceMemoryRegisterSpace regSpace =
TraceMemorySpace regSpace =
memoryManager.getMemoryRegisterSpace(traceThread, frameLevel, true);
for (Entry<String, byte[]> ent : updates.entrySet()) {
RegisterValue rv = regMapper.targetToTrace(ent.getKey(), ent.getValue());
@ -304,11 +304,11 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
//TimedMsg.info(this, "Register value changed: " + targetRegister);
recorder.parTx.execute("Register " + path + " changed", () -> {
TraceCodeManager codeManager = trace.getCodeManager();
TraceCodeRegisterSpace codeRegisterSpace =
TraceCodeSpace codeRegisterSpace =
codeManager.getCodeRegisterSpace(traceThread, false);
TraceDefinedDataRegisterView definedData =
TraceDefinedDataView definedData =
codeRegisterSpace == null ? null : codeRegisterSpace.definedData();
TraceMemoryRegisterSpace regSpace =
TraceMemorySpace regSpace =
memoryManager.getMemoryRegisterSpace(traceThread, frameLevel, true);
String key = targetRegister.getName();
if (PathUtils.isIndex(key)) {
@ -337,7 +337,7 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
String path = bank.getJoinedPath(".");
recorder.parTx.execute("Registers invalidated: " + path, () -> {
TraceMemoryRegisterSpace regSpace =
TraceMemorySpace regSpace =
memoryManager.getMemoryRegisterSpace(traceThread, frameLevel, false);
if (regSpace == null) {
return;

View File

@ -227,8 +227,7 @@ public class DisassembleAtPcDebuggerBot implements DebuggerBot {
TraceData pcUnit = null;
try (UndoableTransaction tid =
UndoableTransaction.start(trace, "Disassemble: PC is code pointer")) {
TraceCodeRegisterSpace regCode =
codeManager.getCodeRegisterSpace(thread, frameLevel, true);
TraceCodeSpace regCode = codeManager.getCodeRegisterSpace(thread, frameLevel, true);
try {
pcUnit = regCode.definedData()
.create(Range.atLeast(pcSnap), pc, PointerDataType.dataType);

View File

@ -32,7 +32,7 @@ import ghidra.trace.model.Trace;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.modules.TraceModule;
import ghidra.trace.model.modules.TraceSection;
import ghidra.trace.model.stack.TraceStackFrame;
@ -365,7 +365,7 @@ public interface TraceRecorder {
RegisterValue rv = new RegisterValue(register,
Utils.bytesToBigInteger(data, data.length, lang.isBigEndian(), false));
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frameLevel, false);
rv = TraceRegisterUtils.combineWithTraceBaseRegisterValue(rv, getSnap(), regs, true);
return writeThreadRegisters(thread, frameLevel, Map.of(rv.getRegister(), rv));

View File

@ -48,7 +48,7 @@ import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceLocation;
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
import ghidra.trace.model.memory.TraceMemoryOperations;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule;
@ -947,7 +947,7 @@ public interface FlatDebuggerAPI {
catch (InterruptedException | ExecutionException | TimeoutException e) {
return null;
}
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frame, false);
if (regs == null) {
return registers.stream().map(RegisterValue::new).collect(Collectors.toList());

View File

@ -31,7 +31,7 @@ import ghidra.program.model.symbol.SourceType;
import ghidra.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.symbol.*;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction;
@ -110,7 +110,7 @@ public class DebuggerListingPluginScreenShots extends GhidraScreenShotGenerator
TraceThread thread = tb.getOrAddThread("[1]", snap);
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(),
childLabel.getAddress().getOffsetAsBigInteger()));

View File

@ -31,7 +31,7 @@ import ghidra.program.model.symbol.SourceType;
import ghidra.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.symbol.*;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction;
@ -114,7 +114,7 @@ public class DebuggerMemoryBytesPluginScreenShots extends GhidraScreenShotGenera
TraceThread thread = tb.getOrAddThread("[1]", snap);
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(),
childLabel.getAddress().getOffsetAsBigInteger()));

View File

@ -28,7 +28,7 @@ import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.RegisterValue;
import ghidra.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction;
import help.screenshot.GhidraScreenShotGenerator;
@ -62,7 +62,7 @@ public class DebuggerRegistersPluginScreenShots extends GhidraScreenShotGenerato
long snap1 = tb.trace.getTimeManager().createSnapshot("Second").getKey();
TraceThread thread = tb.getOrAddThread("[1]", snap0);
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
Language lang = tb.trace.getBaseLanguage();
regs.setValue(snap0,

View File

@ -56,7 +56,7 @@ import ghidra.program.util.ProgramSelection;
import ghidra.trace.database.listing.DBTraceInstruction;
import ghidra.trace.database.listing.DBTraceInstructionsMemoryView;
import ghidra.trace.database.memory.DBTraceMemoryManager;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.database.program.DBTraceVariableSnapProgramView;
import ghidra.trace.database.target.DBTraceObject;
import ghidra.trace.database.target.DBTraceObjectManager;
@ -225,7 +225,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
TraceThread thread;
try (UndoableTransaction tid = tb.startTransaction()) {
thread = tb.getOrAddThread("Threads[0]", 0);
DBTraceMemoryRegisterSpace regs =
DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO));
}
@ -259,7 +259,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
TraceThread thread;
try (UndoableTransaction tid = tb.startTransaction()) {
thread = tb.getOrAddThread("Threads[0]", 0);
DBTraceMemoryRegisterSpace regs =
DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0,
new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ONE.shiftLeft(5)));

View File

@ -68,7 +68,7 @@ import ghidra.test.TestEnv;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace.TraceMemoryBytesChangeType;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.InvalidNameException;
@ -750,7 +750,7 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
if (space.getThread() != traceThread) {
return;
}
TraceMemoryRegisterSpace regSpace =
TraceMemorySpace regSpace =
trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false);
assertNotNull(regSpace);
for (Map.Entry<String, byte[]> ent : values.entrySet()) {

View File

@ -182,7 +182,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(tb.trace);
@ -208,7 +208,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(tb.trace);
@ -237,9 +237,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(tb.trace);
@ -282,9 +282,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(tb.trace);
@ -322,7 +322,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
assertEquals(tb.trace.getProgramView(), listingProvider.getProgram());
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800)));
}
@ -356,7 +356,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(b1.trace);
@ -368,7 +368,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(b1.trace);
@ -412,7 +412,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(b1.trace);
@ -424,7 +424,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(b1.trace);
@ -505,7 +505,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForProgram(program);
@ -582,7 +582,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(tb.trace);
@ -618,7 +618,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00408765)));
}
@ -823,7 +823,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register r0 = tb.language.getRegister("r0");
regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16)));
mm.putBytes(0, tb.addr(0x00401234), tb.buf(0x00, 0x40, 0x43, 0x21));
@ -863,7 +863,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("[stack]", Range.atLeast(0L), tb.range(0x1f000000, 0x1fffffff),
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register pc = tb.language.getProgramCounter();
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
@ -1009,9 +1009,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(tb.trace);
@ -1309,9 +1309,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread1 = tb.getOrAddThread("Thread 1", 0);
thread2 = tb.getOrAddThread("Thread 2", 0);
TraceMemoryRegisterSpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
TraceMemoryRegisterSpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
waitForDomainObject(tb.trace);
@ -1338,7 +1338,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
@ -1394,7 +1394,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
}
waitForDomainObject(tb.trace);
@ -1404,7 +1404,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
waitForDomainObject(tb.trace);
@ -1424,7 +1424,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
DBTraceStackManager sm = tb.trace.getStackManager();
@ -1438,7 +1438,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
waitForDomainObject(tb.trace);

View File

@ -158,7 +158,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(tb.trace);
@ -184,7 +184,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(tb.trace);
@ -214,9 +214,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(tb.trace);
@ -259,9 +259,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(tb.trace);
@ -299,7 +299,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
assertEquals(tb.trace.getProgramView(), memBytesProvider.getProgram());
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800)));
}
@ -332,7 +332,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(b1.trace);
@ -344,7 +344,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(b1.trace);
@ -383,7 +383,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(b1.trace);
@ -395,7 +395,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(b1.trace);
@ -456,7 +456,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
}
waitForDomainObject(tb.trace);
@ -616,7 +616,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register r0 = tb.language.getRegister("r0");
regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16)));
mm.putBytes(0, tb.addr(0x00401234), tb.buf(0x00, 0x40, 0x43, 0x21));
@ -656,7 +656,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("[stack]", Range.atLeast(0L), tb.range(0x1f000000, 0x1fffffff),
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register pc = tb.language.getProgramCounter();
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
@ -708,9 +708,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
}
waitForDomainObject(tb.trace);
@ -911,9 +911,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread1 = tb.getOrAddThread("Thread 1", 0);
thread2 = tb.getOrAddThread("Thread 2", 0);
TraceMemoryRegisterSpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
TraceMemorySpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
regs1.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
TraceMemoryRegisterSpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
TraceMemorySpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
regs2.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
waitForDomainObject(tb.trace);
@ -940,7 +940,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
@ -996,7 +996,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
}
waitForDomainObject(tb.trace);
@ -1006,7 +1006,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
waitForDomainObject(tb.trace);
@ -1026,7 +1026,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
DBTraceStackManager sm = tb.trace.getStackManager();
@ -1040,7 +1040,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
}
waitForDomainObject(tb.trace);

View File

@ -46,10 +46,10 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.model.listing.*;
import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction;
import ghidra.util.exception.DuplicateNameException;
@ -122,7 +122,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
}
protected void addRegisterValues(TraceThread thread, UndoableTransaction tid) {
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regVals.putBytes(0, pc, tb.buf(0, 0, 0, 0, 0, 0x40, 0, 0));
regVals.putBytes(0, sp, tb.buf(0x1f, 0, 0, 0, 0, 0, 0, 0));
@ -131,7 +131,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
protected void addRegisterTypes(TraceThread thread, UndoableTransaction tid)
throws CodeUnitInsertionException {
TraceCodeRegisterSpace regCode =
TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
regCode.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
// TODO: Pointer needs to be to ram, not register space
@ -384,7 +384,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
addRegisterValues(thread);
waitForDomainObject(tb.trace);
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
RegisterRow row = findRegisterRow(r0);
@ -422,7 +422,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
addRegisterValues(thread);
waitForDomainObject(tb.trace);
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
RegisterRow row = findRegisterRow(r0);
@ -456,7 +456,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
row.setDataType(PointerDataType.dataType);
waitForSwing();
DBTraceCodeRegisterSpace regCode =
DBTraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
assertNotNull(regCode);
TraceData data = regCode.data().getForRegister(0L, pc);
@ -478,7 +478,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
row.setDataType(LongLongDataType.dataType);
waitForSwing();
DBTraceCodeRegisterSpace regCode =
DBTraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
assertNotNull(regCode);
TraceData data = regCode.data().getForRegister(0L, pc);
@ -514,7 +514,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
rowH.setDataType(SignedDWordDataType.dataType);
waitForSwing();
DBTraceCodeRegisterSpace regCode =
DBTraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
assertNotNull(regCode);
// It's two units, not a struct with two components
@ -621,9 +621,9 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowValuePopulated();
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
TraceCodeRegisterSpace regCode =
TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
regVals.putBytes(1, r0, tb.buf(1, 1, 2, 2, 3, 3, 4, 4));
regCode.definedData().create(Range.atLeast(1L), r0, r0Struct);
@ -649,7 +649,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) {
TraceCodeRegisterSpace regCode =
TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0);
code.setEndSnap(0);
@ -679,7 +679,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) {
TraceCodeRegisterSpace regCode =
TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0);
code.delete();
@ -890,9 +890,9 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
TraceCodeRegisterSpace regCode =
TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
regVals.putBytes(10, r0, tb.buf(0, 0, 0, 0, 0, 0, 0, 0));
// NB. the manager should have split the data unit at the value change
@ -932,11 +932,11 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, 1, true);
regVals.putBytes(0, pc, tb.buf(0, 0, 0, 0, 0, 0x50, 0, 0));
TraceCodeRegisterSpace regCode =
TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, 1, true);
regCode.definedData().create(Range.atLeast(0L), pc, QWordDataType.dataType);
}

View File

@ -40,7 +40,7 @@ import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.DefaultTraceLocation;
import ghidra.trace.model.TraceLocation;
import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread;
@ -73,7 +73,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
protected void addRegVals(TraceThread thread) {
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00400123", 16)));
}

View File

@ -119,7 +119,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
private void setRegisterValues(TraceThread thread) {
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x00400000)));
}
@ -318,7 +318,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
waitForSwing();
// Verify no target read has occurred yet
TraceMemoryRegisterSpace regs =
TraceMemorySpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
if (regs != null) {
assertEquals(BigInteger.ZERO, regs.getValue(0, r0).getUnsignedValue());
@ -402,7 +402,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
@Test
public void testEditRegisterEmu() {
WatchRow row = prepareTestEditEmu("r0");
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
row.setRawValueString("0x1234");
@ -433,7 +433,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
waitForSwing();
assertTrue(row.isValueEditable());
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
row.setValueString("1234");
@ -748,7 +748,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
.createLabel(tb.addr(0x00601234), "my_symbol", SourceType.USER_DEFINED);
}
try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals =
TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x55751234)));
}

View File

@ -37,7 +37,7 @@ import ghidra.pcode.exec.DebuggerPcodeUtils;
import ghidra.program.model.lang.*;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.database.UndoableTransaction;
@ -366,8 +366,8 @@ public class DebuggerStateEditingServiceTest extends AbstractGhidraHeadedDebugge
StateEditor editor = editingService.createStateEditor(tb.trace);
waitOn(editor.setRegister(rv1234));
waitForPass(() -> {
DBTraceMemoryRegisterSpace regs = tb.trace.getMemoryManager()
.getMemoryRegisterSpace(thread, false);
TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertNotNull(regs);
RegisterValue value = regs.getValue(traceManager.getCurrentSnap(), r0);
assertEquals(rv1234, value);

View File

@ -36,7 +36,7 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.database.UndoableTransaction;
@ -89,8 +89,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
assertNotNull(trace);
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
TraceMemoryRegisterSpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertEquals(new BigInteger("00400000", 16),
regs.getViewValue(0, regPC).getUnsignedValue());
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue());
@ -146,8 +145,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
assertNotNull(trace);
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
TraceMemoryRegisterSpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertEquals(new BigInteger("00000400", 16),
regs.getViewValue(0, regPC).getUnsignedValue());
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue());
@ -205,8 +203,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
assertNotNull(trace);
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
TraceMemoryRegisterSpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertEquals(new BigInteger("000100", 16),
regs.getViewValue(0, regPC).getUnsignedValue());
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regW0).getUnsignedValue());

View File

@ -36,7 +36,7 @@ import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeRegisterSpace;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.memory.*;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction;
@ -75,7 +75,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
});
}
protected TraceMemoryRegisterSpace createRegSpace(TraceThread thread) {
protected TraceMemorySpace createRegSpace(TraceThread thread) {
try (UndoableTransaction tid =
UndoableTransaction.start(thread.getTrace(), "Create register space")) {
return thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, true);
@ -105,7 +105,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
Register r1 = lang.getRegister("r1");
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
//TraceThread thread = recorder.getTraceThread(mb.testThread1);
TraceMemoryRegisterSpace rs = createRegSpace(thread);
TraceMemorySpace rs = createRegSpace(thread);
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
Register::isBaseRegister);
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
@ -138,13 +138,13 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
Register pc = lang.getRegister("pc");
Register sp = lang.getRegister("sp");
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
TraceMemoryRegisterSpace rs = createRegSpace(thread);
TraceMemorySpace rs = createRegSpace(thread);
mb.testProcess1.addRegion("bin:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
r -> r.isBaseRegister() && r != pc && r != sp);
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add PC type")) {
TraceCodeRegisterSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
code.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
}
@ -187,13 +187,13 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
Register pc = lang.getRegister("pc");
Register sp = lang.getRegister("sp");
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
TraceMemoryRegisterSpace rs = createRegSpace(thread);
TraceMemorySpace rs = createRegSpace(thread);
mb.testProcess1.addRegion("[stack]", mb.rng(0x22220000, 0x2222ffff), "rw");
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
r -> r.isBaseRegister() && r != pc && r != sp);
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add SP type")) {
TraceCodeRegisterSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
code.definedData().create(Range.atLeast(0L), sp, PointerDataType.dataType);
}
@ -242,7 +242,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
//waitForCondition(() -> registerMapped(recorder, thread, pc));
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add PC type")) {
TraceCodeRegisterSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
code.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
}
regs.writeRegister("pc", tb.arr(0x55, 0x55, 0x02, 0x22));

View File

@ -59,7 +59,7 @@ import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Program;
import ghidra.trace.database.memory.DBTraceMemoryManager;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.model.Trace;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
@ -718,7 +718,7 @@ public class FlatDebuggerAPITest extends AbstractGhidraHeadedDebuggerGUITest {
waitForSwing();
assertTrue(flat.writeRegister(thread, 0, 0, "r0", BigInteger.valueOf(0x0102030405060708L)));
DBTraceMemoryRegisterSpace regs =
DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertNotNull(regs);
Register r0 = tb.language.getRegister("r0");
@ -734,7 +734,7 @@ public class FlatDebuggerAPITest extends AbstractGhidraHeadedDebuggerGUITest {
waitForSwing();
assertTrue(flat.writeRegister("r0", BigInteger.valueOf(0x0102030405060708L)));
DBTraceMemoryRegisterSpace regs =
DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertNotNull(regs);
Register r0 = tb.language.getRegister("r0");

View File

@ -21,7 +21,7 @@ import ghidra.pcode.emu.PcodeThread;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.thread.TraceThreadManager;
@ -88,7 +88,7 @@ public interface TracePcodeMachine<T> extends PcodeMachine<T> {
long snap = getSnap();
TraceThread traceThread =
trace.getThreadManager().getLiveThreadByPath(snap, thread.getName());
TraceMemoryRegisterSpace space =
TraceMemorySpace space =
trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false);
if (space == null) {
return false;

View File

@ -44,8 +44,7 @@ import ghidra.util.database.DBOpenMode;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceBookmarkManager
extends AbstractDBTraceSpaceBasedManager<DBTraceBookmarkSpace, DBTraceBookmarkRegisterSpace>
public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBTraceBookmarkSpace>
implements TraceBookmarkManager, DBTraceDelegatingManager<DBTraceBookmarkSpace> {
public static final String NAME = "Bookmark";
@ -180,13 +179,13 @@ public class DBTraceBookmarkManager
@Override
protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceBookmarkSpace(this, space);
return new DBTraceBookmarkSpace(this, space, null, 0);
}
@Override
protected DBTraceBookmarkRegisterSpace createRegisterSpace(AddressSpace space,
protected DBTraceBookmarkSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceBookmarkRegisterSpace(this, space, thread, ent.getFrameLevel());
return new DBTraceBookmarkSpace(this, space, thread, ent.getFrameLevel());
}
@Override
@ -195,13 +194,13 @@ public class DBTraceBookmarkManager
}
@Override
public DBTraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceThread thread,
public DBTraceBookmarkSpace getBookmarkRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}
@Override
public DBTraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceStackFrame frame,
public DBTraceBookmarkSpace getBookmarkRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent);
}

View File

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.bookmark;
import java.io.IOException;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.model.bookmark.TraceBookmarkRegisterSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.exception.VersionException;
public class DBTraceBookmarkRegisterSpace extends DBTraceBookmarkSpace
implements TraceBookmarkRegisterSpace {
private final TraceThread thread;
private final int frameLevel;
public DBTraceBookmarkRegisterSpace(DBTraceBookmarkManager manager, AddressSpace space,
TraceThread thread, int frameLevel) throws VersionException, IOException {
super(manager, space);
this.thread = thread;
this.frameLevel = frameLevel;
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
}

View File

@ -39,20 +39,27 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
protected final DBTraceBookmarkManager manager;
protected final ReadWriteLock lock;
protected final DBTrace trace;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBookmark, DBTraceBookmark> bookmarkMapSpace;
protected final DBCachedObjectIndex<String, DBTraceBookmark> bookmarksByTypeName;
protected final Collection<DBTraceBookmark> bookmarkView;
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space)
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space,
TraceThread thread, int frameLevel)
throws VersionException, IOException {
this.manager = manager;
this.lock = manager.getLock();
this.trace = manager.getTrace();
this.space = space;
this.thread = thread;
this.frameLevel = frameLevel;
this.bookmarkMapSpace =
new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space, -1, 0),
trace.getStoreFactory(), lock, space, DBTraceBookmark.class,
trace.getStoreFactory(), lock, space, null, 0, DBTraceBookmark.class,
(t, s, r) -> new DBTraceBookmark(this, t, s, r));
this.bookmarksByTypeName =
bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN);
@ -61,17 +68,17 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
@Override
public AddressSpace getAddressSpace() {
return bookmarkMapSpace.getAddressSpace();
return space;
}
@Override
public TraceThread getThread() {
return null;
return thread;
}
@Override
public int getFrameLevel() {
return 0;
return frameLevel;
}
protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) {

View File

@ -40,7 +40,7 @@ import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceBreakpointManager
extends AbstractDBTraceSpaceBasedManager<DBTraceBreakpointSpace, DBTraceBreakpointSpace>
extends AbstractDBTraceSpaceBasedManager<DBTraceBreakpointSpace>
implements TraceBreakpointManager, DBTraceDelegatingManager<DBTraceBreakpointSpace> {
protected static final String NAME = "Breakpoint";

View File

@ -67,7 +67,7 @@ public class DBTraceBreakpointSpace implements DBTraceSpaceBased {
assert threadKey == -1; // No breakpoints on registers
breakpointMapSpace =
new DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint>(
DBTraceBreakpoint.tableName(space, threadKey), factory, lock, space,
DBTraceBreakpoint.tableName(space, threadKey), factory, lock, space, null, 0,
DBTraceBreakpoint.class, (t, s, r) -> new DBTraceBreakpoint(this, t, s, r));
breakpointsByPath =
breakpointMapSpace.getUserIndex(String.class, DBTraceBreakpoint.PATH_COLUMN);

View File

@ -45,8 +45,8 @@ import ghidra.util.database.annot.*;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceRegisterContextManager extends
AbstractDBTraceSpaceBasedManager<DBTraceRegisterContextSpace, DBTraceRegisterContextRegisterSpace>
public class DBTraceRegisterContextManager
extends AbstractDBTraceSpaceBasedManager<DBTraceRegisterContextSpace>
implements TraceRegisterContextManager,
DBTraceDelegatingManager<DBTraceRegisterContextSpace> {
public static final String NAME = "RegisterContext";
@ -100,14 +100,14 @@ public class DBTraceRegisterContextManager extends
@Override
protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceRegisterContextSpace(this, dbh, space, ent);
return new DBTraceRegisterContextSpace(this, dbh, space, ent, null);
}
@Override
protected DBTraceRegisterContextRegisterSpace createRegisterSpace(AddressSpace space,
protected DBTraceRegisterContextSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
// TODO: Should I just forbid this? It doesn't seem sane. Then again, what do I know?
return new DBTraceRegisterContextRegisterSpace(this, dbh, space, ent, thread);
return new DBTraceRegisterContextSpace(this, dbh, space, ent, thread);
}
@Override
@ -132,7 +132,7 @@ public class DBTraceRegisterContextManager extends
}
@Override
public DBTraceRegisterContextRegisterSpace getRegisterContextRegisterSpace(TraceThread thread,
public DBTraceRegisterContextSpace getRegisterContextRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}

View File

@ -1,49 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.context;
import java.io.IOException;
import db.DBHandle;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
import ghidra.trace.model.context.TraceRegisterContextRegisterSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.exception.VersionException;
public class DBTraceRegisterContextRegisterSpace extends DBTraceRegisterContextSpace
implements TraceRegisterContextRegisterSpace {
private final TraceThread thread;
private final int frameLevel;
public DBTraceRegisterContextRegisterSpace(DBTraceRegisterContextManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
throws VersionException, IOException {
super(manager, dbh, space, ent);
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
}

View File

@ -81,6 +81,8 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
protected final DBTraceRegisterContextManager manager;
protected final DBHandle dbh;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock;
protected final Language baseLanguage;
protected final DBTrace trace;
@ -91,10 +93,13 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
new HashMap<>();
public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
throws VersionException, IOException {
this.manager = manager;
this.dbh = dbh;
this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace();
@ -129,7 +134,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
@Override
public TraceThread getThread() {
return null;
return thread;
}
protected long getThreadKey() {
@ -139,7 +144,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
@Override
public int getFrameLevel() {
return 0;
return frameLevel;
}
protected String tableName(Language language, Register register) {
@ -152,7 +157,8 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
String name = tableName(lr.getLeft(), lr.getRight());
try {
return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(),
lock, space, DBTraceRegisterContextEntry.class, DBTraceRegisterContextEntry::new);
lock, space, thread, frameLevel, DBTraceRegisterContextEntry.class,
DBTraceRegisterContextEntry::new);
}
catch (IOException e) {
manager.dbError(e);

View File

@ -159,29 +159,8 @@ public class DBTraceDataSettingsAdapter
DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
implements DBTraceDataSettingsOperations {
public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
ReadWriteLock lock, AddressSpace space, Class<DBTraceSettingsEntry> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
throws VersionException, IOException {
super(tableName, storeFactory, lock, space, dataType, dataFactory);
}
@Override
public void makeWay(DBTraceSettingsEntry entry, Range<Long> span) {
DBTraceUtils.makeWay(entry, span, (e, s) -> e.setLifespan(s), e -> deleteData(e));
}
@Override
public ReadWriteLock getLock() {
return lock;
}
}
public class DBTraceDataSettingsRegisterSpace extends
DBTraceAddressSnapRangePropertyMapRegisterSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
implements DBTraceDataSettingsOperations {
public DBTraceDataSettingsRegisterSpace(String tableName,
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
TraceThread thread, int frameLevel, Class<DBTraceSettingsEntry> dataType,
ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
Class<DBTraceSettingsEntry> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
throws VersionException, IOException {
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
@ -206,20 +185,20 @@ public class DBTraceDataSettingsAdapter
}
@Override
protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
protected DBTraceDataSettingsSpace createSpace(
AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceDataSettingsSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()),
trace.getStoreFactory(), lock, space, dataType, dataFactory);
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, null, 0, dataType, dataFactory);
}
@Override
protected DBTraceDataSettingsRegisterSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceDataSettingsRegisterSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()),
trace.getStoreFactory(), lock, space, thread, ent.getFrameLevel(), dataType,
dataFactory);
protected DBTraceDataSettingsSpace createRegisterSpace(
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceDataSettingsSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
}
@Override
@ -228,9 +207,9 @@ public class DBTraceDataSettingsAdapter
}
@Override
public DBTraceDataSettingsRegisterSpace getRegisterSpace(TraceThread thread,
public DBTraceDataSettingsSpace getRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return (DBTraceDataSettingsRegisterSpace) super.getRegisterSpace(thread, createIfAbsent);
return (DBTraceDataSettingsSpace) super.getRegisterSpace(thread, createIfAbsent);
}
@Override

View File

@ -28,42 +28,126 @@ import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.space.DBTraceDelegatingManager;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.LockHold;
/**
* An abstract implementation of {@link TraceBaseCodeUnitsView} for composing views of many address
* spaces
*
* @param <T> the implementation type of the units contained in the view
* @param <M> the implementation type of the views being composed
*/
public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>>
implements DBTraceDelegatingManager<M> {
protected final DBTraceCodeManager manager;
protected final Collection<M> activeSpacesView;
/**
* Construct a composite view
*
* @param manager the code manager, from which individual views are retrieved
*/
public AbstractBaseDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
this.manager = manager;
this.activeSpacesView =
Collections2.transform(manager.getActiveMemorySpaces(), this::getView);
}
/**
* @see TraceBaseCodeUnitsView#getTrace()
*/
public Trace getTrace() {
return manager.getTrace();
}
/**
* @see TraceBaseCodeUnitsView#getThread()
*/
public TraceThread getThread() {
return null;
}
/**
* @see TraceBaseCodeUnitsView#getFrameLevel()
*/
public int getFrameLevel() {
return 0;
}
/**
* Get the individual view from the given space
*
* @param space the space, bound to a specific address space
* @return the view
*/
protected abstract M getView(DBTraceCodeSpace space);
/**
* Create the appropriate unit (possibly caching) when there is no view or space for the given
* address's space
*
* <p>
* Views composing undefined units should generate (possibly delegating to a view) an undefined
* unit. Others should leave this null.
*
* @param snap the snap the client requested
* @param address the address the client requested
* @return the unit or null
*/
protected T nullOrUndefined(long snap, Address address) {
return null;
}
/**
* The address set when there is no view or space for the given range's space
*
* <p>
* Views composing undefined units should return the whole range. Others should leave this
* empty.
*
* @param within the range the client requested
* @return the full range or empty
*/
protected AddressSetView emptyOrFullAddressSetUndefined(AddressRange within) {
return new AddressSet();
}
/**
* The result of contains, covers, or intersects when there is no view or space for an address
* space
*
* <p>
* Views composing undefined units should return true, since the address is known to be in an
* unpopulated space. Others should leave this false.
*
* @return true if an undefined unit implicitly contains the address, false otherwise.
*/
protected boolean falseOrTrueUndefined() {
return false;
}
/**
* The result of iteration when there is no view or space for the given range's space
*
* <p>
* Views composing undefiend units should return an iterable that generates (possibly caching)
* undefined units. Others should leave this empty.
*
* @param snap the snap the client requested
* @param range the range of iteration
* @param forward true to iterate forward (min to max), false for backward (max to min)
* @return the iterator
*/
public Iterable<? extends T> emptyOrFullIterableUndefined(long snap, AddressRange range,
boolean forward) {
return Collections.emptyList();
}
/**
* @see #emptyOrFullIterableUndefined(long, AddressRange, boolean)
*/
public Iterable<? extends T> emptyOrFullIterableUndefined(TraceAddressSnapRange tasr) {
return Collections.emptyList();
}
@ -84,6 +168,16 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return codeSpace == null ? null : getView(codeSpace);
}
/**
* Compute the address preceding the given
*
* <p>
* If this address is the minimum in its space, then this will choose the maximum address of the
* previous space, if it exists.
*
* @param address the address
* @return the previous address or null
*/
protected Address prevAddress(Address address) {
Address prev = address.previous();
if (prev != null) {
@ -108,6 +202,15 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return prevRange.getMaxAddress();
}
/**
* Compute the address following the given
*
* <p>
* If the address is the maximum in its space, then this will choose the minimum address of the
* next space, if it exists.
*
* @return the next address or null
*/
protected Address nextAddress(Address address) {
Address next = address.next();
if (next != null) {
@ -132,6 +235,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return nextRange.getMinAddress();
}
/**
* @see TraceBaseCodeUnitsView#size()
*/
public int size() {
int sum = 0;
for (M m : activeSpacesView) {
@ -140,6 +246,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return sum;
}
/**
* @see TraceBaseCodeUnitsView#getBefore(long, Address)
*/
public T getBefore(long snap, Address address) {
Address prev = prevAddress(address);
if (prev == null) {
@ -148,6 +257,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return getFloor(snap, prev);
}
/**
* @see TraceBaseCodeUnitsView#getFloor(long, Address)
*/
public T getFloor(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) {
for (AddressRange range : DBTraceUtils.getAddressSet(
@ -163,6 +275,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
}
}
/**
* @see TraceBaseCodeUnitsView#getContaining(long, Address)
*/
public T getContaining(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) {
M m = getForSpace(address.getAddressSpace(), false);
@ -173,6 +288,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
}
}
/**
* @see TraceBaseCodeUnitsView#getAt(long, Address)
*/
public T getAt(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) {
M m = getForSpace(address.getAddressSpace(), false);
@ -183,6 +301,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
}
}
/**
* @see TraceBaseCodeUnitsView#getCeiling(long, Address)
*/
public T getCeiling(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) {
for (AddressRange range : DBTraceUtils.getAddressSet(
@ -198,6 +319,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
}
}
/**
* @see TraceBaseCodeUnitsView#getAfter(long, Address)
*/
public T getAfter(long snap, Address address) {
Address next = nextAddress(address);
if (next == null) {
@ -206,6 +330,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return getCeiling(snap, next);
}
/**
* @see TraceBaseCodeUnitsView#get(long, Address, Address, boolean)
*/
public Iterable<? extends T> get(long snap, Address min, Address max, boolean forward) {
if (min.hasSameAddressSpace(max)) {
return get(snap, new AddressRangeImpl(min, max), forward);
@ -214,11 +341,17 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
forward);
}
/**
* @see TraceBaseCodeUnitsView#get(long, AddressSetView, boolean)
*/
public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) {
return () -> NestedIterator.start(set.iterator(forward),
r -> get(snap, r, forward).iterator());
}
/**
* @see TraceBaseCodeUnitsView#get(long, AddressRange, boolean)
*/
public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) {
M m = getForSpace(range.getAddressSpace(), false);
if (m == null) {
@ -227,15 +360,24 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return m.get(snap, range, forward);
}
/**
* @see TraceBaseCodeUnitsView#get(long, Address, boolean)
*/
public Iterable<? extends T> get(long snap, Address start, boolean forward) {
AddressFactory factory = manager.getBaseLanguage().getAddressFactory();
return get(snap, DBTraceUtils.getAddressSet(factory, start, forward), forward);
}
/**
* @see TraceBaseCodeUnitsView#get(long, boolean)
*/
public Iterable<? extends T> get(long snap, boolean forward) {
return get(snap, manager.getBaseLanguage().getAddressFactory().getAddressSet(), forward);
}
/**
* @see TraceBaseCodeUnitsView#getIntersecting(TraceAddressSnapRange)
*/
public Iterable<? extends T> getIntersecting(TraceAddressSnapRange tasr) {
M m = getForSpace(tasr.getX1().getAddressSpace(), false);
if (m == null) {
@ -244,6 +386,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return m.getIntersecting(tasr);
}
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long, AddressRange)
*/
public AddressSetView getAddressSetView(long snap, AddressRange within) {
M m = getForSpace(within.getAddressSpace(), false);
if (m == null) {
@ -252,6 +397,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return m.getAddressSetView(snap, within);
}
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long)
*/
public AddressSetView getAddressSetView(long snap) {
AddressSet result = new AddressSet();
for (AddressRange range : manager.getBaseLanguage().getAddressFactory().getAddressSet()) {
@ -266,26 +414,41 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return result;
}
/**
* @see TraceBaseCodeUnitsView#containsAddress(long, Address)
*/
public boolean containsAddress(long snap, Address address) {
return delegateRead(address.getAddressSpace(), m -> m.containsAddress(snap, address),
falseOrTrueUndefined());
}
/**
* @see TraceBaseCodeUnitsView#coversRange(Range, AddressRange)
*/
public boolean coversRange(Range<Long> span, AddressRange range) {
return delegateRead(range.getAddressSpace(), m -> m.coversRange(span, range),
falseOrTrueUndefined());
}
/**
* @see TraceBaseCodeUnitsView#coversRange(TraceAddressSnapRange)
*/
public boolean coversRange(TraceAddressSnapRange range) {
return delegateRead(range.getRange().getAddressSpace(), m -> m.coversRange(range),
falseOrTrueUndefined());
}
/**
* @see TraceBaseCodeUnitsView#intersectsRange(Range, AddressRange)
*/
public boolean intersectsRange(Range<Long> span, AddressRange range) {
return delegateRead(range.getAddressSpace(), m -> m.intersectsRange(span, range),
falseOrTrueUndefined());
}
/**
* @see TraceBaseCodeUnitsView#intersectsRange(TraceAddressSnapRange)
*/
public boolean intersectsRange(TraceAddressSnapRange range) {
return delegateRead(range.getRange().getAddressSpace(), m -> m.intersectsRange(range),
falseOrTrueUndefined());

View File

@ -21,21 +21,70 @@ import generic.NestedIterator;
import ghidra.program.model.address.*;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
import ghidra.trace.model.thread.TraceThread;
/**
* An abstract implementation of a {@link TraceBaseCodeUnitsView} for a specific address space
*
* <p>
* Note that this class does not declare {@link TraceBaseCodeUnitsView} as an implemented interface,
* thought it does implement it structurally. If it were implemented nominally, the realizations
* would inherit the same interface twice, with different type parameters, which is not allowed.
*
* @param <T> the implementation type of the units contained in the view
*/
public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter> {
protected final DBTraceCodeSpace space;
/**
* Construct a view
*
* @param space the space, bound to an address space
*/
public AbstractBaseDBTraceCodeUnitsView(DBTraceCodeSpace space) {
this.space = space;
}
/**
* Get the address space for this view
*
* @return the address space
*/
protected AddressSpace getAddressSpace() {
return space.space;
}
/**
* @see TraceBaseCodeUnitsView#getTrace()
*/
public Trace getTrace() {
return space.manager.getTrace();
}
/**
* @see TraceBaseCodeUnitsView#getThread()
*/
public TraceThread getThread() {
return space.getThread();
}
/**
* @see TraceBaseCodeUnitsView#getFrameLevel()
*/
public int getFrameLevel() {
return space.getFrameLevel();
}
/**
* @see TraceBaseCodeUnitsView#size()
*/
public abstract int size();
/**
* @see TraceBaseCodeUnitsView#getBefore(long, Address)
*/
public T getBefore(long snap, Address address) {
Address previous = address.previous();
if (previous == null) {
@ -44,14 +93,29 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
return getFloor(snap, previous);
}
/**
* @see TraceBaseCodeUnitsView#getFloor(long, Address)
*/
public abstract T getFloor(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getContaining(long, Address)
*/
public abstract T getContaining(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getAt(long, Address)
*/
public abstract T getAt(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getCeiling(long, Address)
*/
public abstract T getCeiling(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getAfter(long, Address)
*/
public T getAfter(long snap, Address address) {
Address next = address.next();
if (next == null) {
@ -60,50 +124,85 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
return getCeiling(snap, next);
}
public AddressSpace getAddressSpace() {
return space.space;
}
/**
* @see TraceBaseCodeUnitsView#get(long, Address, Address, boolean)
*/
public abstract Iterable<? extends T> get(long snap, Address min, Address max, boolean forward);
/**
* @see TraceBaseCodeUnitsView#getIntersecting(TraceAddressSnapRange)
*/
public abstract Iterable<? extends T> getIntersecting(TraceAddressSnapRange tasr);
/**
* @see TraceBaseCodeUnitsView#get(long, AddressSetView, boolean)
*/
public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) {
return () -> NestedIterator.start(set.iterator(forward),
r -> this.get(snap, r, forward).iterator());
}
/**
* @see TraceBaseCodeUnitsView#get(long, AddressRange, boolean)
*/
public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) {
return get(snap, range.getMinAddress(), range.getMaxAddress(), forward);
}
/**
* @see TraceBaseCodeUnitsView#get(long, Address, boolean)
*/
public Iterable<? extends T> get(long snap, Address start, boolean forward) {
return forward //
? get(snap, start, getAddressSpace().getMaxAddress(), forward)
: get(snap, getAddressSpace().getMinAddress(), start, forward);
}
/**
* @see TraceBaseCodeUnitsView#get(long, boolean)
*/
public Iterable<? extends T> get(long snap, boolean forward) {
return get(snap, getAddressSpace().getMinAddress(), getAddressSpace().getMaxAddress(),
forward);
}
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long, AddressRange)
*/
public abstract AddressSetView getAddressSetView(long snap, AddressRange within);
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long)
*/
public AddressSetView getAddressSetView(long snap) {
return getAddressSetView(snap, space.all);
}
/**
* @see TraceBaseCodeUnitsView#containsAddress(long, Address)
*/
public abstract boolean containsAddress(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#coversRange(Range, AddressRange)
*/
public abstract boolean coversRange(Range<Long> span, AddressRange range);
/**
* @see TraceBaseCodeUnitsView#coversRange(TraceAddressSnapRange)
*/
public boolean coversRange(TraceAddressSnapRange range) {
return coversRange(range.getLifespan(), range.getRange());
}
/**
* @see TraceBaseCodeUnitsView#intersectsRange(Range, AddressRange)
*/
public abstract boolean intersectsRange(Range<Long> span, AddressRange range);
/**
* @see TraceBaseCodeUnitsView#intersectsRange(TraceAddressSnapRange)
*/
public boolean intersectsRange(TraceAddressSnapRange range) {
return intersectsRange(range.getLifespan(), range.getRange());
}

View File

@ -31,12 +31,23 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAdd
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.Trace.TraceCodeChangeType;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceBaseDefinedUnitsView;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.util.LockHold;
import ghidra.util.database.spatial.rect.Rectangle2DDirection;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* An abstract implementation of a single-type view for a defined unit type
*
* <p>
* This is <em>note</em> a base class of {@link DBTraceDefinedUnitsView}. This class supports the
* implementation of one or the other: Instruction or Defined data. {@link DBTraceDefinedUnitsView}
* is the implementation of the composition of both.
*
* @param <T>
*/
public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTraceCodeUnit<T>>
extends AbstractSingleDBTraceCodeUnitsView<T> {
@ -44,6 +55,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
protected final static int CACHE_ADDRESS_BREADTH = 10000;
protected final static int CACHE_MAX_POINTS = 10000;
/**
* Cache for optimizing {@link AbstractBaseDBTraceDefinedUnitsView#getAt(long, Address)}
*/
protected class CacheForGetUnitContainingQueries
extends DBTraceCacheForContainingQueries<GetKey, T, T> {
@ -64,6 +78,10 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
}
};
/**
* Cache for optimizing {@link AbstractBaseDBTraceDefinedUnitsView#getFloor(long, Address)} and
* similar.
*/
protected class CacheForGetUnitSequenceQueries extends DBTraceCacheForSequenceQueries<T> {
public CacheForGetUnitSequenceQueries() {
super(CACHE_MAX_REGIONS, CACHE_ADDRESS_BREADTH);
@ -104,6 +122,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
protected final CacheForGetUnitSequenceQueries cacheForSequence =
new CacheForGetUnitSequenceQueries();
/**
* Construct the view
*
* @param space the space, bound to an address space
* @param mapSpace the map storing the actual code unit entries
*/
public AbstractBaseDBTraceDefinedUnitsView(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapSpace<T, T> mapSpace) {
super(space);
@ -121,6 +145,30 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
return !mapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).isEmpty();
}
/**
* Subtract from cur, the boxes covered by the entries intersecting the given query box
*
* <p>
* Compute C = A - B, where A B and C are sets of (possibly overlapping) boxes. A is given by
* {@code} cur, and B is the set of bounding boxes for entries intersecting the query box. Two
* temporary sets must be provided, and {@code cur} must be identical to one of them. This
* routine will mutate them. The returned result will be identical to one of them.
*
* <p>
* If repeated subtraction is needed, the temporary sets need only be constructed once. For each
* subsequent round of subtraction, {@code cur} should be the returned result of the previous
* round. The final result is the return value of the final round.
*
* <p>
* This is used in the implementation of {@link #coversRange(TraceAddressSnapRange)}.
*
* @param span the lifespan of the query box
* @param range the address range of the query box
* @param cur the set of boxes, identical to one of the temporary working sets.
* @param set1 a temporary set for working
* @param set2 a temporary set for working
* @return the result of subtraction, identical to one of the temporary working sets
*/
protected Set<TraceAddressSnapRange> subtractFrom(Range<Long> span, AddressRange range,
Set<TraceAddressSnapRange> cur, Set<TraceAddressSnapRange> set1,
Set<TraceAddressSnapRange> set2) {
@ -239,6 +287,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
t -> true);
}
/**
* Clear the register context in the given box
*
* @param span the lifespan of the box
* @param range the address range of the box
*/
protected void clearContext(Range<Long> span, AddressRange range) {
DBTraceRegisterContextSpace ctxSpace =
space.trace.getRegisterContextManager().get(space, false);
@ -248,6 +302,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
ctxSpace.clear(span, range);
}
/**
* @see TraceBaseDefinedUnitsView#clear(Range, AddressRange, boolean, TaskMonitor)
*/
public void clear(Range<Long> span, AddressRange range, boolean clearContext,
TaskMonitor monitor) throws CancelledException {
long startSnap = DBTraceUtils.lowerEndpoint(span);
@ -275,6 +332,11 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
}
}
/**
* Notify domain object listeners that a unit was removed
*
* @param unit the removed unit
*/
protected void unitRemoved(T unit) {
cacheForContaining.notifyEntryRemoved(unit.getLifespan(), unit.getRange(), unit);
cacheForSequence.notifyEntryRemoved(unit.getLifespan(), unit.getRange(), unit);
@ -283,6 +345,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
space, unit.getBounds(), unit, null));
}
/**
* Notify domain object listeners taht a unit's lifespan changed
*
* @param oldSpan the old snap
* @param unit the unit (having the new span)
*/
protected void unitSpanChanged(Range<Long> oldSpan, T unit) {
cacheForContaining.notifyEntryShapeChanged(unit.getLifespan(), unit.getRange(), unit);
cacheForSequence.notifyEntryShapeChanged(unit.getLifespan(), unit.getRange(), unit);
@ -291,6 +359,18 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
space, unit, oldSpan, unit.getLifespan()));
}
/**
* Select a sub-lifespan from that given so that the box does not overlap an existing unit
*
* <p>
* The selected lifespan will have the same start snap at that given. The box is the bounding
* box of a unit the client is trying to create.
*
* @param span the lifespan of the box
* @param range the address range of the box
* @return the selected sub-lifespan
* @throws CodeUnitInsertionException if the start snap is contained in an existing unit
*/
protected Range<Long> truncateSoonestDefined(Range<Long> span, AddressRange range)
throws CodeUnitInsertionException {
T truncateBy =
@ -308,6 +388,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
truncateBy.getStartSnap() - 1);
}
/**
* Invalidate the query-optimizing caches for this view
*/
public void invalidateCache() {
cacheForContaining.invalidate();
cacheForSequence.invalidate();

View File

@ -26,20 +26,46 @@ import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeUnit;
import ghidra.util.*;
/**
* An abstract implementation of a multi-type view, by composing other single-type views
*
* @param <T> the implementation type of units contained in the view
* @param <P> the implementation type of views composed by this view
*/
public abstract class AbstractComposedDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter, //
P extends AbstractSingleDBTraceCodeUnitsView<? extends T>>
extends AbstractBaseDBTraceCodeUnitsView<T> {
/**
* Compare two code units for forward iteration
*
* @param a a code unit
* @param b a code unit
* @return as in {@link Comparable#compareTo(Object)}
*/
protected static int compareForward(TraceCodeUnit a, TraceCodeUnit b) {
return a.getMinAddress().compareTo(b.getMinAddress());
}
/**
* Compare two code units for backward iteration
*
* @param a a code unit
* @param b a code unit
* @return as in {@link Comparable#compareTo(Object)}
*/
protected static int compareBackward(TraceCodeUnit a, TraceCodeUnit b) {
return b.getMaxAddress().compareTo(a.getMaxAddress());
}
protected final Collection<P> parts;
/**
* Construct a view
*
* @param space the space, bound to an address space
* @param parts the single-type views composed
*/
public AbstractComposedDBTraceCodeUnitsView(DBTraceCodeSpace space, Collection<P> parts) {
super(space);
this.parts = parts;

View File

@ -29,6 +29,15 @@ import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.LockHold;
import ghidra.util.database.DBCachedObjectStore;
/**
* An abstract implementation of a table-backed code unit
*
* <p>
* This is implemented as a data entry in an address-snap-range property map. This is not suitable
* for data components, nor for undefined units.
*
* @param <T> the implementation type of this unit
*/
public abstract class AbstractDBTraceCodeUnit<T extends AbstractDBTraceCodeUnit<T>> extends
AbstractDBTraceAddressSnapRangePropertyMapData<T> implements DBTraceCodeUnitAdapter {
@ -36,6 +45,14 @@ public abstract class AbstractDBTraceCodeUnit<T extends AbstractDBTraceCodeUnit<
protected ByteBuffer byteCache; // NOTE: Memory cannot be changed under a code unit
/**
* Construct a code unit
*
* @param space the space
* @param tree the storage R*-Tree
* @param store the object store
* @param record the record
*/
public AbstractDBTraceCodeUnit(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapTree<T, ?> tree, DBCachedObjectStore<?> store,
DBRecord record) {

View File

@ -26,9 +26,19 @@ import ghidra.program.model.lang.Language;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.data.DBTraceDataSettingsAdapter.DBTraceDataSettingsSpace;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceData;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.LockHold;
/**
* An abstract implementation of a {@link TraceData} for a data component, i.e., field of a struct
* or element of an array
*
* <p>
* These are not backed directly by a table. The root data unit, along with its type, is stored in
* the table. If the type is composite, then these are generated, possibly recursively, for the
* components therein.
*/
public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedDataAdapter {
protected final DBTraceData root;
@ -47,6 +57,16 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
protected AbstractDBTraceDataComponent[] componentCache = null;
/**
* Create a data component
*
* @param root the root data unit
* @param parent the parent component, possibly the root
* @param index the index of this component in its parent
* @param address the minimum address of this component
* @param dataType the data type of this component
* @param length the length of this component
*/
public AbstractDBTraceDataComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
int index, Address address, DataType dataType, int length) {
this.root = root;
@ -173,6 +193,7 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
/**
* {@inheritDoc}
*
* <p>
* In other words, this includes the symbol name of the root unit; whereas,
* {@link #getComponentPathName()} omits it.
*/
@ -184,6 +205,7 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
/**
* {@inheritDoc}
*
* <p>
* In other words, this omits the symbol name of the root unit; whereas, {@link #getPathName()}
* includes it.
*/

View File

@ -15,9 +15,22 @@
*/
package ghidra.trace.database.listing;
/**
* An abstract implementation of a single-type view
*
* @implNote This class cannot be removed. Despite it appearing not to do anything, this class
* serves as an upper bound on the views composed by
* {@link AbstractComposedDBTraceCodeUnitsView}.
* @param <T> the implementation type of the units contained in the view
*/
public abstract class AbstractSingleDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter>
extends AbstractBaseDBTraceCodeUnitsView<T> {
/**
* Construct a view
*
* @param space the space, bound to an address space
*/
public AbstractSingleDBTraceCodeUnitsView(DBTraceCodeSpace space) {
super(space);
}

View File

@ -22,16 +22,24 @@ import com.google.common.collect.Iterators;
import ghidra.program.model.address.*;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
/**
* TODO: Document me
* An abstract implementation of {@link TraceBaseCodeUnitsView} for composing views of many address
* spaces, where the views include undefined units
*
* @param <T> type of units in the view. Must be a super-type of {@link UndefinedDBTraceData}.
* @param <M>
* @param <T> the implementation type of the units contained in the view. Must be a super-type of
* {@link UndefinedDBTraceData}.
* @param <M> the implementation type of the views being composed
*/
public abstract class AbstractWithUndefinedDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>>
extends AbstractBaseDBTraceCodeUnitsMemoryView<T, M> {
/**
* Construct a composite view
*
* @param manager the code manager, from which individual views are retrieved
*/
public AbstractWithUndefinedDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -32,8 +32,7 @@ import db.DBRecord;
import ghidra.lifecycle.Internal;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.ContextChangeException;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.ByteMemBufferImpl;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.util.ProgramContextImpl;
@ -52,8 +51,7 @@ import ghidra.trace.database.symbol.DBTraceReferenceManager;
import ghidra.trace.database.thread.DBTraceThreadManager;
import ghidra.trace.model.AddressSnap;
import ghidra.trace.model.DefaultAddressSnap;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.*;
import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
@ -64,8 +62,119 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceCodeManager
extends AbstractDBTraceSpaceBasedManager<DBTraceCodeSpace, DBTraceCodeRegisterSpace>
/**
* The implementation of {@link TraceCodeManager} for {@link DBTrace}
*
* <p>
* The "fluent" interfaces actually create quite a burden to implement here; however, we have some
* opportunity to extract common code among the various views. There are a few concepts and nuances
* to consider in order to handle all the fluent cases. The manager implements
* {@link TraceCodeOperations} directly, which means it must provide a version of each
* {@link TraceCodeUnitsView} that composes all memory address spaces. These are named with the
* suffix {@code MemoryView} and extend {@link AbstractBaseDBTraceCodeUnitsMemoryView}.
*
* <p>
* In addition, in order to support {@link #getCodeSpace(AddressSpace, boolean)}, it must provide a
* version of each that can be bound to a single memory address space. Same for
* {@link #getCodeRegisterSpace(TraceThread, int, boolean)}. These are named with the suffix
* {@code View} and extend {@link AbstractBaseDBTraceCodeUnitsView}.
*
* <p>
* Furthermore, there are three types of views:
*
* <ol>
* <li>Those defined by a table, i.e., defined data and instructions. These extend
* {@link AbstractBaseDBTraceDefinedUnitsView}.</li>
* <li>Those defined implicitly, but may have a support table, i.e., undefined units. This is
* implemented by {@link DBTraceUndefinedDataView}.</li>
* <li>Those defined as the composition of others, i.e., data and defined units. These extend
* {@link AbstractComposedDBTraceCodeUnitsView}.</li>
* </ol>
*
* <p>
* The first two types represent a view of a single code unit type, so they both extend
* {@link AbstractSingleDBTraceCodeUnitsView}.
*
* <p>
* The abstract classes do not nominally implement the trace manager's
* {@link TraceBaseCodeUnitsView} nor {@link TraceBaseDefinedUnitsView} interfaces, because Java
* prevents the (nominal) implementation of the same interface with different type parameters by the
* same class. E.g., {@link DBTraceDataView} would inherit
* {@code TraceBaseCodeUnitsView<DBTraceData>} via {@link AbstractBaseDBTraceCodeUnitsView}, but
* also {@code TraceBaseCodeUnitsView<TraceDataUnit>} via {@link TraceDataView}. Instead, the
* abstract classes <em>structurally</em> implement those interfaces, meaning they implement the
* methods required by the interface, but without naming the interface in their `implements` clause.
* The realizations, e.g., {@link DBTraceDataView}, <em>nominally</em> implement their corresponding
* interfaces, meaning they do name the interface. Each realization will inherit the structural
* implementation from the abstract classes, satisfying the requirements imposed by nominally
* implementing the interface.
*
* <p>
* Note, as a result, navigating from declarations in the interfaces to implementations in abstract
* classes using your IDE may not work as expected :/ . The best way is probably to display the type
* hierarchy of the interface declaring the desired method. Open one of the classes implementing it,
* then display all its methods, including those inherited, and search for desired method.
*
* <p>
* Here is the type hierarchy presented with notes regarding structural interface implementations:
* <ul>
* <li>{@link AbstractBaseDBTraceCodeUnitsView} structurally implements
* {@link TraceBaseCodeUnitsView}</li>
* <ul>
* <li>{@link AbstractComposedDBTraceCodeUnitsView}</li>
* <ul>
* <li>{@link DBTraceCodeUnitsView} nominally implements {@link TraceCodeUnitsView}</li>
* <li>{@link DBTraceDataView} nominally implements {@link TraceDataView}</li>
* <li>{@link DBTraceDefinedUnitsView} nominally implements {@link TraceDefinedUnitsView}</li>
* </ul>
* <li>{@link AbstractSingleDBTraceCodeUnitsView}</li>
* <ul>
* <li>{@link AbstractBaseDBTraceDefinedUnitsView} structurally implements
* {@link TraceBaseDefinedUnitsView}</li>
* <ul>
* <li>{@link DBTraceDefinedDataView} nominally implements {@link TraceDefinedDataView}</li>
* <li>{@link DBTraceInstructionsView} nominally implements {@link TraceInstructionsView}</li>
* </ul>
* <li>{@link DBTraceUndefinedDataView} nominally implements {@link TraceUndefinedDataView}</li>
* </ul>
* </ul>
*
* <p>
* The view composition is not hierarchical, as each may represent a different combination, and one
* type may appear in several compositions. The single-type views are named first, then the composed
* views:
* <ul>
* <li>Instructions - single-type view</li>
* <li>Defined Data - single-type view</li>
* <li>Undefined Data - single-type view</li>
* </ul>
*
* <p>
* Note that while the API presents separate views for defined data and undefined units, both are
* represented by the type {@link TraceData}. Meaning, a client with a data unit in hand cannot
* determine whether it is defined or undefined from its type alone. It must invoke
* {@link Data#isDefined()} instead. While the implementation provides a separate type, which we see
* mirrors the hierarchy of the views' implementation, the client interfaces do not.
*
* <ul>
* <li>Code Units - Instructions, Defined Data, Undefined Data</li>
* <li>Data - Defined Data, Undefined Data</li>
* <li>Defined Units - Instructions, Defined Data</li>
* </ul>
*
* <p>
* The {@code MemoryView} classes compose the memory address spaces into a single view. These need
* not mirror the same implementation hierarchy as the views they compose. Other than special
* handling for compositions including undefined units, each memory view need not know anything
* about the views it composes. There are two abstract classes:
* {@link AbstractBaseDBTraceCodeUnitsMemoryView}, which is suitable for composing views without
* undefined units, and {@link AbstractWithUndefinedDBTraceCodeUnitsMemoryView}, which extends the
* base making it suitable for composing views with undefined units. The realizations each extend
* from the appropriate abstract class. Again, the abstract classes do not nominally implement
* {@link TraceBaseCodeUnitsView}. They structurally implement it, partly satisfying the
* requirements on the realizations, which nominally implement their appropriate interfaces.
*/
public class DBTraceCodeManager extends AbstractDBTraceSpaceBasedManager<DBTraceCodeSpace>
implements TraceCodeManager, DBTraceDelegatingManager<DBTraceCodeSpace> {
public static final String NAME = "Code";
@ -302,13 +411,13 @@ public class DBTraceCodeManager
@Override
protected DBTraceCodeSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceCodeSpace(this, dbh, space, ent);
return new DBTraceCodeSpace(this, dbh, space, ent, null);
}
@Override
protected DBTraceCodeRegisterSpace createRegisterSpace(AddressSpace space, TraceThread thread,
protected DBTraceCodeSpace createRegisterSpace(AddressSpace space, TraceThread thread,
DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceCodeRegisterSpace(this, dbh, space, ent, thread);
return new DBTraceCodeSpace(this, dbh, space, ent, thread);
}
@Override
@ -337,19 +446,19 @@ public class DBTraceCodeManager
}
@Override
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceThread thread,
public DBTraceCodeSpace getCodeRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}
@Override
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceThread thread, int frameLevel,
public DBTraceCodeSpace getCodeRegisterSpace(TraceThread thread, int frameLevel,
boolean createIfAbsent) {
return getForRegisterSpace(thread, frameLevel, createIfAbsent);
}
@Override
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceStackFrame frame,
public DBTraceCodeSpace getCodeRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent);
}
@ -378,7 +487,7 @@ public class DBTraceCodeManager
for (DBTraceCodeSpace codeSpace : memSpaces.values()) {
codeSpace.clearPlatform(Range.all(), codeSpace.all, guest, monitor);
}
for (DBTraceCodeRegisterSpace codeSpace : regSpaces.values()) {
for (DBTraceCodeSpace codeSpace : regSpaces.values()) {
// TODO: I don't know any way to get guest instructions into register space
// The mapping manager does (should) not allow guest register addresses
// TODO: Test this if I ever get guest data units

View File

@ -1,107 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import java.io.IOException;
import db.DBHandle;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
import ghidra.trace.model.listing.TraceCodeRegisterSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.exception.VersionException;
public class DBTraceCodeRegisterSpace extends DBTraceCodeSpace implements TraceCodeRegisterSpace {
protected final TraceThread thread;
private final int frameLevel;
public DBTraceCodeRegisterSpace(DBTraceCodeManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
super(manager, dbh, space, ent);
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
@Override
protected DBTraceInstructionsRegisterView createInstructionsView() {
return new DBTraceInstructionsRegisterView(this);
}
@Override
protected DBTraceDefinedDataRegisterView createDefinedDataView() {
return new DBTraceDefinedDataRegisterView(this);
}
@Override
protected DBTraceDefinedUnitsRegisterView createDefinedUnitsView() {
return new DBTraceDefinedUnitsRegisterView(this);
}
@Override
protected DBTraceUndefinedDataRegisterView createUndefinedDataView() {
return new DBTraceUndefinedDataRegisterView(this);
}
@Override
protected DBTraceDataRegisterView createDataView() {
return new DBTraceDataRegisterView(this);
}
@Override
protected DBTraceCodeUnitsRegisterView createCodeUnitsView() {
return new DBTraceCodeUnitsRegisterView(this);
}
@Override
public DBTraceCodeUnitsRegisterView codeUnits() {
return (DBTraceCodeUnitsRegisterView) codeUnits;
}
@Override
public DBTraceInstructionsRegisterView instructions() {
return (DBTraceInstructionsRegisterView) instructions;
}
@Override
public DBTraceDataRegisterView data() {
return (DBTraceDataRegisterView) data;
}
@Override
public DBTraceDefinedDataRegisterView definedData() {
return (DBTraceDefinedDataRegisterView) definedData;
}
@Override
public DBTraceUndefinedDataRegisterView undefinedData() {
return (DBTraceUndefinedDataRegisterView) undefinedData;
}
@Override
public DBTraceDefinedUnitsRegisterView definedUnits() {
return (DBTraceDefinedUnitsRegisterView) definedUnits;
}
}

View File

@ -39,6 +39,7 @@ import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpace
import ghidra.trace.database.space.DBTraceSpaceBased;
import ghidra.trace.database.symbol.DBTraceReferenceManager;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.ByteArrayUtils;
@ -48,10 +49,19 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
* A space managed by the {@link DBTraceCodeManager}
*
* <p>
* This implements {@link TraceCodeManager#getCodeSpace(AddressSpace, boolean)} and
* {@link TraceCodeManager#getCodeRegisterSpace(TraceThread, int, boolean)}.
*/
public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
protected final DBTraceCodeManager manager;
protected final DBHandle dbh;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock;
protected final Language baseLanguage;
protected final DBTrace trace;
@ -70,11 +80,24 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
protected DBTraceDefinedUnitsView definedUnits;
protected DBTraceCodeUnitsView codeUnits;
/**
* Construct a space
*
* @param manager the manager
* @param dbh the database handle
* @param space the address space
* @param ent an entry describing this space
* @param thread a thread, if applicable, for a per-thread/frame space
* @throws VersionException if there is already a table of a different version
* @throws IOException if there is trouble accessing the database
*/
public DBTraceCodeSpace(DBTraceCodeManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws VersionException, IOException {
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
this.manager = manager;
this.dbh = dbh;
this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace();
@ -88,10 +111,10 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
int frameLevel = ent.getFrameLevel();
instructionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceInstruction.tableName(space, threadKey), factory, lock, space,
DBTraceInstruction.tableName(space, threadKey), factory, lock, space, null, 0,
DBTraceInstruction.class, (t, s, r) -> new DBTraceInstruction(this, t, s, r));
dataMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceData.tableName(space, threadKey, frameLevel), factory, lock, space,
DBTraceData.tableName(space, threadKey, frameLevel), factory, lock, space, null, 0,
DBTraceData.class, (t, s, r) -> new DBTraceData(this, t, s, r));
instructions = createInstructionsView();
@ -102,30 +125,57 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
codeUnits = createCodeUnitsView(); // dep: instructions,definedData,undefinedData
}
/**
* A factory method for the instructions view
*/
protected DBTraceInstructionsView createInstructionsView() {
return new DBTraceInstructionsView(this);
}
/**
* A factory method for the defined data view
*/
protected DBTraceDefinedDataView createDefinedDataView() {
return new DBTraceDefinedDataView(this);
}
/**
* A factory method for the defined units view
*/
protected DBTraceDefinedUnitsView createDefinedUnitsView() {
return new DBTraceDefinedUnitsView(this);
}
/**
* A factory method for the undefined data view
*/
protected DBTraceUndefinedDataView createUndefinedDataView() {
return new DBTraceUndefinedDataView(this);
}
/**
* A factory method for the data view
*/
protected DBTraceDataView createDataView() {
return new DBTraceDataView(this);
}
/**
* A factory method for the code units view
*/
protected DBTraceCodeUnitsView createCodeUnitsView() {
return new DBTraceCodeUnitsView(this);
}
/**
* Clear all units belonging to the given guest platform
*
* @param span the lifespan
* @param range the address range
* @param guest the guest platform
* @param monitor a monitor for progress
* @throws CancelledException if the monitor was cancelled
*/
void clearPlatform(Range<Long> span, AddressRange range, DBTraceGuestPlatform guest,
TaskMonitor monitor) throws CancelledException {
// Note "makeWay" does not apply here.
@ -170,12 +220,12 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
@Override
public TraceThread getThread() {
return null;
return thread;
}
@Override
public int getFrameLevel() {
return 0;
return frameLevel;
}
@Override
@ -221,6 +271,20 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
}
}
/**
* Notify this space that some bytes have changed
*
* <p>
* If any unit(s) contained the changed bytes, they may need to be truncated, deleted, and/or
* replaced. Instructions are generally truncated or deleted without replacement. A data unit
* may be replaced if its length would match that of the original.
*
* @param changed the boxes whose bytes changed
* @param snap the snap where the client requested the change
* @param start the starting address where the client requested the change
* @param oldBytes the old bytes
* @param newBytes the new bytes
*/
public void bytesChanged(Set<TraceAddressSnapRange> changed, long snap, Address start,
byte[] oldBytes, byte[] newBytes) {
AddressSet diffs = ByteArrayUtils.computeDiffsAddressSet(start, oldBytes, newBytes);

View File

@ -44,6 +44,13 @@ import ghidra.util.Saveable;
import ghidra.util.exception.NoValueException;
import ghidra.util.prop.PropertyVisitor;
/**
* A base interface for implementations of {@link TraceCodeUnit}
*
* <p>
* This behaves somewhat like a mixin, allowing it to be used on code units as well as data
* components, e.g., fields of a struct data unit.
*/
public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferAdapter {
@Override

View File

@ -16,11 +16,21 @@
package ghidra.trace.database.listing;
import ghidra.program.model.address.*;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceCodeUnitsView;
/**
* The implementation of {@link TraceCodeManager#codeUnits()}
*/
public class DBTraceCodeUnitsMemoryView extends
AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceCodeUnitAdapter, DBTraceCodeUnitsView>
implements TraceCodeUnitsView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -1,31 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceCodeUnitsRegisterView;
import ghidra.trace.model.thread.TraceThread;
public class DBTraceCodeUnitsRegisterView extends DBTraceCodeUnitsView
implements TraceCodeUnitsRegisterView {
public DBTraceCodeUnitsRegisterView(DBTraceCodeSpace space) {
super(space);
}
@Override
public TraceThread getThread() {
return space.getThread();
}
}

View File

@ -20,12 +20,21 @@ import java.util.List;
import com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceCodeUnitsView;
/**
* The implementation of {@link TraceCodeSpace#codeUnits()}
*/
public class DBTraceCodeUnitsView extends
AbstractComposedDBTraceCodeUnitsView<DBTraceCodeUnitAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceCodeUnitAdapter>>
implements TraceCodeUnitsView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceCodeUnitsView(DBTraceCodeSpace space) {
super(space, List.of(space.instructions, space.definedData, space.undefinedData));
}

View File

@ -27,6 +27,7 @@ import db.DBRecord;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Listing;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.listing.DBTraceCommentAdapter.DBTraceCommentEntry;
@ -46,12 +47,18 @@ import ghidra.util.database.annot.*;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
/**
* A property map for storing code unit comments
*/
public class DBTraceCommentAdapter
extends DBTraceAddressSnapRangePropertyMap<DBTraceCommentEntry, DBTraceCommentEntry> {
protected static final String[] EMPTY_STRING_ARRAY = new String[] {};
protected static final int MIN_COMMENT_TYPE = CodeUnit.EOL_COMMENT;
protected static final int MAX_COMMENT_TYPE = CodeUnit.REPEATABLE_COMMENT;
/**
* A comment entry
*/
@DBAnnotatedObjectInfo(version = 0)
public static class DBTraceCommentEntry
extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceCommentEntry> {
@ -99,6 +106,9 @@ public class DBTraceCommentAdapter
}
}
/**
* Construct the adapter
*/
public DBTraceCommentAdapter(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
DBTraceThreadManager threadManager) throws IOException, VersionException {
@ -106,10 +116,27 @@ public class DBTraceCommentAdapter
DBTraceCommentEntry.class, DBTraceCommentEntry::new);
}
/**
* Truncate or delete and existing comment entry
*
* <p>
* It is assumed the entry intersects some implied address range.
*
* @param entry the entry to truncate or delete
* @param span the span that must be clear
*/
protected void makeWay(DBTraceCommentEntry entry, Range<Long> span) {
DBTraceUtils.makeWay(entry, span, (e, s) -> e.setLifespan(s), e -> deleteData(e));
}
/**
* Set a comment at the given address for the given lifespan
*
* @param lifespan the lifespan
* @param address the address
* @param commentType the type of comment as in {@link Listing#setComment(Address, int, String)}
* @param comment the comment
*/
public void setComment(Range<Long> lifespan, Address address, int commentType, String comment) {
if (commentType < MIN_COMMENT_TYPE || commentType > MAX_COMMENT_TYPE) {
throw new IllegalArgumentException("commentType");
@ -138,14 +165,34 @@ public class DBTraceCommentAdapter
oldValue, comment));
}
/**
* Construct a comment from an array of lines
*
* @param comment the lines or null
* @return the comment text or null
*/
public static String commentFromArray(String[] comment) {
return comment == null || comment.length == 0 ? null : StringUtils.join(comment, '\n');
}
/**
* Split a comment into an array of lines
*
* @param comment the comment text or null
* @return the array of lines or null
*/
public static String[] arrayFromComment(String comment) {
return comment == null || comment.length() == 0 ? EMPTY_STRING_ARRAY : comment.split("\n");
}
/**
* Get the comment at the given point
*
* @param snap the snap
* @param address the address
* @param commentType the type of comment
* @return the comment text
*/
public String getComment(long snap, Address address, int commentType) {
try (LockHold hold = LockHold.lock(lock.readLock())) {
for (DBTraceCommentEntry entry : reduce(
@ -160,10 +207,10 @@ public class DBTraceCommentAdapter
}
/**
* TODO: Document me
* Clear all comments in the given box of the given type
*
* @param span
* @param range
* @param span the lifespan fo the box
* @param range the address range of the box
* @param commentType a comment type to clear, or {@link CodeUnit#NO_COMMENT} to clear all.
*/
public void clearComments(Range<Long> span, AddressRange range, int commentType) {

View File

@ -24,16 +24,21 @@ import ghidra.docking.settings.Settings;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.Language;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.data.DBTraceDataSettingsOperations;
import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceData;
import ghidra.util.LockHold;
import ghidra.util.database.DBCachedObjectStore;
import ghidra.util.database.DBObjectColumn;
import ghidra.util.database.annot.*;
/**
* The implementation for a defined {@link TraceData} for {@link DBTrace}
*/
@DBAnnotatedObjectInfo(version = 0)
public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
implements DBTraceDefinedDataAdapter {
@ -63,6 +68,14 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
protected AbstractDBTraceDataComponent[] componentCache = null;
/**
* Construct a data unit
*
* @param space the space
* @param tree the storage R*-Tree
* @param store the object store
* @param record the record
*/
public DBTraceData(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapTree<DBTraceData, ?> tree,
DBCachedObjectStore<?> store, DBRecord record) {
@ -102,6 +115,12 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
return this;
}
/**
* Set the fields of this record
*
* @param platform the platform
* @param dataType the data type
*/
protected void set(InternalTracePlatform platform, DataType dataType) {
this.platformKey = platform.getIntKey();
this.dataTypeID = space.dataTypeManager.getResolvedID(dataType);
@ -115,6 +134,11 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
this.baseDataType = getBaseDataType(this.dataType);
}
/**
* If this unit's data type has a fixed length, get that length
*
* @return the length, or -1
*/
protected int getDataTypeLength() {
if (baseDataType instanceof Pointer) {
// TODO: Also need to know where this address maps into the other language's spaces....
@ -125,6 +149,12 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
return dataType.getLength(); // -1 is checked elsewhere
}
/**
* Get the base data type of the given data type, following typedefs recursively
*
* @param dt the data type
* @return the base data type
*/
public static DataType getBaseDataType(DataType dt) {
if (dt instanceof TypeDef) {
return ((TypeDef) dt).getBaseDataType();

View File

@ -31,6 +31,13 @@ import ghidra.trace.model.symbol.TraceReference;
import ghidra.trace.util.*;
import ghidra.util.LockHold;
/**
* A base interface for implementations of {@link TraceData}
*
* <p>
* This behaves somewhat like a mixin, allowing it to be used on data units as well as data
* components, e.g., fields of a struct data unit.
*/
public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterMinimal,
DataAdapterFromDataType, DataAdapterFromSettings, TraceData {
static String[] EMPTY_STRING_ARRAY = new String[] {};
@ -67,6 +74,12 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM
}
}
/**
* Get the same space from the internal settings adapter
*
* @param createIfAbsent true to create the space if its not already present
* @return the space or null
*/
DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent);
@Override

View File

@ -17,11 +17,26 @@ package ghidra.trace.database.listing;
import ghidra.program.model.address.*;
import ghidra.program.model.data.DataType;
import ghidra.trace.database.DBTrace;
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.util.TraceAddressSpace;
/**
* The implementation of an array-element data component in a {@link DBTrace}
*/
public class DBTraceDataArrayElementComponent extends AbstractDBTraceDataComponent {
/**
* Create an array element
*
* @param root the root data unit
* @param parent the parent component, possibly the root
* @param index the index of this component in its parent
* @param address the minimum address of this component
* @param dataType the data type of this component
* @param length the length of this component
*/
public DBTraceDataArrayElementComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
int index, Address address, DataType dataType, int length) {
super(root, parent, index, address, dataType, length);

View File

@ -17,13 +17,26 @@ package ghidra.trace.database.listing;
import ghidra.program.model.address.*;
import ghidra.program.model.data.DataTypeComponent;
import ghidra.trace.database.DBTrace;
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.util.TraceAddressSpace;
/**
* The implementation of a field data component in a {@link DBTrace}
*/
public class DBTraceDataCompositeFieldComponent extends AbstractDBTraceDataComponent {
protected final DataTypeComponent dtc;
/**
* Create a field
*
* @param root the root data unit
* @param parent the parent component, possibly the root
* @param index the index of this component in its parent
* @param address the minimum address of this component
* @param dtc the data type component, giving the index, data type, and length
*/
public DBTraceDataCompositeFieldComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
Address address, DataTypeComponent dtc) {
super(root, parent, dtc.getOrdinal(), address, dtc.getDataType(), dtc.getLength());

View File

@ -15,11 +15,21 @@
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceDataView;
/**
* The implementation of {@link TraceCodeManager#data()}
*/
public class DBTraceDataMemoryView
extends AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceDataAdapter, DBTraceDataView>
implements TraceDataView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceDataMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -1,30 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceDataRegisterView;
import ghidra.trace.model.thread.TraceThread;
public class DBTraceDataRegisterView extends DBTraceDataView implements TraceDataRegisterView {
public DBTraceDataRegisterView(DBTraceCodeSpace space) {
super(space);
}
@Override
public TraceThread getThread() {
return space.getThread();
}
}

View File

@ -20,11 +20,21 @@ import java.util.List;
import com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceDataView;
/**
* The implementation of {@link TraceCodeSpace#data()}
*/
public class DBTraceDataView extends
AbstractComposedDBTraceCodeUnitsView<DBTraceDataAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceDataAdapter>>
implements TraceDataView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceDataView(DBTraceCodeSpace space) {
super(space, List.of(space.definedData, space.undefinedData));
}

View File

@ -20,9 +20,17 @@ import java.util.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Data;
import ghidra.trace.model.listing.TraceData;
import ghidra.util.LockHold;
import ghidra.util.Msg;
/**
* A base interface for implementations of {@link TraceData}
*
* <p>
* This behaves somewhat like a mixin, allowing it to be used on defined data units as well as data
* components, e.g., fields of a struct data unit.
*/
public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
@Override
@ -121,7 +129,7 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
default DBTraceDefinedDataAdapter getComponentAt(int offset) {
return getComponentContaining(offset);
}
@Override
default DBTraceDefinedDataAdapter getComponentContaining(int offset) {
// We may write to the cache

View File

@ -21,13 +21,23 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.data.DataType;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceDefinedDataView;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeManager#definedData()}
*/
public class DBTraceDefinedDataMemoryView
extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceData, DBTraceDefinedDataView>
implements TraceDefinedDataView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceDefinedDataMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -1,31 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceDefinedDataRegisterView;
import ghidra.trace.model.thread.TraceThread;
public class DBTraceDefinedDataRegisterView extends DBTraceDefinedDataView
implements TraceDefinedDataRegisterView {
public DBTraceDefinedDataRegisterView(DBTraceCodeSpace space) {
super(space);
}
@Override
public TraceThread getThread() {
return space.getThread();
}
}

View File

@ -27,12 +27,21 @@ import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.Trace.TraceCodeChangeType;
import ghidra.trace.model.Trace.TraceCompositeDataChangeType;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceDefinedDataView;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.util.LockHold;
/**
* The implementation of {@link TraceCodeSpace#definedData()}
*/
public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceData>
implements TraceDefinedDataView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceDefinedDataView(DBTraceCodeSpace space) {
super(space, space.dataMapSpace);
}
@ -43,6 +52,15 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
return create(lifespan, address, dataType, dataType.getLength());
}
/**
* Check if the given data type represents a function definition
*
* <p>
* This recursively resolves typedefs and checks each.
*
* @param dt the data type
* @return true if it is a function definition, false otherwise
*/
protected boolean isFunctionDefinition(DataType dt) {
if (dt instanceof FunctionDefinition) {
return true;

View File

@ -18,13 +18,23 @@ package ghidra.trace.database.listing;
import com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceDefinedUnitsView;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeManager#definedUnits()}
*/
public class DBTraceDefinedUnitsMemoryView extends
AbstractBaseDBTraceCodeUnitsMemoryView<AbstractDBTraceCodeUnit<?>, DBTraceDefinedUnitsView>
implements TraceDefinedUnitsView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceDefinedUnitsMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -1,31 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceDefinedUnitsRegisterView;
import ghidra.trace.model.thread.TraceThread;
public class DBTraceDefinedUnitsRegisterView extends DBTraceDefinedUnitsView
implements TraceDefinedUnitsRegisterView {
public DBTraceDefinedUnitsRegisterView(DBTraceCodeSpace space) {
super(space);
}
@Override
public TraceThread getThread() {
return space.getThread();
}
}

View File

@ -22,15 +22,24 @@ import com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceDefinedUnitsView;
import ghidra.util.LockHold;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeSpace#data()}
*/
public class DBTraceDefinedUnitsView extends
AbstractComposedDBTraceCodeUnitsView<AbstractDBTraceCodeUnit<?>, AbstractBaseDBTraceDefinedUnitsView<? extends AbstractDBTraceCodeUnit<?>>>
implements TraceDefinedUnitsView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceDefinedUnitsView(DBTraceCodeSpace space) {
super(space, List.of(space.instructions, space.definedData));
}

View File

@ -29,6 +29,7 @@ import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.context.DBTraceRegisterContextManager;
import ghidra.trace.database.context.DBTraceRegisterContextSpace;
@ -48,6 +49,9 @@ import ghidra.util.database.DBCachedObjectStore;
import ghidra.util.database.DBObjectColumn;
import ghidra.util.database.annot.*;
/**
* The implementation of {@link TraceInstruction} for {@link DBTrace}
*/
@DBAnnotatedObjectInfo(version = 0)
public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstruction> implements
TraceInstruction, InstructionAdapterFromPrototype, InstructionContext {
@ -76,6 +80,9 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0);
}
/**
* A context for guest instructions that maps addresses appropriately
*/
protected class GuestInstructionContext implements InstructionContext {
@Override
public Address getAddress() {
@ -121,12 +128,25 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
protected InternalTracePlatform platform;
protected InstructionContext instructionContext;
/**
* Construct an instruction unit
*
* @param space the space
* @param tree the storage R*-Tree
* @param store the object store
* @param record the record
*/
public DBTraceInstruction(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapTree<DBTraceInstruction, ?> tree,
DBCachedObjectStore<?> store, DBRecord record) {
super(space, tree, store, record);
}
/**
* At load/create time: set the platform and context (which may map addresses)
*
* @param platform the platform
*/
protected void doSetPlatformMapping(final InternalTracePlatform platform) {
this.platform = platform;
if (platform.isHost()) {
@ -137,6 +157,13 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
}
}
/**
* Set the fields of this record
*
* @param platform the platform
* @param prototype the instruction prototype
* @param context the context for locating or creating the prototype entry
*/
protected void set(InternalTracePlatform platform, InstructionPrototype prototype,
ProcessorContextView context) {
this.platformKey = platform.getIntKey();

View File

@ -25,14 +25,24 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceInstructionsView;
import ghidra.util.LockHold;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeManager#definedData()}
*/
public class DBTraceInstructionsMemoryView
extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceInstruction, DBTraceInstructionsView>
implements TraceInstructionsView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceInstructionsMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -1,32 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceInstructionsRegisterView;
import ghidra.trace.model.thread.TraceThread;
public class DBTraceInstructionsRegisterView extends DBTraceInstructionsView
implements TraceInstructionsRegisterView {
public DBTraceInstructionsRegisterView(DBTraceCodeSpace space) {
super(space);
}
@Override
public TraceThread getThread() {
return space.getThread();
}
}

View File

@ -35,14 +35,16 @@ import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.Trace.TraceCodeChangeType;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceInstruction;
import ghidra.trace.model.listing.TraceInstructionsView;
import ghidra.trace.model.listing.*;
import ghidra.trace.util.OverlappingObjectIterator;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.util.LockHold;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeSpace#instructions()}
*/
public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceInstruction>
implements TraceInstructionsView {
@ -50,6 +52,9 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
return rep != null ? rep : cur;
}
/**
* A mechanism for adding a block of instructions
*/
protected class InstructionBlockAdder {
private final Set<Address> skipDelaySlots;
private final Range<Long> lifespan;
@ -61,6 +66,20 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
protected int count = 0;
/**
* Construct an adder
*
* <p>
* This should only be done after the entire instruction set has been checked
*
* @param skipDelaySlots addresses of delay slotted instructions to skip
* @param lifespan the lifespan for each instruction
* @param platform the platform (language, compiler) for the instructions
* @param block the block to add
* @param errorAddress the address of the first error in the block, if any
* @param conflict a description of the error, if any
* @param conflictCodeUnit if a conflict, the code unit that already exists
*/
private InstructionBlockAdder(Set<Address> skipDelaySlots, Range<Long> lifespan,
InternalTracePlatform platform, InstructionBlock block, Address errorAddress,
InstructionError conflict, CodeUnit conflictCodeUnit) {
@ -73,6 +92,14 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
this.conflictCodeUnit = conflictCodeUnit;
}
/**
* Store the given instruction in the database
*
* @param address the address of the instruction
* @param prototype the instruction prototype
* @param protoInstr the parsed (usually pseudo) instruction
* @return the created instruction
*/
protected Instruction doCreateInstruction(Address address,
InstructionPrototype prototype, Instruction protoInstr) {
try {
@ -97,12 +124,14 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
/**
* Adds the instructions and returns the last instruction added
*
* <p>
* If it encounters a delay-slotted instruction, it will recurse on the group, iterating in
* reverse order.
*
* @param instructions
* @param areDelaySlots
* @return
* @param instructions the instructions to add
* @param areDelaySlots true if the instructions are already reversed from being
* delay-slotted
* @return the last instruction added
*/
protected Instruction doAddInstructions(Iterator<Instruction> it, boolean areDelaySlots) {
Instruction lastInstruction = null;
@ -158,13 +187,38 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
}
return lastInstruction;
}
/**
* Add the instructions and return the last one added
*
* @return the last instruction added
*/
protected Instruction doAddInstructions() {
return doAddInstructions(block.iterator(), false);
}
}
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceInstructionsView(DBTraceCodeSpace space) {
super(space, space.instructionMapSpace);
}
protected void doSetContexts(TraceAddressSnapRange tasr, Language language,
/**
* Set the context over the given box
*
* <p>
* If the given context matches the language's default at the mininum address of the box, the
* context is cleared.
*
* @param tasr the box
* @param language the language for the instruction
* @param context the desired context
*/
protected void doSetContext(TraceAddressSnapRange tasr, Language language,
ProcessorContextView context) {
Register contextReg = language.getContextBaseRegister();
if (contextReg == null || contextReg == Register.NO_CONTEXT) {
@ -185,6 +239,19 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
ctxSpace.setValue(language, newValue, tasr.getLifespan(), tasr.getRange());
}
/**
* Create an instruction
*
* @param lifespan the lifespan of the instruction
* @param address the minimum address of the instruction
* @param platform the platform (language, compiler) for the instruction
* @param prototype the instruction's prototype
* @param context the initial context for parsing the instruction
* @return the new instructions
* @throws CodeUnitInsertionException if the instruction cannot be created due to an existing
* unit
* @throws AddressOverflowException if the instruction would fall off the address space
*/
protected DBTraceInstruction doCreate(Range<Long> lifespan, Address address,
InternalTracePlatform platform, InstructionPrototype prototype,
ProcessorContextView context)
@ -221,7 +288,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
throw new CodeUnitInsertionException("Code units cannot overlap");
}
doSetContexts(tasr, prototype.getLanguage(), context);
doSetContext(tasr, prototype.getLanguage(), context);
DBTraceInstruction created = space.instructionMapSpace.put(tasr, null);
created.set(platform, prototype, context);
@ -253,6 +320,13 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
}
}
/**
* Prepare to check a block for conflicts
*
* @param startSnap the minimum snap for each instruction
* @param block the block of instructions
* @return an iterator for overlapping object pairs
*/
protected OverlappingObjectIterator<Instruction, CodeUnit> startCheckingBlock(long startSnap,
InstructionBlock block) {
Address startAddress = block.getStartAddress();
@ -267,6 +341,19 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
OverlappingObjectIterator.CODE_UNIT, existing, OverlappingObjectIterator.CODE_UNIT);
}
/**
* Start adding the given block to the database
*
* <p>
* If this returns non-null, it should be immediately followed by
* {@link InstructionBlockAdder#doAddInstructions()}.
*
* @param lifespan the lifespan of each instruction
* @param skipDelaySlots the addresses of delay-slotted instructions to skip
* @param platform the instructions' platform (language, compiler)
* @param block the block of instructions to add
* @return the adder, or null
*/
protected InstructionBlockAdder startAddingBlock(Range<Long> lifespan,
Set<Address> skipDelaySlots, InternalTracePlatform platform, InstructionBlock block) {
InstructionError conflict = block.getInstructionConflict();
@ -292,6 +379,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
/**
* Checks the intended locations for conflicts with existing units.
*
* <p>
* This also clears locations where delay slots will be replacing non-delay slots.
* {@code skipDelaySlots} will be populated with any existing delay slot locations which should
* not be overwritten
@ -400,7 +488,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
if (adder == null) {
continue;
}
Instruction lastInstruction = adder.doAddInstructions(block.iterator(), false);
Instruction lastInstruction = adder.doAddInstructions();
block.setInstructionsAddedCount(adder.count);
if (lastInstruction != null) {
Address maxAddress = DBTraceCodeManager.instructionMax(lastInstruction, true);

View File

@ -15,11 +15,21 @@
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceUndefinedDataView;
/**
* The implementation of {@link TraceCodeManager#undefinedData()}
*/
public class DBTraceUndefinedDataMemoryView extends
AbstractWithUndefinedDBTraceCodeUnitsMemoryView<UndefinedDBTraceData, DBTraceUndefinedDataView>
implements TraceUndefinedDataView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceUndefinedDataMemoryView(DBTraceCodeManager manager) {
super(manager);
}

View File

@ -1,31 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceUndefinedDataRegisterView;
import ghidra.trace.model.thread.TraceThread;
public class DBTraceUndefinedDataRegisterView extends DBTraceUndefinedDataView
implements TraceUndefinedDataRegisterView {
public DBTraceUndefinedDataRegisterView(DBTraceCodeSpace space) {
super(space);
}
@Override
public TraceThread getThread() {
return space.getThread();
}
}

View File

@ -26,9 +26,13 @@ import com.google.common.collect.Range;
import ghidra.program.model.address.*;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceUndefinedDataView;
import ghidra.util.*;
/**
* The implementation of {@link TraceCodeSpace#undefinedData()}
*/
public class DBTraceUndefinedDataView extends
AbstractSingleDBTraceCodeUnitsView<UndefinedDBTraceData> implements TraceUndefinedDataView {
@ -42,6 +46,11 @@ public class DBTraceUndefinedDataView extends
.build()
.asMap();
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceUndefinedDataView(DBTraceCodeSpace space) {
super(space);
this.manager = space.manager;
@ -51,6 +60,13 @@ public class DBTraceUndefinedDataView extends
// Nothing
}
/**
* Generate an undefined data unit at the given point
*
* @param snap the snap of the unit
* @param address the address of the unit
* @return the unit
*/
protected UndefinedDBTraceData doCreateUnit(long snap, Address address) {
space.assertInSpace(address);
return manager.doCreateUndefinedUnit(snap, address, space.getThread(),
@ -62,6 +78,16 @@ public class DBTraceUndefinedDataView extends
return 0;
}
/**
* Get an address set view for optimizing various queries
*
* <p>
* As its code may suggest, this creates the lazy address set view {@code all - definedUnits},
* and wraps it in a cached address set view.
*
* @param snap the snapshot key for the address set
* @return the address set
*/
protected AddressSetView doGetAddressSetView(long snap) {
return cache.computeIfAbsent(snap,
t -> new CachedAddressSetView(new DifferenceAddressSetView(new AddressSet(space.all),
@ -142,6 +168,9 @@ public class DBTraceUndefinedDataView extends
doGetAddressSetView(snap));
}
/**
* Invalidate the cache of generated undefined units
*/
public void invalidateCache() {
cache.clear();
}

View File

@ -38,6 +38,13 @@ import ghidra.trace.model.listing.TraceData;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
/**
* The implementation for an undefined {@link TraceData} for {@link DBTrace}
*
* <p>
* These are not backed by a table. They are generated ephemerally. Each is exactly one unit in size
* in both time and space.
*/
public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey {
protected final DBTrace trace;
protected final long snap;
@ -46,6 +53,15 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey
protected final TraceThread thread;
protected final int frameLevel;
/**
* Construct an undefined unit
*
* @param trace the trace
* @param snap the snap
* @param address the address
* @param thread the thread, if in a per-thread space
* @param frameLevel the frame, if in a per-frame space
*/
public UndefinedDBTraceData(DBTrace trace, long snap, Address address, TraceThread thread,
int frameLevel) {
this.trace = trace;

View File

@ -126,14 +126,14 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTracePropertyMapSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, dataType, dataFactory);
lock, space, null, 0, dataType, dataFactory);
}
@Override
protected DBTracePropertyMapRegisterSpace createRegisterSpace(
protected DBTracePropertyMapSpace createRegisterSpace(
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTracePropertyMapRegisterSpace(
return new DBTracePropertyMapSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
}
@ -145,9 +145,9 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
}
@Override
public TracePropertyMapRegisterSpace<T> getPropertyMapRegisterSpace(TraceThread thread,
public TracePropertyMapSpace<T> getPropertyMapRegisterSpace(TraceThread thread,
int frameLevel, boolean createIfAbsent) {
return (DBTracePropertyMapRegisterSpace) getForRegisterSpace(thread, frameLevel,
return (DBTracePropertyMapSpace) getForRegisterSpace(thread, frameLevel,
createIfAbsent);
}
@ -161,96 +161,11 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
implements TracePropertyMapSpace<T> {
public DBTracePropertyMapSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
ReadWriteLock lock, AddressSpace space, Class<DR> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
throws VersionException, IOException {
super(tableName, storeFactory, lock, space, dataType, dataFactory);
}
@Override
public Trace getTrace() {
return trace;
}
@Override
public Class<T> getValueClass() {
return AbstractDBTracePropertyMap.this.getValueClass();
}
@SuppressWarnings("unchecked")
protected void makeWay(Entry<TraceAddressSnapRange, T> entry, Range<Long> span) {
// TODO: Would rather not rely on implementation knowledge here
// The shape is the database record in AbstractDBTraceAddressSnapRangePropertyMapData
makeWay((DR) entry.getKey(), span);
}
protected void makeWay(DR data, Range<Long> span) {
DBTraceUtils.makeWay(data, span, (d, s) -> d.doSetLifespan(s), d -> deleteData(d));
// TODO: Any events?
}
@Override
public void set(Range<Long> lifespan, Address address, T value) {
put(address, lifespan, value);
}
@Override
public void set(Range<Long> lifespan, AddressRange range, T value) {
put(range, lifespan, value);
}
@Override
public T get(long snap, Address address) {
return reduce(TraceAddressSnapRangeQuery.at(address, snap)).firstValue();
}
@Override
public Entry<TraceAddressSnapRange, T> getEntry(long snap, Address address) {
return reduce(TraceAddressSnapRangeQuery.at(address, snap)).firstEntry();
}
@Override
public Collection<Entry<TraceAddressSnapRange, T>> getEntries(Range<Long> lifespan,
AddressRange range) {
return reduce(TraceAddressSnapRangeQuery.intersecting(range, lifespan)).entries();
}
@Override
public boolean clear(Range<Long> span, AddressRange range) {
try (LockHold hold = LockHold.lock(lock.writeLock())) {
boolean result = false;
for (Entry<TraceAddressSnapRange, T> entry : reduce(
TraceAddressSnapRangeQuery.intersecting(range, span)).entries()) {
makeWay(entry, span);
result = true;
}
return result;
}
}
@Override
public T put(TraceAddressSnapRange shape, T value) {
try (LockHold hold = LockHold.lock(lock.writeLock())) {
for (Entry<TraceAddressSnapRange, T> entry : reduce(
TraceAddressSnapRangeQuery.intersecting(shape)).entries()) {
makeWay(entry, shape.getLifespan());
}
return super.put(shape, value);
}
}
}
public class DBTracePropertyMapRegisterSpace
extends DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR>
implements TracePropertyMapRegisterSpace<T> {
public DBTracePropertyMapRegisterSpace(String tableName,
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
TraceThread thread, int frameLevel, Class<DR> dataType,
ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
Class<DR> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
throws VersionException, IOException {
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
// TODO Auto-generated constructor stub
}
@Override

View File

@ -48,8 +48,7 @@ import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAddressSnapRangePropertyMapData<T>>
extends
AbstractDBTraceSpaceBasedManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>, DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR>>
extends AbstractDBTraceSpaceBasedManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>>
implements TraceAddressSnapRangePropertyMap<T>,
DBTraceDelegatingManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>> {
@ -83,26 +82,26 @@ public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAdd
DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceAddressSnapRangePropertyMapSpace<>(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, dataType, dataFactory);
lock, space, null, ent.getFrameLevel(), dataType, dataFactory);
}
@Override
protected DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> createRegisterSpace(
protected DBTraceAddressSnapRangePropertyMapSpace<T, DR> createRegisterSpace(
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceAddressSnapRangePropertyMapRegisterSpace<>(
return new DBTraceAddressSnapRangePropertyMapSpace<>(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
}
@Override
public DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> getRegisterSpace(
public DBTraceAddressSnapRangePropertyMapSpace<T, DR> getRegisterSpace(
TraceThread thread, boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}
@Override
public DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> getRegisterSpace(
public DBTraceAddressSnapRangePropertyMapSpace<T, DR> getRegisterSpace(
TraceStackFrame frame, boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent);
}

View File

@ -1,54 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.map;
import java.io.IOException;
import java.util.concurrent.locks.ReadWriteLock;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMap.DBTraceAddressSnapRangePropertyMapDataFactory;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData;
import ghidra.trace.model.map.TraceAddressSnapRangePropertyMapRegisterSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.DBCachedObjectStoreFactory;
import ghidra.util.exception.VersionException;
public class DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR extends AbstractDBTraceAddressSnapRangePropertyMapData<T>>
extends DBTraceAddressSnapRangePropertyMapSpace<T, DR>
implements TraceAddressSnapRangePropertyMapRegisterSpace<T> {
protected final TraceThread thread;
protected final int frameLevel;
public DBTraceAddressSnapRangePropertyMapRegisterSpace(String tableName,
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
TraceThread thread, int frameLevel, Class<DR> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
throws VersionException, IOException {
super(tableName, storeFactory, lock, space, dataType, dataFactory);
this.thread = thread;
this.frameLevel = frameLevel;
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
}

View File

@ -44,6 +44,8 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
TraceAddressSnapRangePropertyMapSpace<T> {
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock;
protected final DBTraceAddressSnapRangePropertyMapTree<T, DR> tree;
protected final AbstractConstraintsTreeSpatialMap<TraceAddressSnapRange, DR, TraceAddressSnapRange, T, TraceAddressSnapRangeQuery> map;
@ -51,9 +53,12 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
public DBTraceAddressSnapRangePropertyMapSpace(String tableName,
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
Class<DR> dataType, DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
TraceThread thread, int frameLevel, Class<DR> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
throws VersionException, IOException {
this.space = space;
this.thread = thread;
this.frameLevel = frameLevel;
this.lock = lock;
this.tree = new DBTraceAddressSnapRangePropertyMapTree<>(storeFactory, tableName, this,
@ -70,12 +75,12 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
@Override
public TraceThread getThread() {
return null;
return thread;
}
@Override
public int getFrameLevel() {
return 0;
return frameLevel;
}
public <K> DBCachedObjectIndex<K, DR> getUserIndex(Class<K> fieldClass, DBObjectColumn column) {

View File

@ -48,8 +48,7 @@ import ghidra.util.database.DBOpenMode;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
public class DBTraceMemoryManager
extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace, DBTraceMemoryRegisterSpace>
public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace>
implements TraceMemoryManager, DBTraceDelegatingManager<DBTraceMemorySpace> {
protected static final String NAME = "Memory";
@ -80,13 +79,13 @@ public class DBTraceMemoryManager
@Override
protected DBTraceMemorySpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceMemorySpace(this, dbh, space, ent);
return new DBTraceMemorySpace(this, dbh, space, ent, null);
}
@Override
protected DBTraceMemoryRegisterSpace createRegisterSpace(AddressSpace space,
protected DBTraceMemorySpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceMemoryRegisterSpace(this, dbh, space, ent, thread);
return new DBTraceMemorySpace(this, dbh, space, ent, thread);
}
@Override
@ -110,19 +109,19 @@ public class DBTraceMemoryManager
}
@Override
public DBTraceMemoryRegisterSpace getMemoryRegisterSpace(TraceThread thread,
public DBTraceMemorySpace getMemoryRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}
@Override
public TraceMemoryRegisterSpace getMemoryRegisterSpace(TraceThread thread, int frame,
public DBTraceMemorySpace getMemoryRegisterSpace(TraceThread thread, int frame,
boolean createIfAbsent) {
return getForRegisterSpace(thread, frame, createIfAbsent);
}
@Override
public DBTraceMemoryRegisterSpace getMemoryRegisterSpace(TraceStackFrame frame,
public DBTraceMemorySpace getMemoryRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent);
}

View File

@ -1,68 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.memory;
import java.io.IOException;
import javax.help.UnsupportedOperationException;
import com.google.common.collect.Range;
import db.DBHandle;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
import ghidra.trace.model.memory.*;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.VersionException;
public class DBTraceMemoryRegisterSpace extends DBTraceMemorySpace
implements TraceMemoryRegisterSpace {
protected final TraceThread thread;
private final int frameLevel;
public DBTraceMemoryRegisterSpace(DBTraceMemoryManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
throws IOException, VersionException {
super(manager, dbh, space, ent);
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
@Override
public DBTraceCodeRegisterSpace getCodeSpace(boolean createIfAbsent) {
return trace.getCodeManager().getCodeRegisterSpace(thread, frameLevel, createIfAbsent);
}
@Override
public DBTraceMemoryRegion addRegion(String name, Range<Long> lifespan, AddressRange range,
TraceMemoryFlag... flags)
throws TraceOverlappedRegionException, DuplicateNameException {
throw new UnsupportedOperationException();
}
}

View File

@ -68,6 +68,8 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
protected final DBTraceMemoryManager manager;
protected final DBHandle dbh;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock;
protected final DBTrace trace;
@ -96,10 +98,12 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
protected final DefaultTraceTimeViewport viewport;
public DBTraceMemorySpace(DBTraceMemoryManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws IOException, VersionException {
DBTraceSpaceEntry ent, TraceThread thread) throws IOException, VersionException {
this.manager = manager;
this.dbh = dbh;
this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock();
this.trace = manager.getTrace();
@ -108,15 +112,16 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
long threadKey = ent.getThreadKey();
int frameLevel = ent.getFrameLevel();
this.regionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space,
DBTraceMemoryRegion.class, (t, s, r) -> new DBTraceMemoryRegion(this, t, s, r));
DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space, thread,
frameLevel, DBTraceMemoryRegion.class,
(t, s, r) -> new DBTraceMemoryRegion(this, t, s, r));
this.regionView = Collections.unmodifiableCollection(regionMapSpace.values());
this.regionsByPath =
regionMapSpace.getUserIndex(String.class, DBTraceMemoryRegion.PATH_COLUMN);
this.stateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceMemoryStateEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new);
thread, frameLevel, DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new);
this.bufferStore = factory.getOrCreateCachedStore(
DBTraceMemoryBufferEntry.tableName(space, threadKey, frameLevel),
@ -257,6 +262,9 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
@Override
public DBTraceCodeSpace getCodeSpace(boolean createIfAbsent) {
if (space.isRegisterSpace()) {
return trace.getCodeManager().getCodeRegisterSpace(thread, frameLevel, createIfAbsent);
}
return trace.getCodeManager().getCodeSpace(space, createIfAbsent);
}
@ -405,7 +413,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
@Override
public Entry<TraceAddressSnapRange, TraceMemoryState> getViewMostRecentStateEntry(long snap,
Address address) {
for (Range<Long> span: viewport.getOrderedSpans(snap)) {
for (Range<Long> span : viewport.getOrderedSpans(snap)) {
Entry<TraceAddressSnapRange, TraceMemoryState> entry =
stateMapSpace.reduce(TraceAddressSnapRangeQuery.mostRecent(address, span))
.firstEntry();

View File

@ -41,8 +41,7 @@ import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceModuleManager
extends AbstractDBTraceSpaceBasedManager<DBTraceModuleSpace, DBTraceModuleSpace>
public class DBTraceModuleManager extends AbstractDBTraceSpaceBasedManager<DBTraceModuleSpace>
implements TraceModuleManager, DBTraceDelegatingManager<DBTraceModuleSpace> {
public static final String NAME = "Module";

View File

@ -58,13 +58,13 @@ public class DBTraceModuleSpace implements TraceModuleSpace, DBTraceSpaceBased {
this.trace = manager.getTrace();
this.moduleMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceModule.tableName(space), trace.getStoreFactory(), lock, space,
DBTraceModule.tableName(space), trace.getStoreFactory(), lock, space, null, 0,
DBTraceModule.class, (t, s, r) -> new DBTraceModule(this, t, s, r));
this.modulesByPath = moduleMapSpace.getUserIndex(String.class, DBTraceModule.PATH_COLUMN);
this.moduleView = Collections.unmodifiableCollection(moduleMapSpace.values());
this.sectionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceSection.tableName(space), trace.getStoreFactory(), lock, space,
DBTraceSection.tableName(space), trace.getStoreFactory(), lock, space, null, 0,
DBTraceSection.class, (t, s, r) -> new DBTraceSection(this, t, s, r));
this.sectionsByModuleKey =
sectionMapSpace.getUserIndex(long.class, DBTraceSection.MODULE_COLUMN);

View File

@ -45,8 +45,8 @@ import ghidra.program.model.util.PropertyMapManager;
import ghidra.program.util.ChangeManager;
import ghidra.program.util.ProgramChangeRecord;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.listing.*;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.database.listing.DBTraceDefinedUnitsView;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.database.symbol.DBTraceFunctionSymbolView;
import ghidra.trace.model.Trace.*;
@ -990,12 +990,12 @@ public class DBTraceProgramView implements TraceProgramView {
return regView;
}
assert trace.getThreadManager().getAllThreads().contains(thread);
DBTraceCodeRegisterSpace codeSpace =
DBTraceCodeSpace codeSpace =
trace.getCodeManager().getCodeRegisterSpace(thread, createIfAbsent);
if (codeSpace == null) {
return null;
}
DBTraceMemoryRegisterSpace memorySpace =
DBTraceMemorySpace memorySpace =
trace.getMemoryManager().getMemoryRegisterSpace(thread, createIfAbsent);
if (memorySpace == null) {
return null;

View File

@ -18,7 +18,7 @@ package ghidra.trace.database.program;
import com.google.common.collect.Range;
import ghidra.program.model.address.*;
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.database.listing.UndefinedDBTraceData;
import ghidra.trace.model.program.TraceProgramViewRegisterListing;
import ghidra.trace.model.thread.TraceThread;
@ -32,7 +32,7 @@ public class DBTraceProgramViewRegisterListing extends AbstractDBTraceProgramVie
private Address maxAddr;
public DBTraceProgramViewRegisterListing(DBTraceProgramView program,
DBTraceCodeRegisterSpace regSpace) {
DBTraceCodeSpace regSpace) {
super(program, regSpace);
this.thread = regSpace.getThread();

View File

@ -17,14 +17,14 @@ package ghidra.trace.database.program;
import ghidra.program.model.address.*;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.database.memory.DBTraceMemorySpace;
public class DBTraceProgramViewRegisterMemory extends AbstractDBTraceProgramViewMemory {
protected final DBTraceMemoryRegisterSpace space;
protected final DBTraceMemorySpace space;
protected final DBTraceProgramViewRegisterMemoryBlock block;
public DBTraceProgramViewRegisterMemory(DBTraceProgramView program,
DBTraceMemoryRegisterSpace space) {
DBTraceMemorySpace space) {
super(program);
this.space = space;
this.block = new DBTraceProgramViewRegisterMemoryBlock(program, space);

View File

@ -27,7 +27,7 @@ import ghidra.program.database.mem.ByteMappingScheme;
import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*;
import ghidra.program.model.mem.*;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.model.memory.TraceMemorySpaceInputStream;
public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
@ -96,14 +96,14 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
}
private final DBTraceProgramView program;
private final DBTraceMemoryRegisterSpace space;
private final DBTraceMemorySpace space;
private final AddressRange range;
private final List<MemoryBlockSourceInfo> info =
Collections.singletonList(new DBTraceProgramViewRegisterMemoryBlockSourceInfo());
public DBTraceProgramViewRegisterMemoryBlock(DBTraceProgramView program,
DBTraceMemoryRegisterSpace space) {
DBTraceMemorySpace space) {
this.program = program;
this.space = space;
this.range = new AddressRangeImpl(space.getAddressSpace().getMinAddress(),

View File

@ -34,8 +34,8 @@ import ghidra.program.model.reloc.RelocationTable;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.AddressSetPropertyMap;
import ghidra.program.model.util.PropertyMapManager;
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.model.Trace;
import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.program.TraceProgramView;
@ -56,8 +56,8 @@ public class DBTraceProgramViewRegisters implements TraceProgramView {
private final DBTraceProgramViewRegisterMemory memory;
private final DBTraceProgramViewRegistersReferenceManager referenceManager;
public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeRegisterSpace codeSpace,
DBTraceMemoryRegisterSpace memorySpace) {
public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeSpace codeSpace,
DBTraceMemorySpace memorySpace) {
this.view = view;
this.thread = codeSpace.getThread(); // TODO: Bleh, should be parameter

View File

@ -39,7 +39,7 @@ import ghidra.util.database.annot.*;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBased, R extends M>
public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBased>
implements DBTraceManager {
protected static final AddressSpace NO_ADDRESS_SPACE = Address.NO_ADDRESS.getAddressSpace();
@ -96,10 +96,10 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
// Note: use tree map so traversal is ordered by address space
protected final Map<AddressSpace, M> memSpaces = new TreeMap<>();
// Note: can use hash map here. I see no need to order these spaces
protected final Map<Pair<TraceThread, Integer>, R> regSpaces = new HashMap<>();
protected final Map<Pair<TraceThread, Integer>, M> regSpaces = new HashMap<>();
protected final Collection<M> memSpacesView =
Collections.unmodifiableCollection(memSpaces.values());
protected final Collection<R> regSpacesView =
protected final Collection<M> regSpacesView =
Collections.unmodifiableCollection(regSpaces.values());
protected final Collection<M> allSpacesView =
new CatenatedCollection<>(memSpacesView, regSpacesView);
@ -145,12 +145,12 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
continue;
}
TraceThread thread = threadManager.getThread(ent.threadKey);
R regSpace;
M regSpace;
if (ent.space == null) {
regSpace = createRegisterSpace(space, thread, ent);
}
else {
regSpace = (R) ent.space;
regSpace = (M) ent.space;
}
regSpaces.put(ImmutablePair.of(thread, ent.getFrameLevel()), regSpace);
}
@ -199,7 +199,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
}
}
protected R getForRegisterSpace(TraceThread thread, int frameLevel, boolean createIfAbsent) {
protected M getForRegisterSpace(TraceThread thread, int frameLevel, boolean createIfAbsent) {
trace.getThreadManager().assertIsMine(thread);
// TODO: What if registers are memory mapped?
Pair<TraceThread, Integer> frame = ImmutablePair.of(thread, frameLevel);
@ -227,7 +227,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
}
}
protected R getForRegisterSpace(TraceStackFrame frame, boolean createIfAbsent) {
protected M getForRegisterSpace(TraceStackFrame frame, boolean createIfAbsent) {
return getForRegisterSpace(frame.getStack().getThread(), frame.getLevel(), createIfAbsent);
}
@ -259,14 +259,14 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
return memSpacesView;
}
public Collection<R> getActiveRegisterSpaces() {
public Collection<M> getActiveRegisterSpaces() {
return regSpacesView;
}
protected abstract M createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException;
protected abstract R createRegisterSpace(AddressSpace space, TraceThread thread,
protected abstract M createRegisterSpace(AddressSpace space, TraceThread thread,
DBTraceSpaceEntry ent) throws VersionException, IOException;
@Override
@ -286,7 +286,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
for (M m : memSpaces.values()) {
m.invalidateCache();
}
for (R r : regSpaces.values()) {
for (M r : regSpaces.values()) {
r.invalidateCache();
}
}

View File

@ -40,8 +40,7 @@ import ghidra.util.database.*;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
public class DBTraceEquateManager
extends AbstractDBTraceSpaceBasedManager<DBTraceEquateSpace, DBTraceEquateRegisterSpace>
public class DBTraceEquateManager extends AbstractDBTraceSpaceBasedManager<DBTraceEquateSpace>
implements TraceEquateManager, DBTraceDelegatingManager<DBTraceEquateSpace> {
public static final String NAME = "Equate";
@ -96,13 +95,13 @@ public class DBTraceEquateManager
}
@Override
public DBTraceEquateRegisterSpace getEquateRegisterSpace(TraceThread thread,
public DBTraceEquateSpace getEquateRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}
@Override
public DBTraceEquateRegisterSpace getEquateRegisterSpace(TraceStackFrame frame,
public DBTraceEquateSpace getEquateRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent);
}
@ -110,13 +109,13 @@ public class DBTraceEquateManager
@Override
protected DBTraceEquateSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceEquateSpace(this, dbh, space, ent);
return new DBTraceEquateSpace(this, dbh, space, ent, null);
}
@Override
protected DBTraceEquateRegisterSpace createRegisterSpace(AddressSpace space,
protected DBTraceEquateSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceEquateRegisterSpace(this, dbh, space, ent, thread);
return new DBTraceEquateSpace(this, dbh, space, ent, thread);
}
@Override

View File

@ -1,50 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.symbol;
import java.io.IOException;
import db.DBHandle;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
import ghidra.trace.model.symbol.TraceEquateRegisterSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.exception.VersionException;
public class DBTraceEquateRegisterSpace extends DBTraceEquateSpace
implements TraceEquateRegisterSpace {
protected final TraceThread thread;
private final int frameLevel;
public DBTraceEquateRegisterSpace(DBTraceEquateManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
throws VersionException, IOException {
super(manager, dbh, space, ent);
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
}

View File

@ -101,6 +101,8 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
protected final DBTraceEquateManager manager;
protected final DBHandle dbh;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock;
protected final Language baseLanguage;
protected final DBTrace trace;
@ -110,10 +112,12 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceEquateReference, DBTraceEquateReference> equateMapSpace;
public DBTraceEquateSpace(DBTraceEquateManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws VersionException, IOException {
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
this.manager = manager;
this.dbh = dbh;
this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace();
@ -126,7 +130,8 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
int frameLevel = ent.getFrameLevel();
this.equateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceEquateReference.tableName(space, threadKey, frameLevel), factory, lock, space,
DBTraceEquateReference.class, (t, s, r) -> new DBTraceEquateReference(this, t, s, r));
thread, ent.getFrameLevel(), DBTraceEquateReference.class,
(t, s, r) -> new DBTraceEquateReference(this, t, s, r));
}
@Override
@ -136,12 +141,12 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
@Override
public TraceThread getThread() {
return null;
return thread;
}
@Override
public int getFrameLevel() {
return 0;
return frameLevel;
}
@Override

View File

@ -44,8 +44,7 @@ import ghidra.util.database.DBOpenMode;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
public class DBTraceReferenceManager extends
AbstractDBTraceSpaceBasedManager<DBTraceReferenceSpace, DBTraceReferenceRegisterSpace>
public class DBTraceReferenceManager extends AbstractDBTraceSpaceBasedManager<DBTraceReferenceSpace>
implements TraceReferenceManager, DBTraceDelegatingManager<DBTraceReferenceSpace> {
public static final String NAME = "Reference";
@ -64,13 +63,13 @@ public class DBTraceReferenceManager extends
@Override
protected DBTraceReferenceSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException {
return new DBTraceReferenceSpace(this, dbh, space, ent);
return new DBTraceReferenceSpace(this, dbh, space, ent, null);
}
@Override
protected DBTraceReferenceRegisterSpace createRegisterSpace(AddressSpace space,
protected DBTraceReferenceSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceReferenceRegisterSpace(this, dbh, space, ent, thread);
return new DBTraceReferenceSpace(this, dbh, space, ent, thread);
}
/**
@ -147,13 +146,13 @@ public class DBTraceReferenceManager extends
}
@Override
public DBTraceReferenceRegisterSpace getReferenceRegisterSpace(TraceThread thread,
public DBTraceReferenceSpace getReferenceRegisterSpace(TraceThread thread,
boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent);
}
@Override
public DBTraceReferenceRegisterSpace getReferenceRegisterSpace(TraceStackFrame frame,
public DBTraceReferenceSpace getReferenceRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent);
}

View File

@ -1,49 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.symbol;
import java.io.IOException;
import db.DBHandle;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
import ghidra.trace.model.symbol.TraceReferenceRegisterSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.exception.VersionException;
public class DBTraceReferenceRegisterSpace extends DBTraceReferenceSpace
implements TraceReferenceRegisterSpace {
protected final TraceThread thread;
private final int frameLevel;
public DBTraceReferenceRegisterSpace(DBTraceReferenceManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
throws VersionException, IOException {
super(manager, dbh, space, ent);
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
}
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
}

View File

@ -334,6 +334,8 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
protected final DBTraceReferenceManager manager;
protected final DBHandle dbh;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock;
protected final Language baseLanguage;
protected final DBTrace trace;
@ -347,10 +349,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
protected final DBCachedObjectIndex<Long, DBTraceXRefEntry> xrefsByRefKey;
public DBTraceReferenceSpace(DBTraceReferenceManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws VersionException, IOException {
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
this.manager = manager;
this.dbh = dbh;
this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace();
@ -363,13 +367,14 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
int frameLevel = ent.getFrameLevel();
this.referenceMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceReferenceEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
DBTraceReferenceEntry.class, (t, s, r) -> new DBTraceReferenceEntry(this, t, s, r));
thread, frameLevel, DBTraceReferenceEntry.class,
(t, s, r) -> new DBTraceReferenceEntry(this, t, s, r));
this.refsBySymbolId =
referenceMapSpace.getUserIndex(long.class, DBTraceReferenceEntry.SYMBOL_ID_COLUMN);
this.xrefMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r));
DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space, thread,
frameLevel, DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r));
this.xrefsByRefKey = xrefMapSpace.getUserIndex(long.class, DBTraceXRefEntry.REF_KEY_COLUMN);
}
@ -409,12 +414,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
@Override
public TraceThread getThread() {
return null;
return thread;
}
@Override
public int getFrameLevel() {
return 0;
return frameLevel;
}
@Override

View File

@ -27,9 +27,9 @@ import ghidra.trace.model.thread.TraceThread;
public interface TraceBookmarkManager extends TraceBookmarkOperations {
TraceBookmarkSpace getBookmarkSpace(AddressSpace space, boolean createIfAbsent);
TraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceThread thread, boolean createIfAbsent);
TraceBookmarkSpace getBookmarkRegisterSpace(TraceThread thread, boolean createIfAbsent);
TraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceStackFrame frame,
TraceBookmarkSpace getBookmarkRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent);
/**

View File

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.model.bookmark;
import com.google.common.collect.Range;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceRegisterUtils;
public interface TraceBookmarkRegisterSpace extends TraceBookmarkSpace {
@Override
TraceThread getThread();
default TraceBookmark addBookmark(Range<Long> lifespan, Register register,
TraceBookmarkType type, String category, String comment) {
return addBookmark(lifespan, register.getAddress(), type, category, comment);
}
default Iterable<? extends TraceBookmark> getBookmarksEnclosed(Range<Long> lifespan,
Register register) {
return getBookmarksEnclosed(lifespan, TraceRegisterUtils.rangeForRegister(register));
}
default Iterable<? extends TraceBookmark> getBookmarksIntersecting(Range<Long> lifespan,
Register register) {
return getBookmarksIntersecting(lifespan, TraceRegisterUtils.rangeForRegister(register));
}
}

View File

@ -15,11 +15,30 @@
*/
package ghidra.trace.model.bookmark;
import com.google.common.collect.Range;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceRegisterUtils;
public interface TraceBookmarkSpace extends TraceBookmarkOperations {
AddressSpace getAddressSpace();
TraceThread getThread();
default TraceBookmark addBookmark(Range<Long> lifespan, Register register,
TraceBookmarkType type, String category, String comment) {
return addBookmark(lifespan, register.getAddress(), type, category, comment);
}
default Iterable<? extends TraceBookmark> getBookmarksEnclosed(Range<Long> lifespan,
Register register) {
return getBookmarksEnclosed(lifespan, TraceRegisterUtils.rangeForRegister(register));
}
default Iterable<? extends TraceBookmark> getBookmarksIntersecting(Range<Long> lifespan,
Register register) {
return getBookmarksIntersecting(lifespan, TraceRegisterUtils.rangeForRegister(register));
}
}

View File

@ -1,22 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.model.context;
import ghidra.trace.model.thread.TraceThread;
public interface TraceRegisterContextRegisterSpace extends TraceRegisterContextSpace {
TraceThread getThread();
}

View File

@ -1,113 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.model.listing;
import java.util.HashSet;
import java.util.Set;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceRegisterUtils;
/**
* A {@link TraceBaseCodeUnitsView} associated with a thread, restricted to register space, and
* possibly restricted to a particular subset by type.
*
* @param <T> the type of units in the view
*/
public interface TraceBaseCodeUnitsRegisterView<T extends TraceCodeUnit>
extends TraceBaseCodeUnitsView<T> {
/**
* Get the associated thread
*
* @return the thread
*/
TraceThread getThread();
/**
* Get the set of registers for the trace's base language
*
* @return the register set
*/
default Set<Register> getRegisters() {
return new HashSet<>(getThread().getTrace().getBaseLanguage().getRegisters());
}
/**
* Get the unit (or component of a structure) which spans exactly the addresses of the given
* register
*
* @param register the register
* @return the unit or {@code null}
*/
@SuppressWarnings("unchecked")
default T getForRegister(long snap, Register register) {
// Find a code unit which contains the register completely
T candidate = getContaining(snap, register.getAddress());
if (candidate == null) {
return null;
}
AddressRange range = TraceRegisterUtils.rangeForRegister(register);
int cmpMax = range.getMaxAddress().compareTo(candidate.getMaxAddress());
if (cmpMax > 0) {
return null;
}
if (cmpMax == 0 && candidate.getMinAddress().equals(register.getAddress())) {
return candidate;
}
if (!(candidate instanceof TraceData)) {
return null;
}
TraceData data = (TraceData) candidate;
// Cast because if candidate is TraceData, T is, too
// NOTE: It may not be a primitive
return (T) TraceRegisterUtils.seekComponent(data, range);
}
/**
* Get the unit which completely contains the given register
*
* This does not descend into structures.
*
* @param register the register
* @return the unit or {@code unit}
*/
default T getContaining(long snap, Register register) {
T candidate = getContaining(snap, register.getAddress());
if (candidate == null) {
return null;
}
AddressRange range = TraceRegisterUtils.rangeForRegister(register);
int cmpMax = range.getMaxAddress().compareTo(candidate.getMaxAddress());
if (cmpMax > 0) {
return null;
}
return candidate;
}
/**
* Get the live units whose start addresses are within the given register
*
* @param register the register
* @param forward true to order the units by increasing address, false for descending
* @return the iterable of units
*/
default Iterable<? extends T> get(long snap, Register register, boolean forward) {
return get(snap, TraceRegisterUtils.rangeForRegister(register), forward);
}
}

View File

@ -15,17 +15,23 @@
*/
package ghidra.trace.model.listing;
import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.Range;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceRegisterUtils;
import ghidra.util.IntersectionAddressSetView;
import ghidra.util.UnionAddressSetView;
/**
* A view of code units stored in a trace, possibly restricted to a particular subset by type,
* address space, and/or thread.
* address space, or thread and frame.
*
* @param <T> the type of units in the view
*/
@ -38,6 +44,20 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
*/
Trace getTrace();
/**
* Get the associated thread, if applicable
*
* @return the thread, or null
*/
TraceThread getThread();
/**
* Get the associated frame level, if applicable
*
* @return the frame level, or 0
*/
int getFrameLevel();
/**
* Get the total number of <em>defined</em> units in this view
*
@ -162,6 +182,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
/**
* Get all addresses contained by live units at the given snap
*
* <p>
* Note that the ranges in this set may not be coalesced. If a coalesced set is required, wrap
* it with {@link UnionAddressSetView}.
*
@ -173,10 +194,11 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
/**
* Get all addresses contained by live units at the given snap, within a restricted range
*
* <p>
* Note that the ranges in this set may not be coalesced. If a coalesced set is required, wrap
* it with {@link UnionAddressSetView}. The returned ranges are not necessarily enclosed by
* -within-, but they will intersect it. If strict enclosure is required, wrap the set with
* {@link IntersectionAddressSetView}.
* {@code within}, but they will intersect it. If strict enclosure is required, wrap the set
* with {@link IntersectionAddressSetView}.
*
* @param snap the snap during which the units must be alive
* @param within the range to restrict the view
@ -196,6 +218,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
/**
* Check if the given span of snaps and range of addresses is covered by the units
*
* <p>
* This checks if every (snap, address) point within the given box is contained within some code
* unit in this view.
*
@ -208,6 +231,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
/**
* Check if the given address-snap range is covered by the units
*
* <p>
* This checks if every (snap, address) point within the given box is contained within some code
* unit in this view.
*
@ -219,6 +243,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
/**
* Check if the given span of snaps and range of addresses intersects any unit
*
* <p>
* This checks if any (snap, address) point within the given box is contained within some code
* unit in this view.
*
@ -231,6 +256,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
/**
* Check if the given span of snaps and range of addresses intersects any unit
*
* <p>
* This checks if any (snap, address) point within the given box is contained within some code
* unit in this view.
*
@ -239,4 +265,77 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
* @return true if intersecting, false otherwise
*/
boolean intersectsRange(TraceAddressSnapRange range);
/**
* Get the set of registers for the trace's base language
*
* @return the register set
*/
default Set<Register> getRegisters() {
return new HashSet<>(getTrace().getBaseLanguage().getRegisters());
}
/**
* Get the unit (or component of a structure) which spans exactly the addresses of the given
* register
*
* @param register the register
* @return the unit or {@code null}
*/
@SuppressWarnings("unchecked")
default T getForRegister(long snap, Register register) {
// Find a code unit which contains the register completely
T candidate = getContaining(snap, register.getAddress());
if (candidate == null) {
return null;
}
AddressRange range = TraceRegisterUtils.rangeForRegister(register);
int cmpMax = range.getMaxAddress().compareTo(candidate.getMaxAddress());
if (cmpMax > 0) {
return null;
}
if (cmpMax == 0 && candidate.getMinAddress().equals(register.getAddress())) {
return candidate;
}
if (!(candidate instanceof TraceData)) {
return null;
}
TraceData data = (TraceData) candidate;
// Cast because if candidate is TraceData, T is, too
// NOTE: It may not be a primitive
return (T) TraceRegisterUtils.seekComponent(data, range);
}
/**
* Get the unit which completely contains the given register
*
* <p>
* This does not descend into structures.
*
* @param register the register
* @return the unit or {@code unit}
*/
default T getContaining(long snap, Register register) {
T candidate = getContaining(snap, register.getAddress());
if (candidate == null) {
return null;
}
AddressRange range = TraceRegisterUtils.rangeForRegister(register);
int cmpMax = range.getMaxAddress().compareTo(candidate.getMaxAddress());
if (cmpMax > 0) {
return null;
}
return candidate;
}
/**
* Get the live units whose start addresses are within the given register
*
* @param register the register
* @param forward true to order the units by increasing address, false for descending
* @return the iterable of units
*/
default Iterable<? extends T> get(long snap, Register register, boolean forward) {
return get(snap, TraceRegisterUtils.rangeForRegister(register), forward);
}
}

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