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

View file

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

View file

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

View file

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

View file

@ -24,7 +24,7 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.AddressSetView; import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.trace.model.Trace; 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.memory.TraceMemoryState;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -78,8 +78,7 @@ public class ArmDisassemblyInject implements DisassemblyInject {
return; return;
} }
TraceMemoryRegisterSpace regs = TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
/** /**
* Some variants (particularly Cortex-M) are missing cpsr. This seems to indicate it only * 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 * 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, public static void initializeRegisters(Trace trace, long snap, TraceThread thread,
Program program, Address tracePc, Address programPc, TraceMemoryRegion stack) { Program program, Address tracePc, Address programPc, TraceMemoryRegion stack) {
TraceMemoryRegisterSpace space = TraceMemorySpace space =
trace.getMemoryManager().getMemoryRegisterSpace(thread, true); trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
if (program != null) { if (program != null) {
ProgramContext ctx = program.getProgramContext(); ProgramContext ctx = program.getProgramContext();

View file

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

View file

@ -227,8 +227,7 @@ public class DisassembleAtPcDebuggerBot implements DebuggerBot {
TraceData pcUnit = null; TraceData pcUnit = null;
try (UndoableTransaction tid = try (UndoableTransaction tid =
UndoableTransaction.start(trace, "Disassemble: PC is code pointer")) { UndoableTransaction.start(trace, "Disassemble: PC is code pointer")) {
TraceCodeRegisterSpace regCode = TraceCodeSpace regCode = codeManager.getCodeRegisterSpace(thread, frameLevel, true);
codeManager.getCodeRegisterSpace(thread, frameLevel, true);
try { try {
pcUnit = regCode.definedData() pcUnit = regCode.definedData()
.create(Range.atLeast(pcSnap), pc, PointerDataType.dataType); .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.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.memory.TraceMemoryRegion; 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.TraceModule;
import ghidra.trace.model.modules.TraceSection; import ghidra.trace.model.modules.TraceSection;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
@ -365,7 +365,7 @@ public interface TraceRecorder {
RegisterValue rv = new RegisterValue(register, RegisterValue rv = new RegisterValue(register,
Utils.bytesToBigInteger(data, data.length, lang.isBigEndian(), false)); Utils.bytesToBigInteger(data, data.length, lang.isBigEndian(), false));
TraceMemoryRegisterSpace regs = TraceMemorySpace regs =
getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frameLevel, false); getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frameLevel, false);
rv = TraceRegisterUtils.combineWithTraceBaseRegisterValue(rv, getSnap(), regs, true); rv = TraceRegisterUtils.combineWithTraceBaseRegisterValue(rv, getSnap(), regs, true);
return writeThreadRegisters(thread, frameLevel, Map.of(rv.getRegister(), rv)); 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.TraceLocation;
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
import ghidra.trace.model.memory.TraceMemoryOperations; 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.program.TraceProgramView;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
@ -947,7 +947,7 @@ public interface FlatDebuggerAPI {
catch (InterruptedException | ExecutionException | TimeoutException e) { catch (InterruptedException | ExecutionException | TimeoutException e) {
return null; return null;
} }
TraceMemoryRegisterSpace regs = TraceMemorySpace regs =
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frame, false); thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frame, false);
if (regs == null) { if (regs == null) {
return registers.stream().map(RegisterValue::new).collect(Collectors.toList()); 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.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.model.memory.TraceMemoryFlag; 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.symbol.*;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
@ -110,7 +110,7 @@ public class DebuggerListingPluginScreenShots extends GhidraScreenShotGenerator
TraceThread thread = tb.getOrAddThread("[1]", snap); TraceThread thread = tb.getOrAddThread("[1]", snap);
TraceMemoryRegisterSpace regs = TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(), regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(),
childLabel.getAddress().getOffsetAsBigInteger())); childLabel.getAddress().getOffsetAsBigInteger()));

View file

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

View file

@ -28,7 +28,7 @@ import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.RegisterValue; import ghidra.program.model.lang.RegisterValue;
import ghidra.test.ToyProgramBuilder; import ghidra.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder; 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.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
import help.screenshot.GhidraScreenShotGenerator; import help.screenshot.GhidraScreenShotGenerator;
@ -62,7 +62,7 @@ public class DebuggerRegistersPluginScreenShots extends GhidraScreenShotGenerato
long snap1 = tb.trace.getTimeManager().createSnapshot("Second").getKey(); long snap1 = tb.trace.getTimeManager().createSnapshot("Second").getKey();
TraceThread thread = tb.getOrAddThread("[1]", snap0); TraceThread thread = tb.getOrAddThread("[1]", snap0);
TraceMemoryRegisterSpace regs = TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
Language lang = tb.trace.getBaseLanguage(); Language lang = tb.trace.getBaseLanguage();
regs.setValue(snap0, 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.DBTraceInstruction;
import ghidra.trace.database.listing.DBTraceInstructionsMemoryView; import ghidra.trace.database.listing.DBTraceInstructionsMemoryView;
import ghidra.trace.database.memory.DBTraceMemoryManager; 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.program.DBTraceVariableSnapProgramView;
import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObject;
import ghidra.trace.database.target.DBTraceObjectManager; import ghidra.trace.database.target.DBTraceObjectManager;
@ -225,7 +225,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
TraceThread thread; TraceThread thread;
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
thread = tb.getOrAddThread("Threads[0]", 0); thread = tb.getOrAddThread("Threads[0]", 0);
DBTraceMemoryRegisterSpace regs = DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO)); regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO));
} }
@ -259,7 +259,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
TraceThread thread; TraceThread thread;
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
thread = tb.getOrAddThread("Threads[0]", 0); thread = tb.getOrAddThread("Threads[0]", 0);
DBTraceMemoryRegisterSpace regs = DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, regs.setValue(0,
new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ONE.shiftLeft(5))); 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.database.ToyDBTraceBuilder;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.Trace.TraceMemoryBytesChangeType; 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.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.InvalidNameException; import ghidra.util.InvalidNameException;
@ -750,7 +750,7 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
if (space.getThread() != traceThread) { if (space.getThread() != traceThread) {
return; return;
} }
TraceMemoryRegisterSpace regSpace = TraceMemorySpace regSpace =
trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false); trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false);
assertNotNull(regSpace); assertNotNull(regSpace);
for (Map.Entry<String, byte[]> ent : values.entrySet()) { 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 // NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -208,7 +208,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing // NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -237,9 +237,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing // NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); 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))); regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -282,9 +282,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
// NOTE: PC-tracking should be the default for the main dynamic listing // NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); 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))); regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -322,7 +322,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
assertEquals(tb.trace.getProgramView(), listingProvider.getProgram()); assertEquals(tb.trace.getProgramView(), listingProvider.getProgram());
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true); TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer(); Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800))); regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800)));
} }
@ -356,7 +356,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t1 = b1.getOrAddThread("Thread1", 0); t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -368,7 +368,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t2 = b2.getOrAddThread("Thread2", 0); t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -412,7 +412,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t1 = b1.getOrAddThread("Thread1", 0); t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -424,7 +424,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
t2 = b2.getOrAddThread("Thread2", 0); t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -505,7 +505,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
thread = tb.getOrAddThread("Thread1", 0); thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForProgram(program); waitForProgram(program);
@ -582,7 +582,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
thread = tb.getOrAddThread("Thread1", 0); thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -618,7 +618,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
thread = tb.getOrAddThread("Thread1", 0); thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00408765))); 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), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register r0 = tb.language.getRegister("r0"); Register r0 = tb.language.getRegister("r0");
regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16))); regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16)));
mm.putBytes(0, tb.addr(0x00401234), tb.buf(0x00, 0x40, 0x43, 0x21)); 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), mm.addRegion("[stack]", Range.atLeast(0L), tb.range(0x1f000000, 0x1fffffff),
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
thread = tb.getOrAddThread("Thread 1", 0); thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register pc = tb.language.getProgramCounter(); Register pc = tb.language.getProgramCounter();
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer(); 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 // NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); 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))); regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -1309,9 +1309,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread1 = tb.getOrAddThread("Thread 1", 0); thread1 = tb.getOrAddThread("Thread 1", 0);
thread2 = tb.getOrAddThread("Thread 2", 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))); 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))); regs2.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -1338,7 +1338,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); 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(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 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), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); 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(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -1404,7 +1404,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress()); assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) { 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))); regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -1424,7 +1424,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); 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(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
DBTraceStackManager sm = tb.trace.getStackManager(); DBTraceStackManager sm = tb.trace.getStackManager();
@ -1438,7 +1438,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress()); assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) { 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))); regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
} }
waitForDomainObject(tb.trace); 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 // NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -184,7 +184,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer // NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -214,9 +214,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer // NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); 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))); regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -259,9 +259,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
// NOTE: PC-tracking should be the default for the main bytes viewer // NOTE: PC-tracking should be the default for the main bytes viewer
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); 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))); regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -299,7 +299,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
assertEquals(tb.trace.getProgramView(), memBytesProvider.getProgram()); assertEquals(tb.trace.getProgramView(), memBytesProvider.getProgram());
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true); TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer(); Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800))); regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800)));
} }
@ -332,7 +332,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t1 = b1.getOrAddThread("Thread1", 0); t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -344,7 +344,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t2 = b2.getOrAddThread("Thread2", 0); t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -383,7 +383,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t1 = b1.getOrAddThread("Thread1", 0); t1 = b1.getOrAddThread("Thread1", 0);
Register pc = b1.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -395,7 +395,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
t2 = b2.getOrAddThread("Thread2", 0); t2 = b2.getOrAddThread("Thread2", 0);
Register pc = b2.trace.getBaseLanguage().getProgramCounter(); 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))); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(b1.trace); waitForDomainObject(b1.trace);
@ -456,7 +456,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
thread = tb.getOrAddThread("Thread1", 0); thread = tb.getOrAddThread("Thread1", 0);
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -616,7 +616,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register r0 = tb.language.getRegister("r0"); Register r0 = tb.language.getRegister("r0");
regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16))); regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16)));
mm.putBytes(0, tb.addr(0x00401234), tb.buf(0x00, 0x40, 0x43, 0x21)); 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), mm.addRegion("[stack]", Range.atLeast(0L), tb.range(0x1f000000, 0x1fffffff),
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
thread = tb.getOrAddThread("Thread 1", 0); thread = tb.getOrAddThread("Thread 1", 0);
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
Register pc = tb.language.getProgramCounter(); Register pc = tb.language.getProgramCounter();
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer(); 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 // NOTE: PC-tracking should be the default for the main dynamic listing
Register pc = tb.trace.getBaseLanguage().getProgramCounter(); 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))); 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))); regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -911,9 +911,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread1 = tb.getOrAddThread("Thread 1", 0); thread1 = tb.getOrAddThread("Thread 1", 0);
thread2 = tb.getOrAddThread("Thread 2", 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))); 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))); regs2.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -940,7 +940,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); 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(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 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), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); 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(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -1006,7 +1006,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress()); assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) { 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))); regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -1026,7 +1026,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("Thread 1", 0); 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(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
DBTraceStackManager sm = tb.trace.getStackManager(); DBTraceStackManager sm = tb.trace.getStackManager();
@ -1040,7 +1040,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress()); assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
try (UndoableTransaction tid = tb.startTransaction()) { 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))); regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);

View file

@ -46,10 +46,10 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.ToyDBTraceBuilder; 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.listing.*;
import ghidra.trace.model.memory.TraceMemoryFlag; 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.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -122,7 +122,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
} }
protected void addRegisterValues(TraceThread thread, UndoableTransaction tid) { protected void addRegisterValues(TraceThread thread, UndoableTransaction tid) {
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regVals.putBytes(0, pc, tb.buf(0, 0, 0, 0, 0, 0x40, 0, 0)); 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)); 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) protected void addRegisterTypes(TraceThread thread, UndoableTransaction tid)
throws CodeUnitInsertionException { throws CodeUnitInsertionException {
TraceCodeRegisterSpace regCode = TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true); tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
regCode.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType); regCode.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
// TODO: Pointer needs to be to ram, not register space // TODO: Pointer needs to be to ram, not register space
@ -384,7 +384,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
addRegisterValues(thread); addRegisterValues(thread);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
RegisterRow row = findRegisterRow(r0); RegisterRow row = findRegisterRow(r0);
@ -422,7 +422,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
addRegisterValues(thread); addRegisterValues(thread);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
RegisterRow row = findRegisterRow(r0); RegisterRow row = findRegisterRow(r0);
@ -456,7 +456,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
row.setDataType(PointerDataType.dataType); row.setDataType(PointerDataType.dataType);
waitForSwing(); waitForSwing();
DBTraceCodeRegisterSpace regCode = DBTraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false); tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
assertNotNull(regCode); assertNotNull(regCode);
TraceData data = regCode.data().getForRegister(0L, pc); TraceData data = regCode.data().getForRegister(0L, pc);
@ -478,7 +478,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
row.setDataType(LongLongDataType.dataType); row.setDataType(LongLongDataType.dataType);
waitForSwing(); waitForSwing();
DBTraceCodeRegisterSpace regCode = DBTraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false); tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
assertNotNull(regCode); assertNotNull(regCode);
TraceData data = regCode.data().getForRegister(0L, pc); TraceData data = regCode.data().getForRegister(0L, pc);
@ -514,7 +514,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
rowH.setDataType(SignedDWordDataType.dataType); rowH.setDataType(SignedDWordDataType.dataType);
waitForSwing(); waitForSwing();
DBTraceCodeRegisterSpace regCode = DBTraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false); tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
assertNotNull(regCode); assertNotNull(regCode);
// It's two units, not a struct with two components // It's two units, not a struct with two components
@ -621,9 +621,9 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowValuePopulated(); assertR0RowValuePopulated();
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
TraceCodeRegisterSpace regCode = TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true); tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
regVals.putBytes(1, r0, tb.buf(1, 1, 2, 2, 3, 3, 4, 4)); regVals.putBytes(1, r0, tb.buf(1, 1, 2, 2, 3, 3, 4, 4));
regCode.definedData().create(Range.atLeast(1L), r0, r0Struct); regCode.definedData().create(Range.atLeast(1L), r0, r0Struct);
@ -649,7 +649,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated(); assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceCodeRegisterSpace regCode = TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true); tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0); TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0);
code.setEndSnap(0); code.setEndSnap(0);
@ -679,7 +679,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated(); assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceCodeRegisterSpace regCode = TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true); tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0); TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0);
code.delete(); code.delete();
@ -890,9 +890,9 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated(); assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
TraceCodeRegisterSpace regCode = TraceCodeSpace regCode =
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true); tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
regVals.putBytes(10, r0, tb.buf(0, 0, 0, 0, 0, 0, 0, 0)); 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 // NB. the manager should have split the data unit at the value change
@ -932,11 +932,11 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
assertR0RowTypePopulated(); assertR0RowTypePopulated();
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, 1, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, 1, true);
regVals.putBytes(0, pc, tb.buf(0, 0, 0, 0, 0, 0x50, 0, 0)); 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); tb.trace.getCodeManager().getCodeRegisterSpace(thread, 1, true);
regCode.definedData().create(Range.atLeast(0L), pc, QWordDataType.dataType); 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.DefaultTraceLocation;
import ghidra.trace.model.TraceLocation; import ghidra.trace.model.TraceLocation;
import ghidra.trace.model.memory.TraceMemoryFlag; 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.TraceStack;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
@ -73,7 +73,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
protected void addRegVals(TraceThread thread) { protected void addRegVals(TraceThread thread) {
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regs = TraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(pc, new BigInteger("00400123", 16))); 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) { private void setRegisterValues(TraceThread thread) {
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x00400000))); regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x00400000)));
} }
@ -318,7 +318,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
waitForSwing(); waitForSwing();
// Verify no target read has occurred yet // Verify no target read has occurred yet
TraceMemoryRegisterSpace regs = TraceMemorySpace regs =
trace.getMemoryManager().getMemoryRegisterSpace(thread, false); trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
if (regs != null) { if (regs != null) {
assertEquals(BigInteger.ZERO, regs.getValue(0, r0).getUnsignedValue()); assertEquals(BigInteger.ZERO, regs.getValue(0, r0).getUnsignedValue());
@ -402,7 +402,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
@Test @Test
public void testEditRegisterEmu() { public void testEditRegisterEmu() {
WatchRow row = prepareTestEditEmu("r0"); WatchRow row = prepareTestEditEmu("r0");
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
row.setRawValueString("0x1234"); row.setRawValueString("0x1234");
@ -433,7 +433,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
waitForSwing(); waitForSwing();
assertTrue(row.isValueEditable()); assertTrue(row.isValueEditable());
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
row.setValueString("1234"); row.setValueString("1234");
@ -748,7 +748,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
.createLabel(tb.addr(0x00601234), "my_symbol", SourceType.USER_DEFINED); .createLabel(tb.addr(0x00601234), "my_symbol", SourceType.USER_DEFINED);
} }
try (UndoableTransaction tid = tb.startTransaction()) { try (UndoableTransaction tid = tb.startTransaction()) {
TraceMemoryRegisterSpace regVals = TraceMemorySpace regVals =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x55751234))); 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.lang.*;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.trace.database.DBTraceUtils; 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.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
@ -366,8 +366,8 @@ public class DebuggerStateEditingServiceTest extends AbstractGhidraHeadedDebugge
StateEditor editor = editingService.createStateEditor(tb.trace); StateEditor editor = editingService.createStateEditor(tb.trace);
waitOn(editor.setRegister(rv1234)); waitOn(editor.setRegister(rv1234));
waitForPass(() -> { waitForPass(() -> {
DBTraceMemoryRegisterSpace regs = tb.trace.getMemoryManager() TraceMemorySpace regs =
.getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertNotNull(regs); assertNotNull(regs);
RegisterValue value = regs.getValue(traceManager.getCurrentSnap(), r0); RegisterValue value = regs.getValue(traceManager.getCurrentSnap(), r0);
assertEquals(rv1234, value); assertEquals(rv1234, value);

View file

@ -36,7 +36,7 @@ import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.Trace; 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.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
@ -89,8 +89,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
assertNotNull(trace); assertNotNull(trace);
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads()); TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
TraceMemoryRegisterSpace regs = TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertEquals(new BigInteger("00400000", 16), assertEquals(new BigInteger("00400000", 16),
regs.getViewValue(0, regPC).getUnsignedValue()); regs.getViewValue(0, regPC).getUnsignedValue());
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue()); assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue());
@ -146,8 +145,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
assertNotNull(trace); assertNotNull(trace);
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads()); TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
TraceMemoryRegisterSpace regs = TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertEquals(new BigInteger("00000400", 16), assertEquals(new BigInteger("00000400", 16),
regs.getViewValue(0, regPC).getUnsignedValue()); regs.getViewValue(0, regPC).getUnsignedValue());
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue()); assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue());
@ -205,8 +203,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
assertNotNull(trace); assertNotNull(trace);
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads()); TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
TraceMemoryRegisterSpace regs = TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertEquals(new BigInteger("000100", 16), assertEquals(new BigInteger("000100", 16),
regs.getViewValue(0, regPC).getUnsignedValue()); regs.getViewValue(0, regPC).getUnsignedValue());
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regW0).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.program.model.lang.Register;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange; 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.memory.*;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.UndoableTransaction; 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 = try (UndoableTransaction tid =
UndoableTransaction.start(thread.getTrace(), "Create register space")) { UndoableTransaction.start(thread.getTrace(), "Create register space")) {
return thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, true); return thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, true);
@ -105,7 +105,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
Register r1 = lang.getRegister("r1"); Register r1 = lang.getRegister("r1");
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
//TraceThread thread = recorder.getTraceThread(mb.testThread1); //TraceThread thread = recorder.getTraceThread(mb.testThread1);
TraceMemoryRegisterSpace rs = createRegSpace(thread); TraceMemorySpace rs = createRegSpace(thread);
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(), mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
Register::isBaseRegister); Register::isBaseRegister);
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank(); TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
@ -138,13 +138,13 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
Register pc = lang.getRegister("pc"); Register pc = lang.getRegister("pc");
Register sp = lang.getRegister("sp"); Register sp = lang.getRegister("sp");
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); 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.addRegion("bin:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(), mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
r -> r.isBaseRegister() && r != pc && r != sp); r -> r.isBaseRegister() && r != pc && r != sp);
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank(); TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add PC type")) { 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); code.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
} }
@ -187,13 +187,13 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
Register pc = lang.getRegister("pc"); Register pc = lang.getRegister("pc");
Register sp = lang.getRegister("sp"); Register sp = lang.getRegister("sp");
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); 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.addRegion("[stack]", mb.rng(0x22220000, 0x2222ffff), "rw");
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(), mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
r -> r.isBaseRegister() && r != pc && r != sp); r -> r.isBaseRegister() && r != pc && r != sp);
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank(); TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add SP type")) { 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); code.definedData().create(Range.atLeast(0L), sp, PointerDataType.dataType);
} }
@ -242,7 +242,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
//waitForCondition(() -> registerMapped(recorder, thread, pc)); //waitForCondition(() -> registerMapped(recorder, thread, pc));
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add PC type")) { 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); code.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
} }
regs.writeRegister("pc", tb.arr(0x55, 0x55, 0x02, 0x22)); 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.lang.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.trace.database.memory.DBTraceMemoryManager; 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.Trace;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
@ -718,7 +718,7 @@ public class FlatDebuggerAPITest extends AbstractGhidraHeadedDebuggerGUITest {
waitForSwing(); waitForSwing();
assertTrue(flat.writeRegister(thread, 0, 0, "r0", BigInteger.valueOf(0x0102030405060708L))); assertTrue(flat.writeRegister(thread, 0, 0, "r0", BigInteger.valueOf(0x0102030405060708L)));
DBTraceMemoryRegisterSpace regs = DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertNotNull(regs); assertNotNull(regs);
Register r0 = tb.language.getRegister("r0"); Register r0 = tb.language.getRegister("r0");
@ -734,7 +734,7 @@ public class FlatDebuggerAPITest extends AbstractGhidraHeadedDebuggerGUITest {
waitForSwing(); waitForSwing();
assertTrue(flat.writeRegister("r0", BigInteger.valueOf(0x0102030405060708L))); assertTrue(flat.writeRegister("r0", BigInteger.valueOf(0x0102030405060708L)));
DBTraceMemoryRegisterSpace regs = DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
assertNotNull(regs); assertNotNull(regs);
Register r0 = tb.language.getRegister("r0"); 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.Register;
import ghidra.program.model.lang.RegisterValue; import ghidra.program.model.lang.RegisterValue;
import ghidra.trace.model.Trace; 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.memory.TraceMemoryState;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.thread.TraceThreadManager; import ghidra.trace.model.thread.TraceThreadManager;
@ -88,7 +88,7 @@ public interface TracePcodeMachine<T> extends PcodeMachine<T> {
long snap = getSnap(); long snap = getSnap();
TraceThread traceThread = TraceThread traceThread =
trace.getThreadManager().getLiveThreadByPath(snap, thread.getName()); trace.getThreadManager().getLiveThreadByPath(snap, thread.getName());
TraceMemoryRegisterSpace space = TraceMemorySpace space =
trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false); trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false);
if (space == null) { if (space == null) {
return false; return false;

View file

@ -44,8 +44,7 @@ import ghidra.util.database.DBOpenMode;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceBookmarkManager public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBTraceBookmarkSpace>
extends AbstractDBTraceSpaceBasedManager<DBTraceBookmarkSpace, DBTraceBookmarkRegisterSpace>
implements TraceBookmarkManager, DBTraceDelegatingManager<DBTraceBookmarkSpace> { implements TraceBookmarkManager, DBTraceDelegatingManager<DBTraceBookmarkSpace> {
public static final String NAME = "Bookmark"; public static final String NAME = "Bookmark";
@ -180,13 +179,13 @@ public class DBTraceBookmarkManager
@Override @Override
protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceBookmarkSpace(this, space); return new DBTraceBookmarkSpace(this, space, null, 0);
} }
@Override @Override
protected DBTraceBookmarkRegisterSpace createRegisterSpace(AddressSpace space, protected DBTraceBookmarkSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceBookmarkRegisterSpace(this, space, thread, ent.getFrameLevel()); return new DBTraceBookmarkSpace(this, space, thread, ent.getFrameLevel());
} }
@Override @Override
@ -195,13 +194,13 @@ public class DBTraceBookmarkManager
} }
@Override @Override
public DBTraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceThread thread, public DBTraceBookmarkSpace getBookmarkRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent); return getForRegisterSpace(thread, 0, createIfAbsent);
} }
@Override @Override
public DBTraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceStackFrame frame, public DBTraceBookmarkSpace getBookmarkRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(frame, 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 DBTraceBookmarkManager manager;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final DBTrace trace; protected final DBTrace trace;
protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBookmark, DBTraceBookmark> bookmarkMapSpace; protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBookmark, DBTraceBookmark> bookmarkMapSpace;
protected final DBCachedObjectIndex<String, DBTraceBookmark> bookmarksByTypeName; protected final DBCachedObjectIndex<String, DBTraceBookmark> bookmarksByTypeName;
protected final Collection<DBTraceBookmark> bookmarkView; protected final Collection<DBTraceBookmark> bookmarkView;
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space) public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space,
TraceThread thread, int frameLevel)
throws VersionException, IOException { throws VersionException, IOException {
this.manager = manager; this.manager = manager;
this.lock = manager.getLock(); this.lock = manager.getLock();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
this.space = space;
this.thread = thread;
this.frameLevel = frameLevel;
this.bookmarkMapSpace = this.bookmarkMapSpace =
new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space, -1, 0), 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)); (t, s, r) -> new DBTraceBookmark(this, t, s, r));
this.bookmarksByTypeName = this.bookmarksByTypeName =
bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN); bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN);
@ -61,17 +68,17 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
@Override @Override
public AddressSpace getAddressSpace() { public AddressSpace getAddressSpace() {
return bookmarkMapSpace.getAddressSpace(); return space;
} }
@Override @Override
public TraceThread getThread() { public TraceThread getThread() {
return null; return thread;
} }
@Override @Override
public int getFrameLevel() { public int getFrameLevel() {
return 0; return frameLevel;
} }
protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) { protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) {

View file

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

View file

@ -67,7 +67,7 @@ public class DBTraceBreakpointSpace implements DBTraceSpaceBased {
assert threadKey == -1; // No breakpoints on registers assert threadKey == -1; // No breakpoints on registers
breakpointMapSpace = breakpointMapSpace =
new DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint>( 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)); DBTraceBreakpoint.class, (t, s, r) -> new DBTraceBreakpoint(this, t, s, r));
breakpointsByPath = breakpointsByPath =
breakpointMapSpace.getUserIndex(String.class, DBTraceBreakpoint.PATH_COLUMN); 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.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceRegisterContextManager extends public class DBTraceRegisterContextManager
AbstractDBTraceSpaceBasedManager<DBTraceRegisterContextSpace, DBTraceRegisterContextRegisterSpace> extends AbstractDBTraceSpaceBasedManager<DBTraceRegisterContextSpace>
implements TraceRegisterContextManager, implements TraceRegisterContextManager,
DBTraceDelegatingManager<DBTraceRegisterContextSpace> { DBTraceDelegatingManager<DBTraceRegisterContextSpace> {
public static final String NAME = "RegisterContext"; public static final String NAME = "RegisterContext";
@ -100,14 +100,14 @@ public class DBTraceRegisterContextManager extends
@Override @Override
protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceRegisterContextSpace(this, dbh, space, ent); return new DBTraceRegisterContextSpace(this, dbh, space, ent, null);
} }
@Override @Override
protected DBTraceRegisterContextRegisterSpace createRegisterSpace(AddressSpace space, protected DBTraceRegisterContextSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
// TODO: Should I just forbid this? It doesn't seem sane. Then again, what do I know? // 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 @Override
@ -132,7 +132,7 @@ public class DBTraceRegisterContextManager extends
} }
@Override @Override
public DBTraceRegisterContextRegisterSpace getRegisterContextRegisterSpace(TraceThread thread, public DBTraceRegisterContextSpace getRegisterContextRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, 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 DBTraceRegisterContextManager manager;
protected final DBHandle dbh; protected final DBHandle dbh;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final Language baseLanguage; protected final Language baseLanguage;
protected final DBTrace trace; protected final DBTrace trace;
@ -91,10 +93,13 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
new HashMap<>(); new HashMap<>();
public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh, 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.manager = manager;
this.dbh = dbh; this.dbh = dbh;
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock(); this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage(); this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
@ -129,7 +134,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
@Override @Override
public TraceThread getThread() { public TraceThread getThread() {
return null; return thread;
} }
protected long getThreadKey() { protected long getThreadKey() {
@ -139,7 +144,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
@Override @Override
public int getFrameLevel() { public int getFrameLevel() {
return 0; return frameLevel;
} }
protected String tableName(Language language, Register register) { protected String tableName(Language language, Register register) {
@ -152,7 +157,8 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
String name = tableName(lr.getLeft(), lr.getRight()); String name = tableName(lr.getLeft(), lr.getRight());
try { try {
return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(), return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(),
lock, space, DBTraceRegisterContextEntry.class, DBTraceRegisterContextEntry::new); lock, space, thread, frameLevel, DBTraceRegisterContextEntry.class,
DBTraceRegisterContextEntry::new);
} }
catch (IOException e) { catch (IOException e) {
manager.dbError(e); manager.dbError(e);

View file

@ -159,29 +159,8 @@ public class DBTraceDataSettingsAdapter
DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry> DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
implements DBTraceDataSettingsOperations { implements DBTraceDataSettingsOperations {
public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory, public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
ReadWriteLock lock, AddressSpace space, Class<DBTraceSettingsEntry> dataType, ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory) Class<DBTraceSettingsEntry> dataType,
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,
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory) DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
throws VersionException, IOException { throws VersionException, IOException {
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory); super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
@ -206,20 +185,20 @@ public class DBTraceDataSettingsAdapter
} }
@Override @Override
protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceDataSettingsSpace createSpace(
throws VersionException, IOException { AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceDataSettingsSpace( return new DBTraceDataSettingsSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
trace.getStoreFactory(), lock, space, dataType, dataFactory); lock, space, null, 0, dataType, dataFactory);
} }
@Override @Override
protected DBTraceDataSettingsRegisterSpace createRegisterSpace(AddressSpace space, protected DBTraceDataSettingsSpace createRegisterSpace(
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
return new DBTraceDataSettingsRegisterSpace( throws VersionException, IOException {
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), return new DBTraceDataSettingsSpace(
trace.getStoreFactory(), lock, space, thread, ent.getFrameLevel(), dataType, tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
dataFactory); lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
} }
@Override @Override
@ -228,9 +207,9 @@ public class DBTraceDataSettingsAdapter
} }
@Override @Override
public DBTraceDataSettingsRegisterSpace getRegisterSpace(TraceThread thread, public DBTraceDataSettingsSpace getRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return (DBTraceDataSettingsRegisterSpace) super.getRegisterSpace(thread, createIfAbsent); return (DBTraceDataSettingsSpace) super.getRegisterSpace(thread, createIfAbsent);
} }
@Override @Override

View file

@ -28,42 +28,126 @@ import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.space.DBTraceDelegatingManager; import ghidra.trace.database.space.DBTraceDelegatingManager;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.LockHold; 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>> public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>>
implements DBTraceDelegatingManager<M> { implements DBTraceDelegatingManager<M> {
protected final DBTraceCodeManager manager; protected final DBTraceCodeManager manager;
protected final Collection<M> activeSpacesView; protected final Collection<M> activeSpacesView;
/**
* Construct a composite view
*
* @param manager the code manager, from which individual views are retrieved
*/
public AbstractBaseDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) { public AbstractBaseDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
this.manager = manager; this.manager = manager;
this.activeSpacesView = this.activeSpacesView =
Collections2.transform(manager.getActiveMemorySpaces(), this::getView); Collections2.transform(manager.getActiveMemorySpaces(), this::getView);
} }
/**
* @see TraceBaseCodeUnitsView#getTrace()
*/
public Trace getTrace() { public Trace getTrace() {
return manager.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); 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) { protected T nullOrUndefined(long snap, Address address) {
return null; 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) { protected AddressSetView emptyOrFullAddressSetUndefined(AddressRange within) {
return new AddressSet(); 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() { protected boolean falseOrTrueUndefined() {
return false; 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, public Iterable<? extends T> emptyOrFullIterableUndefined(long snap, AddressRange range,
boolean forward) { boolean forward) {
return Collections.emptyList(); return Collections.emptyList();
} }
/**
* @see #emptyOrFullIterableUndefined(long, AddressRange, boolean)
*/
public Iterable<? extends T> emptyOrFullIterableUndefined(TraceAddressSnapRange tasr) { public Iterable<? extends T> emptyOrFullIterableUndefined(TraceAddressSnapRange tasr) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -84,6 +168,16 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return codeSpace == null ? null : getView(codeSpace); 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) { protected Address prevAddress(Address address) {
Address prev = address.previous(); Address prev = address.previous();
if (prev != null) { if (prev != null) {
@ -108,6 +202,15 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return prevRange.getMaxAddress(); 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) { protected Address nextAddress(Address address) {
Address next = address.next(); Address next = address.next();
if (next != null) { if (next != null) {
@ -132,6 +235,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return nextRange.getMinAddress(); return nextRange.getMinAddress();
} }
/**
* @see TraceBaseCodeUnitsView#size()
*/
public int size() { public int size() {
int sum = 0; int sum = 0;
for (M m : activeSpacesView) { for (M m : activeSpacesView) {
@ -140,6 +246,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return sum; return sum;
} }
/**
* @see TraceBaseCodeUnitsView#getBefore(long, Address)
*/
public T getBefore(long snap, Address address) { public T getBefore(long snap, Address address) {
Address prev = prevAddress(address); Address prev = prevAddress(address);
if (prev == null) { if (prev == null) {
@ -148,6 +257,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return getFloor(snap, prev); return getFloor(snap, prev);
} }
/**
* @see TraceBaseCodeUnitsView#getFloor(long, Address)
*/
public T getFloor(long snap, Address address) { public T getFloor(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) { try (LockHold hold = LockHold.lock(readLock())) {
for (AddressRange range : DBTraceUtils.getAddressSet( 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) { public T getContaining(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) { try (LockHold hold = LockHold.lock(readLock())) {
M m = getForSpace(address.getAddressSpace(), false); 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) { public T getAt(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) { try (LockHold hold = LockHold.lock(readLock())) {
M m = getForSpace(address.getAddressSpace(), false); 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) { public T getCeiling(long snap, Address address) {
try (LockHold hold = LockHold.lock(readLock())) { try (LockHold hold = LockHold.lock(readLock())) {
for (AddressRange range : DBTraceUtils.getAddressSet( 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) { public T getAfter(long snap, Address address) {
Address next = nextAddress(address); Address next = nextAddress(address);
if (next == null) { if (next == null) {
@ -206,6 +330,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return getCeiling(snap, next); return getCeiling(snap, next);
} }
/**
* @see TraceBaseCodeUnitsView#get(long, Address, Address, boolean)
*/
public Iterable<? extends T> get(long snap, Address min, Address max, boolean forward) { public Iterable<? extends T> get(long snap, Address min, Address max, boolean forward) {
if (min.hasSameAddressSpace(max)) { if (min.hasSameAddressSpace(max)) {
return get(snap, new AddressRangeImpl(min, max), forward); return get(snap, new AddressRangeImpl(min, max), forward);
@ -214,11 +341,17 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
forward); forward);
} }
/**
* @see TraceBaseCodeUnitsView#get(long, AddressSetView, boolean)
*/
public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) { public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) {
return () -> NestedIterator.start(set.iterator(forward), return () -> NestedIterator.start(set.iterator(forward),
r -> get(snap, r, forward).iterator()); r -> get(snap, r, forward).iterator());
} }
/**
* @see TraceBaseCodeUnitsView#get(long, AddressRange, boolean)
*/
public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) { public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) {
M m = getForSpace(range.getAddressSpace(), false); M m = getForSpace(range.getAddressSpace(), false);
if (m == null) { if (m == null) {
@ -227,15 +360,24 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return m.get(snap, range, forward); return m.get(snap, range, forward);
} }
/**
* @see TraceBaseCodeUnitsView#get(long, Address, boolean)
*/
public Iterable<? extends T> get(long snap, Address start, boolean forward) { public Iterable<? extends T> get(long snap, Address start, boolean forward) {
AddressFactory factory = manager.getBaseLanguage().getAddressFactory(); AddressFactory factory = manager.getBaseLanguage().getAddressFactory();
return get(snap, DBTraceUtils.getAddressSet(factory, start, forward), forward); return get(snap, DBTraceUtils.getAddressSet(factory, start, forward), forward);
} }
/**
* @see TraceBaseCodeUnitsView#get(long, boolean)
*/
public Iterable<? extends T> get(long snap, boolean forward) { public Iterable<? extends T> get(long snap, boolean forward) {
return get(snap, manager.getBaseLanguage().getAddressFactory().getAddressSet(), forward); return get(snap, manager.getBaseLanguage().getAddressFactory().getAddressSet(), forward);
} }
/**
* @see TraceBaseCodeUnitsView#getIntersecting(TraceAddressSnapRange)
*/
public Iterable<? extends T> getIntersecting(TraceAddressSnapRange tasr) { public Iterable<? extends T> getIntersecting(TraceAddressSnapRange tasr) {
M m = getForSpace(tasr.getX1().getAddressSpace(), false); M m = getForSpace(tasr.getX1().getAddressSpace(), false);
if (m == null) { if (m == null) {
@ -244,6 +386,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return m.getIntersecting(tasr); return m.getIntersecting(tasr);
} }
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long, AddressRange)
*/
public AddressSetView getAddressSetView(long snap, AddressRange within) { public AddressSetView getAddressSetView(long snap, AddressRange within) {
M m = getForSpace(within.getAddressSpace(), false); M m = getForSpace(within.getAddressSpace(), false);
if (m == null) { if (m == null) {
@ -252,6 +397,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return m.getAddressSetView(snap, within); return m.getAddressSetView(snap, within);
} }
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long)
*/
public AddressSetView getAddressSetView(long snap) { public AddressSetView getAddressSetView(long snap) {
AddressSet result = new AddressSet(); AddressSet result = new AddressSet();
for (AddressRange range : manager.getBaseLanguage().getAddressFactory().getAddressSet()) { for (AddressRange range : manager.getBaseLanguage().getAddressFactory().getAddressSet()) {
@ -266,26 +414,41 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
return result; return result;
} }
/**
* @see TraceBaseCodeUnitsView#containsAddress(long, Address)
*/
public boolean containsAddress(long snap, Address address) { public boolean containsAddress(long snap, Address address) {
return delegateRead(address.getAddressSpace(), m -> m.containsAddress(snap, address), return delegateRead(address.getAddressSpace(), m -> m.containsAddress(snap, address),
falseOrTrueUndefined()); falseOrTrueUndefined());
} }
/**
* @see TraceBaseCodeUnitsView#coversRange(Range, AddressRange)
*/
public boolean coversRange(Range<Long> span, AddressRange range) { public boolean coversRange(Range<Long> span, AddressRange range) {
return delegateRead(range.getAddressSpace(), m -> m.coversRange(span, range), return delegateRead(range.getAddressSpace(), m -> m.coversRange(span, range),
falseOrTrueUndefined()); falseOrTrueUndefined());
} }
/**
* @see TraceBaseCodeUnitsView#coversRange(TraceAddressSnapRange)
*/
public boolean coversRange(TraceAddressSnapRange range) { public boolean coversRange(TraceAddressSnapRange range) {
return delegateRead(range.getRange().getAddressSpace(), m -> m.coversRange(range), return delegateRead(range.getRange().getAddressSpace(), m -> m.coversRange(range),
falseOrTrueUndefined()); falseOrTrueUndefined());
} }
/**
* @see TraceBaseCodeUnitsView#intersectsRange(Range, AddressRange)
*/
public boolean intersectsRange(Range<Long> span, AddressRange range) { public boolean intersectsRange(Range<Long> span, AddressRange range) {
return delegateRead(range.getAddressSpace(), m -> m.intersectsRange(span, range), return delegateRead(range.getAddressSpace(), m -> m.intersectsRange(span, range),
falseOrTrueUndefined()); falseOrTrueUndefined());
} }
/**
* @see TraceBaseCodeUnitsView#intersectsRange(TraceAddressSnapRange)
*/
public boolean intersectsRange(TraceAddressSnapRange range) { public boolean intersectsRange(TraceAddressSnapRange range) {
return delegateRead(range.getRange().getAddressSpace(), m -> m.intersectsRange(range), return delegateRead(range.getRange().getAddressSpace(), m -> m.intersectsRange(range),
falseOrTrueUndefined()); falseOrTrueUndefined());

View file

@ -21,21 +21,70 @@ import generic.NestedIterator;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange; 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> { public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter> {
protected final DBTraceCodeSpace space; protected final DBTraceCodeSpace space;
/**
* Construct a view
*
* @param space the space, bound to an address space
*/
public AbstractBaseDBTraceCodeUnitsView(DBTraceCodeSpace space) { public AbstractBaseDBTraceCodeUnitsView(DBTraceCodeSpace space) {
this.space = 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() { public Trace getTrace() {
return space.manager.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(); public abstract int size();
/**
* @see TraceBaseCodeUnitsView#getBefore(long, Address)
*/
public T getBefore(long snap, Address address) { public T getBefore(long snap, Address address) {
Address previous = address.previous(); Address previous = address.previous();
if (previous == null) { if (previous == null) {
@ -44,14 +93,29 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
return getFloor(snap, previous); return getFloor(snap, previous);
} }
/**
* @see TraceBaseCodeUnitsView#getFloor(long, Address)
*/
public abstract T getFloor(long snap, Address address); public abstract T getFloor(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getContaining(long, Address)
*/
public abstract T getContaining(long snap, Address address); public abstract T getContaining(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getAt(long, Address)
*/
public abstract T getAt(long snap, Address address); public abstract T getAt(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getCeiling(long, Address)
*/
public abstract T getCeiling(long snap, Address address); public abstract T getCeiling(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#getAfter(long, Address)
*/
public T getAfter(long snap, Address address) { public T getAfter(long snap, Address address) {
Address next = address.next(); Address next = address.next();
if (next == null) { if (next == null) {
@ -60,50 +124,85 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
return getCeiling(snap, next); 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); 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); 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) { public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) {
return () -> NestedIterator.start(set.iterator(forward), return () -> NestedIterator.start(set.iterator(forward),
r -> this.get(snap, r, forward).iterator()); r -> this.get(snap, r, forward).iterator());
} }
/**
* @see TraceBaseCodeUnitsView#get(long, AddressRange, boolean)
*/
public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) { public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) {
return get(snap, range.getMinAddress(), range.getMaxAddress(), 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) { public Iterable<? extends T> get(long snap, Address start, boolean forward) {
return forward // return forward //
? get(snap, start, getAddressSpace().getMaxAddress(), forward) ? get(snap, start, getAddressSpace().getMaxAddress(), forward)
: get(snap, getAddressSpace().getMinAddress(), start, forward); : get(snap, getAddressSpace().getMinAddress(), start, forward);
} }
/**
* @see TraceBaseCodeUnitsView#get(long, boolean)
*/
public Iterable<? extends T> get(long snap, boolean forward) { public Iterable<? extends T> get(long snap, boolean forward) {
return get(snap, getAddressSpace().getMinAddress(), getAddressSpace().getMaxAddress(), return get(snap, getAddressSpace().getMinAddress(), getAddressSpace().getMaxAddress(),
forward); forward);
} }
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long, AddressRange)
*/
public abstract AddressSetView getAddressSetView(long snap, AddressRange within); public abstract AddressSetView getAddressSetView(long snap, AddressRange within);
/**
* @see TraceBaseCodeUnitsView#getAddressSetView(long)
*/
public AddressSetView getAddressSetView(long snap) { public AddressSetView getAddressSetView(long snap) {
return getAddressSetView(snap, space.all); return getAddressSetView(snap, space.all);
} }
/**
* @see TraceBaseCodeUnitsView#containsAddress(long, Address)
*/
public abstract boolean containsAddress(long snap, Address address); public abstract boolean containsAddress(long snap, Address address);
/**
* @see TraceBaseCodeUnitsView#coversRange(Range, AddressRange)
*/
public abstract boolean coversRange(Range<Long> span, AddressRange range); public abstract boolean coversRange(Range<Long> span, AddressRange range);
/**
* @see TraceBaseCodeUnitsView#coversRange(TraceAddressSnapRange)
*/
public boolean coversRange(TraceAddressSnapRange range) { public boolean coversRange(TraceAddressSnapRange range) {
return coversRange(range.getLifespan(), range.getRange()); return coversRange(range.getLifespan(), range.getRange());
} }
/**
* @see TraceBaseCodeUnitsView#intersectsRange(Range, AddressRange)
*/
public abstract boolean intersectsRange(Range<Long> span, AddressRange range); public abstract boolean intersectsRange(Range<Long> span, AddressRange range);
/**
* @see TraceBaseCodeUnitsView#intersectsRange(TraceAddressSnapRange)
*/
public boolean intersectsRange(TraceAddressSnapRange range) { public boolean intersectsRange(TraceAddressSnapRange range) {
return intersectsRange(range.getLifespan(), range.getRange()); 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.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.Trace.TraceCodeChangeType; import ghidra.trace.model.Trace.TraceCodeChangeType;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceBaseDefinedUnitsView;
import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceChangeRecord;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.database.spatial.rect.Rectangle2DDirection; import ghidra.util.database.spatial.rect.Rectangle2DDirection;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; 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>> public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTraceCodeUnit<T>>
extends AbstractSingleDBTraceCodeUnitsView<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_ADDRESS_BREADTH = 10000;
protected final static int CACHE_MAX_POINTS = 10000; protected final static int CACHE_MAX_POINTS = 10000;
/**
* Cache for optimizing {@link AbstractBaseDBTraceDefinedUnitsView#getAt(long, Address)}
*/
protected class CacheForGetUnitContainingQueries protected class CacheForGetUnitContainingQueries
extends DBTraceCacheForContainingQueries<GetKey, T, T> { 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> { protected class CacheForGetUnitSequenceQueries extends DBTraceCacheForSequenceQueries<T> {
public CacheForGetUnitSequenceQueries() { public CacheForGetUnitSequenceQueries() {
super(CACHE_MAX_REGIONS, CACHE_ADDRESS_BREADTH); super(CACHE_MAX_REGIONS, CACHE_ADDRESS_BREADTH);
@ -104,6 +122,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
protected final CacheForGetUnitSequenceQueries cacheForSequence = protected final CacheForGetUnitSequenceQueries cacheForSequence =
new CacheForGetUnitSequenceQueries(); 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, public AbstractBaseDBTraceDefinedUnitsView(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapSpace<T, T> mapSpace) { DBTraceAddressSnapRangePropertyMapSpace<T, T> mapSpace) {
super(space); super(space);
@ -121,6 +145,30 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
return !mapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).isEmpty(); 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, protected Set<TraceAddressSnapRange> subtractFrom(Range<Long> span, AddressRange range,
Set<TraceAddressSnapRange> cur, Set<TraceAddressSnapRange> set1, Set<TraceAddressSnapRange> cur, Set<TraceAddressSnapRange> set1,
Set<TraceAddressSnapRange> set2) { Set<TraceAddressSnapRange> set2) {
@ -239,6 +287,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
t -> true); 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) { protected void clearContext(Range<Long> span, AddressRange range) {
DBTraceRegisterContextSpace ctxSpace = DBTraceRegisterContextSpace ctxSpace =
space.trace.getRegisterContextManager().get(space, false); space.trace.getRegisterContextManager().get(space, false);
@ -248,6 +302,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
ctxSpace.clear(span, range); ctxSpace.clear(span, range);
} }
/**
* @see TraceBaseDefinedUnitsView#clear(Range, AddressRange, boolean, TaskMonitor)
*/
public void clear(Range<Long> span, AddressRange range, boolean clearContext, public void clear(Range<Long> span, AddressRange range, boolean clearContext,
TaskMonitor monitor) throws CancelledException { TaskMonitor monitor) throws CancelledException {
long startSnap = DBTraceUtils.lowerEndpoint(span); 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) { protected void unitRemoved(T unit) {
cacheForContaining.notifyEntryRemoved(unit.getLifespan(), unit.getRange(), unit); cacheForContaining.notifyEntryRemoved(unit.getLifespan(), unit.getRange(), unit);
cacheForSequence.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)); 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) { protected void unitSpanChanged(Range<Long> oldSpan, T unit) {
cacheForContaining.notifyEntryShapeChanged(unit.getLifespan(), unit.getRange(), unit); cacheForContaining.notifyEntryShapeChanged(unit.getLifespan(), unit.getRange(), unit);
cacheForSequence.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())); 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) protected Range<Long> truncateSoonestDefined(Range<Long> span, AddressRange range)
throws CodeUnitInsertionException { throws CodeUnitInsertionException {
T truncateBy = T truncateBy =
@ -308,6 +388,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
truncateBy.getStartSnap() - 1); truncateBy.getStartSnap() - 1);
} }
/**
* Invalidate the query-optimizing caches for this view
*/
public void invalidateCache() { public void invalidateCache() {
cacheForContaining.invalidate(); cacheForContaining.invalidate();
cacheForSequence.invalidate(); cacheForSequence.invalidate();

View file

@ -26,20 +26,46 @@ import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeUnit; import ghidra.trace.model.listing.TraceCodeUnit;
import ghidra.util.*; 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, // public abstract class AbstractComposedDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter, //
P extends AbstractSingleDBTraceCodeUnitsView<? extends T>> P extends AbstractSingleDBTraceCodeUnitsView<? extends T>>
extends AbstractBaseDBTraceCodeUnitsView<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) { protected static int compareForward(TraceCodeUnit a, TraceCodeUnit b) {
return a.getMinAddress().compareTo(b.getMinAddress()); 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) { protected static int compareBackward(TraceCodeUnit a, TraceCodeUnit b) {
return b.getMaxAddress().compareTo(a.getMaxAddress()); return b.getMaxAddress().compareTo(a.getMaxAddress());
} }
protected final Collection<P> parts; 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) { public AbstractComposedDBTraceCodeUnitsView(DBTraceCodeSpace space, Collection<P> parts) {
super(space); super(space);
this.parts = parts; this.parts = parts;

View file

@ -29,6 +29,15 @@ import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.database.DBCachedObjectStore; 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 public abstract class AbstractDBTraceCodeUnit<T extends AbstractDBTraceCodeUnit<T>> extends
AbstractDBTraceAddressSnapRangePropertyMapData<T> implements DBTraceCodeUnitAdapter { 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 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, public AbstractDBTraceCodeUnit(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapTree<T, ?> tree, DBCachedObjectStore<?> store, DBTraceAddressSnapRangePropertyMapTree<T, ?> tree, DBCachedObjectStore<?> store,
DBRecord record) { DBRecord record) {

View file

@ -26,9 +26,19 @@ import ghidra.program.model.lang.Language;
import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTrace;
import ghidra.trace.database.data.DBTraceDataSettingsAdapter.DBTraceDataSettingsSpace; import ghidra.trace.database.data.DBTraceDataSettingsAdapter.DBTraceDataSettingsSpace;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceData;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.LockHold; 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 { public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedDataAdapter {
protected final DBTraceData root; protected final DBTraceData root;
@ -47,6 +57,16 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
protected AbstractDBTraceDataComponent[] componentCache = null; 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, public AbstractDBTraceDataComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
int index, Address address, DataType dataType, int length) { int index, Address address, DataType dataType, int length) {
this.root = root; this.root = root;
@ -173,6 +193,7 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* <p>
* In other words, this includes the symbol name of the root unit; whereas, * In other words, this includes the symbol name of the root unit; whereas,
* {@link #getComponentPathName()} omits it. * {@link #getComponentPathName()} omits it.
*/ */
@ -184,6 +205,7 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* <p>
* In other words, this omits the symbol name of the root unit; whereas, {@link #getPathName()} * In other words, this omits the symbol name of the root unit; whereas, {@link #getPathName()}
* includes it. * includes it.
*/ */

View file

@ -15,9 +15,22 @@
*/ */
package ghidra.trace.database.listing; 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> public abstract class AbstractSingleDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter>
extends AbstractBaseDBTraceCodeUnitsView<T> { extends AbstractBaseDBTraceCodeUnitsView<T> {
/**
* Construct a view
*
* @param space the space, bound to an address space
*/
public AbstractSingleDBTraceCodeUnitsView(DBTraceCodeSpace space) { public AbstractSingleDBTraceCodeUnitsView(DBTraceCodeSpace space) {
super(space); super(space);
} }

View file

@ -22,16 +22,24 @@ import com.google.common.collect.Iterators;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.model.TraceAddressSnapRange; 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 <T> the implementation type of the units contained in the view. Must be a super-type of
* @param <M> * {@link UndefinedDBTraceData}.
* @param <M> the implementation type of the views being composed
*/ */
public abstract class AbstractWithUndefinedDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>> public abstract class AbstractWithUndefinedDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>>
extends AbstractBaseDBTraceCodeUnitsMemoryView<T, M> { extends AbstractBaseDBTraceCodeUnitsMemoryView<T, M> {
/**
* Construct a composite view
*
* @param manager the code manager, from which individual views are retrieved
*/
public AbstractWithUndefinedDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) { public AbstractWithUndefinedDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
super(manager); super(manager);
} }

View file

@ -32,8 +32,7 @@ import db.DBRecord;
import ghidra.lifecycle.Internal; import ghidra.lifecycle.Internal;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.ContextChangeException; import ghidra.program.model.listing.*;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.mem.ByteMemBufferImpl; import ghidra.program.model.mem.ByteMemBufferImpl;
import ghidra.program.model.mem.MemBuffer; import ghidra.program.model.mem.MemBuffer;
import ghidra.program.util.ProgramContextImpl; import ghidra.program.util.ProgramContextImpl;
@ -52,8 +51,7 @@ import ghidra.trace.database.symbol.DBTraceReferenceManager;
import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.database.thread.DBTraceThreadManager;
import ghidra.trace.model.AddressSnap; import ghidra.trace.model.AddressSnap;
import ghidra.trace.model.DefaultAddressSnap; import ghidra.trace.model.DefaultAddressSnap;
import ghidra.trace.model.listing.TraceCodeManager; import ghidra.trace.model.listing.*;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceAddressSpace;
@ -64,8 +62,119 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; 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> { implements TraceCodeManager, DBTraceDelegatingManager<DBTraceCodeSpace> {
public static final String NAME = "Code"; public static final String NAME = "Code";
@ -302,13 +411,13 @@ public class DBTraceCodeManager
@Override @Override
protected DBTraceCodeSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceCodeSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceCodeSpace(this, dbh, space, ent); return new DBTraceCodeSpace(this, dbh, space, ent, null);
} }
@Override @Override
protected DBTraceCodeRegisterSpace createRegisterSpace(AddressSpace space, TraceThread thread, protected DBTraceCodeSpace createRegisterSpace(AddressSpace space, TraceThread thread,
DBTraceSpaceEntry ent) throws VersionException, IOException { DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceCodeRegisterSpace(this, dbh, space, ent, thread); return new DBTraceCodeSpace(this, dbh, space, ent, thread);
} }
@Override @Override
@ -337,19 +446,19 @@ public class DBTraceCodeManager
} }
@Override @Override
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceThread thread, public DBTraceCodeSpace getCodeRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent); return getForRegisterSpace(thread, 0, createIfAbsent);
} }
@Override @Override
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceThread thread, int frameLevel, public DBTraceCodeSpace getCodeRegisterSpace(TraceThread thread, int frameLevel,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, frameLevel, createIfAbsent); return getForRegisterSpace(thread, frameLevel, createIfAbsent);
} }
@Override @Override
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceStackFrame frame, public DBTraceCodeSpace getCodeRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent); return getForRegisterSpace(frame, createIfAbsent);
} }
@ -378,7 +487,7 @@ public class DBTraceCodeManager
for (DBTraceCodeSpace codeSpace : memSpaces.values()) { for (DBTraceCodeSpace codeSpace : memSpaces.values()) {
codeSpace.clearPlatform(Range.all(), codeSpace.all, guest, monitor); 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 // TODO: I don't know any way to get guest instructions into register space
// The mapping manager does (should) not allow guest register addresses // The mapping manager does (should) not allow guest register addresses
// TODO: Test this if I ever get guest data units // 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.space.DBTraceSpaceBased;
import ghidra.trace.database.symbol.DBTraceReferenceManager; import ghidra.trace.database.symbol.DBTraceReferenceManager;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceCodeSpace; import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.ByteArrayUtils; import ghidra.trace.util.ByteArrayUtils;
@ -48,10 +49,19 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; 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 { public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
protected final DBTraceCodeManager manager; protected final DBTraceCodeManager manager;
protected final DBHandle dbh; protected final DBHandle dbh;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final Language baseLanguage; protected final Language baseLanguage;
protected final DBTrace trace; protected final DBTrace trace;
@ -70,11 +80,24 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
protected DBTraceDefinedUnitsView definedUnits; protected DBTraceDefinedUnitsView definedUnits;
protected DBTraceCodeUnitsView codeUnits; 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, public DBTraceCodeSpace(DBTraceCodeManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws VersionException, IOException { DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
this.manager = manager; this.manager = manager;
this.dbh = dbh; this.dbh = dbh;
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock(); this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage(); this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
@ -88,10 +111,10 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
int frameLevel = ent.getFrameLevel(); int frameLevel = ent.getFrameLevel();
instructionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( 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)); DBTraceInstruction.class, (t, s, r) -> new DBTraceInstruction(this, t, s, r));
dataMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( 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)); DBTraceData.class, (t, s, r) -> new DBTraceData(this, t, s, r));
instructions = createInstructionsView(); instructions = createInstructionsView();
@ -102,30 +125,57 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
codeUnits = createCodeUnitsView(); // dep: instructions,definedData,undefinedData codeUnits = createCodeUnitsView(); // dep: instructions,definedData,undefinedData
} }
/**
* A factory method for the instructions view
*/
protected DBTraceInstructionsView createInstructionsView() { protected DBTraceInstructionsView createInstructionsView() {
return new DBTraceInstructionsView(this); return new DBTraceInstructionsView(this);
} }
/**
* A factory method for the defined data view
*/
protected DBTraceDefinedDataView createDefinedDataView() { protected DBTraceDefinedDataView createDefinedDataView() {
return new DBTraceDefinedDataView(this); return new DBTraceDefinedDataView(this);
} }
/**
* A factory method for the defined units view
*/
protected DBTraceDefinedUnitsView createDefinedUnitsView() { protected DBTraceDefinedUnitsView createDefinedUnitsView() {
return new DBTraceDefinedUnitsView(this); return new DBTraceDefinedUnitsView(this);
} }
/**
* A factory method for the undefined data view
*/
protected DBTraceUndefinedDataView createUndefinedDataView() { protected DBTraceUndefinedDataView createUndefinedDataView() {
return new DBTraceUndefinedDataView(this); return new DBTraceUndefinedDataView(this);
} }
/**
* A factory method for the data view
*/
protected DBTraceDataView createDataView() { protected DBTraceDataView createDataView() {
return new DBTraceDataView(this); return new DBTraceDataView(this);
} }
/**
* A factory method for the code units view
*/
protected DBTraceCodeUnitsView createCodeUnitsView() { protected DBTraceCodeUnitsView createCodeUnitsView() {
return new DBTraceCodeUnitsView(this); 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, void clearPlatform(Range<Long> span, AddressRange range, DBTraceGuestPlatform guest,
TaskMonitor monitor) throws CancelledException { TaskMonitor monitor) throws CancelledException {
// Note "makeWay" does not apply here. // Note "makeWay" does not apply here.
@ -170,12 +220,12 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
@Override @Override
public TraceThread getThread() { public TraceThread getThread() {
return null; return thread;
} }
@Override @Override
public int getFrameLevel() { public int getFrameLevel() {
return 0; return frameLevel;
} }
@Override @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, public void bytesChanged(Set<TraceAddressSnapRange> changed, long snap, Address start,
byte[] oldBytes, byte[] newBytes) { byte[] oldBytes, byte[] newBytes) {
AddressSet diffs = ByteArrayUtils.computeDiffsAddressSet(start, oldBytes, 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.exception.NoValueException;
import ghidra.util.prop.PropertyVisitor; 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 { public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferAdapter {
@Override @Override

View file

@ -16,11 +16,21 @@
package ghidra.trace.database.listing; package ghidra.trace.database.listing;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceCodeUnitsView; import ghidra.trace.model.listing.TraceCodeUnitsView;
/**
* The implementation of {@link TraceCodeManager#codeUnits()}
*/
public class DBTraceCodeUnitsMemoryView extends public class DBTraceCodeUnitsMemoryView extends
AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceCodeUnitAdapter, DBTraceCodeUnitsView> AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceCodeUnitAdapter, DBTraceCodeUnitsView>
implements TraceCodeUnitsView { implements TraceCodeUnitsView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) { public DBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
super(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 com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceCodeUnitsView; import ghidra.trace.model.listing.TraceCodeUnitsView;
/**
* The implementation of {@link TraceCodeSpace#codeUnits()}
*/
public class DBTraceCodeUnitsView extends public class DBTraceCodeUnitsView extends
AbstractComposedDBTraceCodeUnitsView<DBTraceCodeUnitAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceCodeUnitAdapter>> AbstractComposedDBTraceCodeUnitsView<DBTraceCodeUnitAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceCodeUnitAdapter>>
implements TraceCodeUnitsView { implements TraceCodeUnitsView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceCodeUnitsView(DBTraceCodeSpace space) { public DBTraceCodeUnitsView(DBTraceCodeSpace space) {
super(space, List.of(space.instructions, space.definedData, space.undefinedData)); 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.address.*;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Listing;
import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.listing.DBTraceCommentAdapter.DBTraceCommentEntry; import ghidra.trace.database.listing.DBTraceCommentAdapter.DBTraceCommentEntry;
@ -46,12 +47,18 @@ import ghidra.util.database.annot.*;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/**
* A property map for storing code unit comments
*/
public class DBTraceCommentAdapter public class DBTraceCommentAdapter
extends DBTraceAddressSnapRangePropertyMap<DBTraceCommentEntry, DBTraceCommentEntry> { extends DBTraceAddressSnapRangePropertyMap<DBTraceCommentEntry, DBTraceCommentEntry> {
protected static final String[] EMPTY_STRING_ARRAY = new String[] {}; protected static final String[] EMPTY_STRING_ARRAY = new String[] {};
protected static final int MIN_COMMENT_TYPE = CodeUnit.EOL_COMMENT; protected static final int MIN_COMMENT_TYPE = CodeUnit.EOL_COMMENT;
protected static final int MAX_COMMENT_TYPE = CodeUnit.REPEATABLE_COMMENT; protected static final int MAX_COMMENT_TYPE = CodeUnit.REPEATABLE_COMMENT;
/**
* A comment entry
*/
@DBAnnotatedObjectInfo(version = 0) @DBAnnotatedObjectInfo(version = 0)
public static class DBTraceCommentEntry public static class DBTraceCommentEntry
extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceCommentEntry> { extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceCommentEntry> {
@ -99,6 +106,9 @@ public class DBTraceCommentAdapter
} }
} }
/**
* Construct the adapter
*/
public DBTraceCommentAdapter(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock, public DBTraceCommentAdapter(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
TaskMonitor monitor, Language baseLanguage, DBTrace trace, TaskMonitor monitor, Language baseLanguage, DBTrace trace,
DBTraceThreadManager threadManager) throws IOException, VersionException { DBTraceThreadManager threadManager) throws IOException, VersionException {
@ -106,10 +116,27 @@ public class DBTraceCommentAdapter
DBTraceCommentEntry.class, DBTraceCommentEntry::new); 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) { protected void makeWay(DBTraceCommentEntry entry, Range<Long> span) {
DBTraceUtils.makeWay(entry, span, (e, s) -> e.setLifespan(s), e -> deleteData(e)); 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) { public void setComment(Range<Long> lifespan, Address address, int commentType, String comment) {
if (commentType < MIN_COMMENT_TYPE || commentType > MAX_COMMENT_TYPE) { if (commentType < MIN_COMMENT_TYPE || commentType > MAX_COMMENT_TYPE) {
throw new IllegalArgumentException("commentType"); throw new IllegalArgumentException("commentType");
@ -138,14 +165,34 @@ public class DBTraceCommentAdapter
oldValue, comment)); 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) { public static String commentFromArray(String[] comment) {
return comment == null || comment.length == 0 ? null : StringUtils.join(comment, '\n'); 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) { public static String[] arrayFromComment(String comment) {
return comment == null || comment.length() == 0 ? EMPTY_STRING_ARRAY : comment.split("\n"); 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) { public String getComment(long snap, Address address, int commentType) {
try (LockHold hold = LockHold.lock(lock.readLock())) { try (LockHold hold = LockHold.lock(lock.readLock())) {
for (DBTraceCommentEntry entry : reduce( 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 span the lifespan fo the box
* @param range * @param range the address range of the box
* @param commentType a comment type to clear, or {@link CodeUnit#NO_COMMENT} to clear all. * @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) { 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.address.AddressSpace;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.data.DBTraceDataSettingsOperations; import ghidra.trace.database.data.DBTraceDataSettingsOperations;
import ghidra.trace.database.guest.InternalTracePlatform; import ghidra.trace.database.guest.InternalTracePlatform;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceData;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.database.DBCachedObjectStore; import ghidra.util.database.DBCachedObjectStore;
import ghidra.util.database.DBObjectColumn; import ghidra.util.database.DBObjectColumn;
import ghidra.util.database.annot.*; import ghidra.util.database.annot.*;
/**
* The implementation for a defined {@link TraceData} for {@link DBTrace}
*/
@DBAnnotatedObjectInfo(version = 0) @DBAnnotatedObjectInfo(version = 0)
public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData> public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
implements DBTraceDefinedDataAdapter { implements DBTraceDefinedDataAdapter {
@ -63,6 +68,14 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
protected AbstractDBTraceDataComponent[] componentCache = null; 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, public DBTraceData(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapTree<DBTraceData, ?> tree, DBTraceAddressSnapRangePropertyMapTree<DBTraceData, ?> tree,
DBCachedObjectStore<?> store, DBRecord record) { DBCachedObjectStore<?> store, DBRecord record) {
@ -102,6 +115,12 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
return this; return this;
} }
/**
* Set the fields of this record
*
* @param platform the platform
* @param dataType the data type
*/
protected void set(InternalTracePlatform platform, DataType dataType) { protected void set(InternalTracePlatform platform, DataType dataType) {
this.platformKey = platform.getIntKey(); this.platformKey = platform.getIntKey();
this.dataTypeID = space.dataTypeManager.getResolvedID(dataType); this.dataTypeID = space.dataTypeManager.getResolvedID(dataType);
@ -115,6 +134,11 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
this.baseDataType = getBaseDataType(this.dataType); 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() { protected int getDataTypeLength() {
if (baseDataType instanceof Pointer) { if (baseDataType instanceof Pointer) {
// TODO: Also need to know where this address maps into the other language's spaces.... // 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 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) { public static DataType getBaseDataType(DataType dt) {
if (dt instanceof TypeDef) { if (dt instanceof TypeDef) {
return ((TypeDef) dt).getBaseDataType(); return ((TypeDef) dt).getBaseDataType();

View file

@ -31,6 +31,13 @@ import ghidra.trace.model.symbol.TraceReference;
import ghidra.trace.util.*; import ghidra.trace.util.*;
import ghidra.util.LockHold; 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, public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterMinimal,
DataAdapterFromDataType, DataAdapterFromSettings, TraceData { DataAdapterFromDataType, DataAdapterFromSettings, TraceData {
static String[] EMPTY_STRING_ARRAY = new String[] {}; 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); DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent);
@Override @Override

View file

@ -17,11 +17,26 @@ package ghidra.trace.database.listing;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.trace.database.DBTrace;
import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceAddressSpace;
/**
* The implementation of an array-element data component in a {@link DBTrace}
*/
public class DBTraceDataArrayElementComponent extends AbstractDBTraceDataComponent { 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, public DBTraceDataArrayElementComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
int index, Address address, DataType dataType, int length) { int index, Address address, DataType dataType, int length) {
super(root, parent, index, address, dataType, 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.address.*;
import ghidra.program.model.data.DataTypeComponent; import ghidra.program.model.data.DataTypeComponent;
import ghidra.trace.database.DBTrace;
import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceAddressSpace;
/**
* The implementation of a field data component in a {@link DBTrace}
*/
public class DBTraceDataCompositeFieldComponent extends AbstractDBTraceDataComponent { public class DBTraceDataCompositeFieldComponent extends AbstractDBTraceDataComponent {
protected final DataTypeComponent dtc; 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, public DBTraceDataCompositeFieldComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
Address address, DataTypeComponent dtc) { Address address, DataTypeComponent dtc) {
super(root, parent, dtc.getOrdinal(), address, dtc.getDataType(), dtc.getLength()); super(root, parent, dtc.getOrdinal(), address, dtc.getDataType(), dtc.getLength());

View file

@ -15,11 +15,21 @@
*/ */
package ghidra.trace.database.listing; package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceDataView; import ghidra.trace.model.listing.TraceDataView;
/**
* The implementation of {@link TraceCodeManager#data()}
*/
public class DBTraceDataMemoryView public class DBTraceDataMemoryView
extends AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceDataAdapter, DBTraceDataView> extends AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceDataAdapter, DBTraceDataView>
implements TraceDataView { implements TraceDataView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceDataMemoryView(DBTraceCodeManager manager) { public DBTraceDataMemoryView(DBTraceCodeManager manager) {
super(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 com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceDataView; import ghidra.trace.model.listing.TraceDataView;
/**
* The implementation of {@link TraceCodeSpace#data()}
*/
public class DBTraceDataView extends public class DBTraceDataView extends
AbstractComposedDBTraceCodeUnitsView<DBTraceDataAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceDataAdapter>> AbstractComposedDBTraceCodeUnitsView<DBTraceDataAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceDataAdapter>>
implements TraceDataView { implements TraceDataView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceDataView(DBTraceCodeSpace space) { public DBTraceDataView(DBTraceCodeSpace space) {
super(space, List.of(space.definedData, space.undefinedData)); 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.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Data;
import ghidra.trace.model.listing.TraceData;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.Msg; 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 { public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
@Override @Override
@ -121,7 +129,7 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
default DBTraceDefinedDataAdapter getComponentAt(int offset) { default DBTraceDefinedDataAdapter getComponentAt(int offset) {
return getComponentContaining(offset); return getComponentContaining(offset);
} }
@Override @Override
default DBTraceDefinedDataAdapter getComponentContaining(int offset) { default DBTraceDefinedDataAdapter getComponentContaining(int offset) {
// We may write to the cache // 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.address.AddressRange;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceDefinedDataView; import ghidra.trace.model.listing.TraceDefinedDataView;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeManager#definedData()}
*/
public class DBTraceDefinedDataMemoryView public class DBTraceDefinedDataMemoryView
extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceData, DBTraceDefinedDataView> extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceData, DBTraceDefinedDataView>
implements TraceDefinedDataView { implements TraceDefinedDataView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceDefinedDataMemoryView(DBTraceCodeManager manager) { public DBTraceDefinedDataMemoryView(DBTraceCodeManager manager) {
super(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.TraceCodeChangeType;
import ghidra.trace.model.Trace.TraceCompositeDataChangeType; import ghidra.trace.model.Trace.TraceCompositeDataChangeType;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceDefinedDataView; import ghidra.trace.model.listing.TraceDefinedDataView;
import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceChangeRecord;
import ghidra.util.LockHold; import ghidra.util.LockHold;
/**
* The implementation of {@link TraceCodeSpace#definedData()}
*/
public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceData> public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceData>
implements TraceDefinedDataView { implements TraceDefinedDataView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceDefinedDataView(DBTraceCodeSpace space) { public DBTraceDefinedDataView(DBTraceCodeSpace space) {
super(space, space.dataMapSpace); super(space, space.dataMapSpace);
} }
@ -43,6 +52,15 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
return create(lifespan, address, dataType, dataType.getLength()); 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) { protected boolean isFunctionDefinition(DataType dt) {
if (dt instanceof FunctionDefinition) { if (dt instanceof FunctionDefinition) {
return true; return true;

View file

@ -18,13 +18,23 @@ package ghidra.trace.database.listing;
import com.google.common.collect.Range; import com.google.common.collect.Range;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceDefinedUnitsView; import ghidra.trace.model.listing.TraceDefinedUnitsView;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeManager#definedUnits()}
*/
public class DBTraceDefinedUnitsMemoryView extends public class DBTraceDefinedUnitsMemoryView extends
AbstractBaseDBTraceCodeUnitsMemoryView<AbstractDBTraceCodeUnit<?>, DBTraceDefinedUnitsView> AbstractBaseDBTraceCodeUnitsMemoryView<AbstractDBTraceCodeUnit<?>, DBTraceDefinedUnitsView>
implements TraceDefinedUnitsView { implements TraceDefinedUnitsView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceDefinedUnitsMemoryView(DBTraceCodeManager manager) { public DBTraceDefinedUnitsMemoryView(DBTraceCodeManager manager) {
super(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.program.model.address.AddressRange;
import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceDefinedUnitsView; import ghidra.trace.model.listing.TraceDefinedUnitsView;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeSpace#data()}
*/
public class DBTraceDefinedUnitsView extends public class DBTraceDefinedUnitsView extends
AbstractComposedDBTraceCodeUnitsView<AbstractDBTraceCodeUnit<?>, AbstractBaseDBTraceDefinedUnitsView<? extends AbstractDBTraceCodeUnit<?>>> AbstractComposedDBTraceCodeUnitsView<AbstractDBTraceCodeUnit<?>, AbstractBaseDBTraceDefinedUnitsView<? extends AbstractDBTraceCodeUnit<?>>>
implements TraceDefinedUnitsView { implements TraceDefinedUnitsView {
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceDefinedUnitsView(DBTraceCodeSpace space) { public DBTraceDefinedUnitsView(DBTraceCodeSpace space) {
super(space, List.of(space.instructions, space.definedData)); 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.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.context.DBTraceRegisterContextManager; import ghidra.trace.database.context.DBTraceRegisterContextManager;
import ghidra.trace.database.context.DBTraceRegisterContextSpace; import ghidra.trace.database.context.DBTraceRegisterContextSpace;
@ -48,6 +49,9 @@ import ghidra.util.database.DBCachedObjectStore;
import ghidra.util.database.DBObjectColumn; import ghidra.util.database.DBObjectColumn;
import ghidra.util.database.annot.*; import ghidra.util.database.annot.*;
/**
* The implementation of {@link TraceInstruction} for {@link DBTrace}
*/
@DBAnnotatedObjectInfo(version = 0) @DBAnnotatedObjectInfo(version = 0)
public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstruction> implements public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstruction> implements
TraceInstruction, InstructionAdapterFromPrototype, InstructionContext { TraceInstruction, InstructionAdapterFromPrototype, InstructionContext {
@ -76,6 +80,9 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0); return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0);
} }
/**
* A context for guest instructions that maps addresses appropriately
*/
protected class GuestInstructionContext implements InstructionContext { protected class GuestInstructionContext implements InstructionContext {
@Override @Override
public Address getAddress() { public Address getAddress() {
@ -121,12 +128,25 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
protected InternalTracePlatform platform; protected InternalTracePlatform platform;
protected InstructionContext instructionContext; 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, public DBTraceInstruction(DBTraceCodeSpace space,
DBTraceAddressSnapRangePropertyMapTree<DBTraceInstruction, ?> tree, DBTraceAddressSnapRangePropertyMapTree<DBTraceInstruction, ?> tree,
DBCachedObjectStore<?> store, DBRecord record) { DBCachedObjectStore<?> store, DBRecord record) {
super(space, tree, store, 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) { protected void doSetPlatformMapping(final InternalTracePlatform platform) {
this.platform = platform; this.platform = platform;
if (platform.isHost()) { 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, protected void set(InternalTracePlatform platform, InstructionPrototype prototype,
ProcessorContextView context) { ProcessorContextView context) {
this.platformKey = platform.getIntKey(); this.platformKey = platform.getIntKey();

View file

@ -25,14 +25,24 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceInstructionsView; import ghidra.trace.model.listing.TraceInstructionsView;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeManager#definedData()}
*/
public class DBTraceInstructionsMemoryView public class DBTraceInstructionsMemoryView
extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceInstruction, DBTraceInstructionsView> extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceInstruction, DBTraceInstructionsView>
implements TraceInstructionsView { implements TraceInstructionsView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceInstructionsMemoryView(DBTraceCodeManager manager) { public DBTraceInstructionsMemoryView(DBTraceCodeManager manager) {
super(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.Trace.TraceCodeChangeType;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceInstruction; import ghidra.trace.model.listing.*;
import ghidra.trace.model.listing.TraceInstructionsView;
import ghidra.trace.util.OverlappingObjectIterator; import ghidra.trace.util.OverlappingObjectIterator;
import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceChangeRecord;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/**
* The implementation of {@link TraceCodeSpace#instructions()}
*/
public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceInstruction> public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceInstruction>
implements TraceInstructionsView { implements TraceInstructionsView {
@ -50,6 +52,9 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
return rep != null ? rep : cur; return rep != null ? rep : cur;
} }
/**
* A mechanism for adding a block of instructions
*/
protected class InstructionBlockAdder { protected class InstructionBlockAdder {
private final Set<Address> skipDelaySlots; private final Set<Address> skipDelaySlots;
private final Range<Long> lifespan; private final Range<Long> lifespan;
@ -61,6 +66,20 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
protected int count = 0; 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, private InstructionBlockAdder(Set<Address> skipDelaySlots, Range<Long> lifespan,
InternalTracePlatform platform, InstructionBlock block, Address errorAddress, InternalTracePlatform platform, InstructionBlock block, Address errorAddress,
InstructionError conflict, CodeUnit conflictCodeUnit) { InstructionError conflict, CodeUnit conflictCodeUnit) {
@ -73,6 +92,14 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
this.conflictCodeUnit = conflictCodeUnit; 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, protected Instruction doCreateInstruction(Address address,
InstructionPrototype prototype, Instruction protoInstr) { InstructionPrototype prototype, Instruction protoInstr) {
try { try {
@ -97,12 +124,14 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
/** /**
* Adds the instructions and returns the last instruction added * 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 * If it encounters a delay-slotted instruction, it will recurse on the group, iterating in
* reverse order. * reverse order.
* *
* @param instructions * @param instructions the instructions to add
* @param areDelaySlots * @param areDelaySlots true if the instructions are already reversed from being
* @return * delay-slotted
* @return the last instruction added
*/ */
protected Instruction doAddInstructions(Iterator<Instruction> it, boolean areDelaySlots) { protected Instruction doAddInstructions(Iterator<Instruction> it, boolean areDelaySlots) {
Instruction lastInstruction = null; Instruction lastInstruction = null;
@ -158,13 +187,38 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
} }
return lastInstruction; 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) { public DBTraceInstructionsView(DBTraceCodeSpace space) {
super(space, space.instructionMapSpace); 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) { ProcessorContextView context) {
Register contextReg = language.getContextBaseRegister(); Register contextReg = language.getContextBaseRegister();
if (contextReg == null || contextReg == Register.NO_CONTEXT) { if (contextReg == null || contextReg == Register.NO_CONTEXT) {
@ -185,6 +239,19 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
ctxSpace.setValue(language, newValue, tasr.getLifespan(), tasr.getRange()); 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, protected DBTraceInstruction doCreate(Range<Long> lifespan, Address address,
InternalTracePlatform platform, InstructionPrototype prototype, InternalTracePlatform platform, InstructionPrototype prototype,
ProcessorContextView context) ProcessorContextView context)
@ -221,7 +288,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
throw new CodeUnitInsertionException("Code units cannot overlap"); throw new CodeUnitInsertionException("Code units cannot overlap");
} }
doSetContexts(tasr, prototype.getLanguage(), context); doSetContext(tasr, prototype.getLanguage(), context);
DBTraceInstruction created = space.instructionMapSpace.put(tasr, null); DBTraceInstruction created = space.instructionMapSpace.put(tasr, null);
created.set(platform, prototype, context); 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, protected OverlappingObjectIterator<Instruction, CodeUnit> startCheckingBlock(long startSnap,
InstructionBlock block) { InstructionBlock block) {
Address startAddress = block.getStartAddress(); Address startAddress = block.getStartAddress();
@ -267,6 +341,19 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
OverlappingObjectIterator.CODE_UNIT, existing, OverlappingObjectIterator.CODE_UNIT); 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, protected InstructionBlockAdder startAddingBlock(Range<Long> lifespan,
Set<Address> skipDelaySlots, InternalTracePlatform platform, InstructionBlock block) { Set<Address> skipDelaySlots, InternalTracePlatform platform, InstructionBlock block) {
InstructionError conflict = block.getInstructionConflict(); InstructionError conflict = block.getInstructionConflict();
@ -292,6 +379,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
/** /**
* Checks the intended locations for conflicts with existing units. * Checks the intended locations for conflicts with existing units.
* *
* <p>
* This also clears locations where delay slots will be replacing non-delay slots. * 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 * {@code skipDelaySlots} will be populated with any existing delay slot locations which should
* not be overwritten * not be overwritten
@ -400,7 +488,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
if (adder == null) { if (adder == null) {
continue; continue;
} }
Instruction lastInstruction = adder.doAddInstructions(block.iterator(), false); Instruction lastInstruction = adder.doAddInstructions();
block.setInstructionsAddedCount(adder.count); block.setInstructionsAddedCount(adder.count);
if (lastInstruction != null) { if (lastInstruction != null) {
Address maxAddress = DBTraceCodeManager.instructionMax(lastInstruction, true); Address maxAddress = DBTraceCodeManager.instructionMax(lastInstruction, true);

View file

@ -15,11 +15,21 @@
*/ */
package ghidra.trace.database.listing; package ghidra.trace.database.listing;
import ghidra.trace.model.listing.TraceCodeManager;
import ghidra.trace.model.listing.TraceUndefinedDataView; import ghidra.trace.model.listing.TraceUndefinedDataView;
/**
* The implementation of {@link TraceCodeManager#undefinedData()}
*/
public class DBTraceUndefinedDataMemoryView extends public class DBTraceUndefinedDataMemoryView extends
AbstractWithUndefinedDBTraceCodeUnitsMemoryView<UndefinedDBTraceData, DBTraceUndefinedDataView> AbstractWithUndefinedDBTraceCodeUnitsMemoryView<UndefinedDBTraceData, DBTraceUndefinedDataView>
implements TraceUndefinedDataView { implements TraceUndefinedDataView {
/**
* Construct the view
*
* @param manager the manager
*/
public DBTraceUndefinedDataMemoryView(DBTraceCodeManager manager) { public DBTraceUndefinedDataMemoryView(DBTraceCodeManager manager) {
super(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.program.model.address.*;
import ghidra.trace.database.DBTraceUtils; import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.listing.TraceCodeSpace;
import ghidra.trace.model.listing.TraceUndefinedDataView; import ghidra.trace.model.listing.TraceUndefinedDataView;
import ghidra.util.*; import ghidra.util.*;
/**
* The implementation of {@link TraceCodeSpace#undefinedData()}
*/
public class DBTraceUndefinedDataView extends public class DBTraceUndefinedDataView extends
AbstractSingleDBTraceCodeUnitsView<UndefinedDBTraceData> implements TraceUndefinedDataView { AbstractSingleDBTraceCodeUnitsView<UndefinedDBTraceData> implements TraceUndefinedDataView {
@ -42,6 +46,11 @@ public class DBTraceUndefinedDataView extends
.build() .build()
.asMap(); .asMap();
/**
* Construct the view
*
* @param space the space, bound to an address space
*/
public DBTraceUndefinedDataView(DBTraceCodeSpace space) { public DBTraceUndefinedDataView(DBTraceCodeSpace space) {
super(space); super(space);
this.manager = space.manager; this.manager = space.manager;
@ -51,6 +60,13 @@ public class DBTraceUndefinedDataView extends
// Nothing // 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) { protected UndefinedDBTraceData doCreateUnit(long snap, Address address) {
space.assertInSpace(address); space.assertInSpace(address);
return manager.doCreateUndefinedUnit(snap, address, space.getThread(), return manager.doCreateUndefinedUnit(snap, address, space.getThread(),
@ -62,6 +78,16 @@ public class DBTraceUndefinedDataView extends
return 0; 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) { protected AddressSetView doGetAddressSetView(long snap) {
return cache.computeIfAbsent(snap, return cache.computeIfAbsent(snap,
t -> new CachedAddressSetView(new DifferenceAddressSetView(new AddressSet(space.all), t -> new CachedAddressSetView(new DifferenceAddressSetView(new AddressSet(space.all),
@ -142,6 +168,9 @@ public class DBTraceUndefinedDataView extends
doGetAddressSetView(snap)); doGetAddressSetView(snap));
} }
/**
* Invalidate the cache of generated undefined units
*/
public void invalidateCache() { public void invalidateCache() {
cache.clear(); cache.clear();
} }

View file

@ -38,6 +38,13 @@ import ghidra.trace.model.listing.TraceData;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace; 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 { public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey {
protected final DBTrace trace; protected final DBTrace trace;
protected final long snap; protected final long snap;
@ -46,6 +53,15 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey
protected final TraceThread thread; protected final TraceThread thread;
protected final int frameLevel; 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, public UndefinedDBTraceData(DBTrace trace, long snap, Address address, TraceThread thread,
int frameLevel) { int frameLevel) {
this.trace = trace; this.trace = trace;

View file

@ -126,14 +126,14 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
DBTraceSpaceEntry ent) throws VersionException, IOException { DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTracePropertyMapSpace( return new DBTracePropertyMapSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, dataType, dataFactory); lock, space, null, 0, dataType, dataFactory);
} }
@Override @Override
protected DBTracePropertyMapRegisterSpace createRegisterSpace( protected DBTracePropertyMapSpace createRegisterSpace(
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent) AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTracePropertyMapRegisterSpace( return new DBTracePropertyMapSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory); lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
} }
@ -145,9 +145,9 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
} }
@Override @Override
public TracePropertyMapRegisterSpace<T> getPropertyMapRegisterSpace(TraceThread thread, public TracePropertyMapSpace<T> getPropertyMapRegisterSpace(TraceThread thread,
int frameLevel, boolean createIfAbsent) { int frameLevel, boolean createIfAbsent) {
return (DBTracePropertyMapRegisterSpace) getForRegisterSpace(thread, frameLevel, return (DBTracePropertyMapSpace) getForRegisterSpace(thread, frameLevel,
createIfAbsent); createIfAbsent);
} }
@ -161,96 +161,11 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
implements TracePropertyMapSpace<T> { implements TracePropertyMapSpace<T> {
public DBTracePropertyMapSpace(String tableName, DBCachedObjectStoreFactory storeFactory, public DBTracePropertyMapSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
ReadWriteLock lock, AddressSpace space, Class<DR> dataType, ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory) Class<DR> dataType,
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,
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory) DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
throws VersionException, IOException { throws VersionException, IOException {
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory); super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
// TODO Auto-generated constructor stub
} }
@Override @Override

View file

@ -48,8 +48,7 @@ import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAddressSnapRangePropertyMapData<T>> public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAddressSnapRangePropertyMapData<T>>
extends extends AbstractDBTraceSpaceBasedManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>>
AbstractDBTraceSpaceBasedManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>, DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR>>
implements TraceAddressSnapRangePropertyMap<T>, implements TraceAddressSnapRangePropertyMap<T>,
DBTraceDelegatingManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>> { DBTraceDelegatingManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>> {
@ -83,26 +82,26 @@ public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAdd
DBTraceSpaceEntry ent) throws VersionException, IOException { DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceAddressSnapRangePropertyMapSpace<>( return new DBTraceAddressSnapRangePropertyMapSpace<>(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, dataType, dataFactory); lock, space, null, ent.getFrameLevel(), dataType, dataFactory);
} }
@Override @Override
protected DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> createRegisterSpace( protected DBTraceAddressSnapRangePropertyMapSpace<T, DR> createRegisterSpace(
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent) AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceAddressSnapRangePropertyMapRegisterSpace<>( return new DBTraceAddressSnapRangePropertyMapSpace<>(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory); lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
} }
@Override @Override
public DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> getRegisterSpace( public DBTraceAddressSnapRangePropertyMapSpace<T, DR> getRegisterSpace(
TraceThread thread, boolean createIfAbsent) { TraceThread thread, boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent); return getForRegisterSpace(thread, 0, createIfAbsent);
} }
@Override @Override
public DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> getRegisterSpace( public DBTraceAddressSnapRangePropertyMapSpace<T, DR> getRegisterSpace(
TraceStackFrame frame, boolean createIfAbsent) { TraceStackFrame frame, boolean createIfAbsent) {
return getForRegisterSpace(frame, 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> { TraceAddressSnapRangePropertyMapSpace<T> {
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final DBTraceAddressSnapRangePropertyMapTree<T, DR> tree; protected final DBTraceAddressSnapRangePropertyMapTree<T, DR> tree;
protected final AbstractConstraintsTreeSpatialMap<TraceAddressSnapRange, DR, TraceAddressSnapRange, T, TraceAddressSnapRangeQuery> map; protected final AbstractConstraintsTreeSpatialMap<TraceAddressSnapRange, DR, TraceAddressSnapRange, T, TraceAddressSnapRangeQuery> map;
@ -51,9 +53,12 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
public DBTraceAddressSnapRangePropertyMapSpace(String tableName, public DBTraceAddressSnapRangePropertyMapSpace(String tableName,
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space, 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 { throws VersionException, IOException {
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = frameLevel;
this.lock = lock; this.lock = lock;
this.tree = new DBTraceAddressSnapRangePropertyMapTree<>(storeFactory, tableName, this, this.tree = new DBTraceAddressSnapRangePropertyMapTree<>(storeFactory, tableName, this,
@ -70,12 +75,12 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
@Override @Override
public TraceThread getThread() { public TraceThread getThread() {
return null; return thread;
} }
@Override @Override
public int getFrameLevel() { public int getFrameLevel() {
return 0; return frameLevel;
} }
public <K> DBCachedObjectIndex<K, DR> getUserIndex(Class<K> fieldClass, DBObjectColumn column) { 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.exception.*;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceMemoryManager public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace>
extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace, DBTraceMemoryRegisterSpace>
implements TraceMemoryManager, DBTraceDelegatingManager<DBTraceMemorySpace> { implements TraceMemoryManager, DBTraceDelegatingManager<DBTraceMemorySpace> {
protected static final String NAME = "Memory"; protected static final String NAME = "Memory";
@ -80,13 +79,13 @@ public class DBTraceMemoryManager
@Override @Override
protected DBTraceMemorySpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceMemorySpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceMemorySpace(this, dbh, space, ent); return new DBTraceMemorySpace(this, dbh, space, ent, null);
} }
@Override @Override
protected DBTraceMemoryRegisterSpace createRegisterSpace(AddressSpace space, protected DBTraceMemorySpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceMemoryRegisterSpace(this, dbh, space, ent, thread); return new DBTraceMemorySpace(this, dbh, space, ent, thread);
} }
@Override @Override
@ -110,19 +109,19 @@ public class DBTraceMemoryManager
} }
@Override @Override
public DBTraceMemoryRegisterSpace getMemoryRegisterSpace(TraceThread thread, public DBTraceMemorySpace getMemoryRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent); return getForRegisterSpace(thread, 0, createIfAbsent);
} }
@Override @Override
public TraceMemoryRegisterSpace getMemoryRegisterSpace(TraceThread thread, int frame, public DBTraceMemorySpace getMemoryRegisterSpace(TraceThread thread, int frame,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, frame, createIfAbsent); return getForRegisterSpace(thread, frame, createIfAbsent);
} }
@Override @Override
public DBTraceMemoryRegisterSpace getMemoryRegisterSpace(TraceStackFrame frame, public DBTraceMemorySpace getMemoryRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(frame, 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 DBTraceMemoryManager manager;
protected final DBHandle dbh; protected final DBHandle dbh;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final DBTrace trace; protected final DBTrace trace;
@ -96,10 +98,12 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
protected final DefaultTraceTimeViewport viewport; protected final DefaultTraceTimeViewport viewport;
public DBTraceMemorySpace(DBTraceMemoryManager manager, DBHandle dbh, AddressSpace space, public DBTraceMemorySpace(DBTraceMemoryManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws IOException, VersionException { DBTraceSpaceEntry ent, TraceThread thread) throws IOException, VersionException {
this.manager = manager; this.manager = manager;
this.dbh = dbh; this.dbh = dbh;
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock(); this.lock = manager.getLock();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
@ -108,15 +112,16 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
long threadKey = ent.getThreadKey(); long threadKey = ent.getThreadKey();
int frameLevel = ent.getFrameLevel(); int frameLevel = ent.getFrameLevel();
this.regionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( this.regionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space, DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space, thread,
DBTraceMemoryRegion.class, (t, s, r) -> new DBTraceMemoryRegion(this, t, s, r)); frameLevel, DBTraceMemoryRegion.class,
(t, s, r) -> new DBTraceMemoryRegion(this, t, s, r));
this.regionView = Collections.unmodifiableCollection(regionMapSpace.values()); this.regionView = Collections.unmodifiableCollection(regionMapSpace.values());
this.regionsByPath = this.regionsByPath =
regionMapSpace.getUserIndex(String.class, DBTraceMemoryRegion.PATH_COLUMN); regionMapSpace.getUserIndex(String.class, DBTraceMemoryRegion.PATH_COLUMN);
this.stateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( this.stateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceMemoryStateEntry.tableName(space, threadKey, frameLevel), factory, lock, space, DBTraceMemoryStateEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new); thread, frameLevel, DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new);
this.bufferStore = factory.getOrCreateCachedStore( this.bufferStore = factory.getOrCreateCachedStore(
DBTraceMemoryBufferEntry.tableName(space, threadKey, frameLevel), DBTraceMemoryBufferEntry.tableName(space, threadKey, frameLevel),
@ -257,6 +262,9 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
@Override @Override
public DBTraceCodeSpace getCodeSpace(boolean createIfAbsent) { public DBTraceCodeSpace getCodeSpace(boolean createIfAbsent) {
if (space.isRegisterSpace()) {
return trace.getCodeManager().getCodeRegisterSpace(thread, frameLevel, createIfAbsent);
}
return trace.getCodeManager().getCodeSpace(space, createIfAbsent); return trace.getCodeManager().getCodeSpace(space, createIfAbsent);
} }
@ -405,7 +413,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
@Override @Override
public Entry<TraceAddressSnapRange, TraceMemoryState> getViewMostRecentStateEntry(long snap, public Entry<TraceAddressSnapRange, TraceMemoryState> getViewMostRecentStateEntry(long snap,
Address address) { Address address) {
for (Range<Long> span: viewport.getOrderedSpans(snap)) { for (Range<Long> span : viewport.getOrderedSpans(snap)) {
Entry<TraceAddressSnapRange, TraceMemoryState> entry = Entry<TraceAddressSnapRange, TraceMemoryState> entry =
stateMapSpace.reduce(TraceAddressSnapRangeQuery.mostRecent(address, span)) stateMapSpace.reduce(TraceAddressSnapRangeQuery.mostRecent(address, span))
.firstEntry(); .firstEntry();

View file

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

View file

@ -58,13 +58,13 @@ public class DBTraceModuleSpace implements TraceModuleSpace, DBTraceSpaceBased {
this.trace = manager.getTrace(); this.trace = manager.getTrace();
this.moduleMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( 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)); DBTraceModule.class, (t, s, r) -> new DBTraceModule(this, t, s, r));
this.modulesByPath = moduleMapSpace.getUserIndex(String.class, DBTraceModule.PATH_COLUMN); this.modulesByPath = moduleMapSpace.getUserIndex(String.class, DBTraceModule.PATH_COLUMN);
this.moduleView = Collections.unmodifiableCollection(moduleMapSpace.values()); this.moduleView = Collections.unmodifiableCollection(moduleMapSpace.values());
this.sectionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( 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)); DBTraceSection.class, (t, s, r) -> new DBTraceSection(this, t, s, r));
this.sectionsByModuleKey = this.sectionsByModuleKey =
sectionMapSpace.getUserIndex(long.class, DBTraceSection.MODULE_COLUMN); 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.ChangeManager;
import ghidra.program.util.ProgramChangeRecord; import ghidra.program.util.ProgramChangeRecord;
import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTrace;
import ghidra.trace.database.listing.*; import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace; import ghidra.trace.database.listing.DBTraceDefinedUnitsView;
import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.database.symbol.DBTraceFunctionSymbolView; import ghidra.trace.database.symbol.DBTraceFunctionSymbolView;
import ghidra.trace.model.Trace.*; import ghidra.trace.model.Trace.*;
@ -990,12 +990,12 @@ public class DBTraceProgramView implements TraceProgramView {
return regView; return regView;
} }
assert trace.getThreadManager().getAllThreads().contains(thread); assert trace.getThreadManager().getAllThreads().contains(thread);
DBTraceCodeRegisterSpace codeSpace = DBTraceCodeSpace codeSpace =
trace.getCodeManager().getCodeRegisterSpace(thread, createIfAbsent); trace.getCodeManager().getCodeRegisterSpace(thread, createIfAbsent);
if (codeSpace == null) { if (codeSpace == null) {
return null; return null;
} }
DBTraceMemoryRegisterSpace memorySpace = DBTraceMemorySpace memorySpace =
trace.getMemoryManager().getMemoryRegisterSpace(thread, createIfAbsent); trace.getMemoryManager().getMemoryRegisterSpace(thread, createIfAbsent);
if (memorySpace == null) { if (memorySpace == null) {
return null; return null;

View file

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

View file

@ -17,14 +17,14 @@ package ghidra.trace.database.program;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace; import ghidra.trace.database.memory.DBTraceMemorySpace;
public class DBTraceProgramViewRegisterMemory extends AbstractDBTraceProgramViewMemory { public class DBTraceProgramViewRegisterMemory extends AbstractDBTraceProgramViewMemory {
protected final DBTraceMemoryRegisterSpace space; protected final DBTraceMemorySpace space;
protected final DBTraceProgramViewRegisterMemoryBlock block; protected final DBTraceProgramViewRegisterMemoryBlock block;
public DBTraceProgramViewRegisterMemory(DBTraceProgramView program, public DBTraceProgramViewRegisterMemory(DBTraceProgramView program,
DBTraceMemoryRegisterSpace space) { DBTraceMemorySpace space) {
super(program); super(program);
this.space = space; this.space = space;
this.block = new DBTraceProgramViewRegisterMemoryBlock(program, 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.database.mem.FileBytes;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace; import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.model.memory.TraceMemorySpaceInputStream; import ghidra.trace.model.memory.TraceMemorySpaceInputStream;
public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock { public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
@ -96,14 +96,14 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
} }
private final DBTraceProgramView program; private final DBTraceProgramView program;
private final DBTraceMemoryRegisterSpace space; private final DBTraceMemorySpace space;
private final AddressRange range; private final AddressRange range;
private final List<MemoryBlockSourceInfo> info = private final List<MemoryBlockSourceInfo> info =
Collections.singletonList(new DBTraceProgramViewRegisterMemoryBlockSourceInfo()); Collections.singletonList(new DBTraceProgramViewRegisterMemoryBlockSourceInfo());
public DBTraceProgramViewRegisterMemoryBlock(DBTraceProgramView program, public DBTraceProgramViewRegisterMemoryBlock(DBTraceProgramView program,
DBTraceMemoryRegisterSpace space) { DBTraceMemorySpace space) {
this.program = program; this.program = program;
this.space = space; this.space = space;
this.range = new AddressRangeImpl(space.getAddressSpace().getMinAddress(), 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.symbol.*;
import ghidra.program.model.util.AddressSetPropertyMap; import ghidra.program.model.util.AddressSetPropertyMap;
import ghidra.program.model.util.PropertyMapManager; import ghidra.program.model.util.PropertyMapManager;
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace; import ghidra.trace.database.listing.DBTraceCodeSpace;
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace; import ghidra.trace.database.memory.DBTraceMemorySpace;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.data.TraceBasedDataTypeManager; import ghidra.trace.model.data.TraceBasedDataTypeManager;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
@ -56,8 +56,8 @@ public class DBTraceProgramViewRegisters implements TraceProgramView {
private final DBTraceProgramViewRegisterMemory memory; private final DBTraceProgramViewRegisterMemory memory;
private final DBTraceProgramViewRegistersReferenceManager referenceManager; private final DBTraceProgramViewRegistersReferenceManager referenceManager;
public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeRegisterSpace codeSpace, public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeSpace codeSpace,
DBTraceMemoryRegisterSpace memorySpace) { DBTraceMemorySpace memorySpace) {
this.view = view; this.view = view;
this.thread = codeSpace.getThread(); // TODO: Bleh, should be parameter 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.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBased, R extends M> public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBased>
implements DBTraceManager { implements DBTraceManager {
protected static final AddressSpace NO_ADDRESS_SPACE = Address.NO_ADDRESS.getAddressSpace(); 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 // Note: use tree map so traversal is ordered by address space
protected final Map<AddressSpace, M> memSpaces = new TreeMap<>(); protected final Map<AddressSpace, M> memSpaces = new TreeMap<>();
// Note: can use hash map here. I see no need to order these spaces // 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 = protected final Collection<M> memSpacesView =
Collections.unmodifiableCollection(memSpaces.values()); Collections.unmodifiableCollection(memSpaces.values());
protected final Collection<R> regSpacesView = protected final Collection<M> regSpacesView =
Collections.unmodifiableCollection(regSpaces.values()); Collections.unmodifiableCollection(regSpaces.values());
protected final Collection<M> allSpacesView = protected final Collection<M> allSpacesView =
new CatenatedCollection<>(memSpacesView, regSpacesView); new CatenatedCollection<>(memSpacesView, regSpacesView);
@ -145,12 +145,12 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
continue; continue;
} }
TraceThread thread = threadManager.getThread(ent.threadKey); TraceThread thread = threadManager.getThread(ent.threadKey);
R regSpace; M regSpace;
if (ent.space == null) { if (ent.space == null) {
regSpace = createRegisterSpace(space, thread, ent); regSpace = createRegisterSpace(space, thread, ent);
} }
else { else {
regSpace = (R) ent.space; regSpace = (M) ent.space;
} }
regSpaces.put(ImmutablePair.of(thread, ent.getFrameLevel()), regSpace); 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); trace.getThreadManager().assertIsMine(thread);
// TODO: What if registers are memory mapped? // TODO: What if registers are memory mapped?
Pair<TraceThread, Integer> frame = ImmutablePair.of(thread, frameLevel); 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); return getForRegisterSpace(frame.getStack().getThread(), frame.getLevel(), createIfAbsent);
} }
@ -259,14 +259,14 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
return memSpacesView; return memSpacesView;
} }
public Collection<R> getActiveRegisterSpaces() { public Collection<M> getActiveRegisterSpaces() {
return regSpacesView; return regSpacesView;
} }
protected abstract M createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected abstract M createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException; throws VersionException, IOException;
protected abstract R createRegisterSpace(AddressSpace space, TraceThread thread, protected abstract M createRegisterSpace(AddressSpace space, TraceThread thread,
DBTraceSpaceEntry ent) throws VersionException, IOException; DBTraceSpaceEntry ent) throws VersionException, IOException;
@Override @Override
@ -286,7 +286,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
for (M m : memSpaces.values()) { for (M m : memSpaces.values()) {
m.invalidateCache(); m.invalidateCache();
} }
for (R r : regSpaces.values()) { for (M r : regSpaces.values()) {
r.invalidateCache(); r.invalidateCache();
} }
} }

View file

@ -40,8 +40,7 @@ import ghidra.util.database.*;
import ghidra.util.exception.*; import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceEquateManager public class DBTraceEquateManager extends AbstractDBTraceSpaceBasedManager<DBTraceEquateSpace>
extends AbstractDBTraceSpaceBasedManager<DBTraceEquateSpace, DBTraceEquateRegisterSpace>
implements TraceEquateManager, DBTraceDelegatingManager<DBTraceEquateSpace> { implements TraceEquateManager, DBTraceDelegatingManager<DBTraceEquateSpace> {
public static final String NAME = "Equate"; public static final String NAME = "Equate";
@ -96,13 +95,13 @@ public class DBTraceEquateManager
} }
@Override @Override
public DBTraceEquateRegisterSpace getEquateRegisterSpace(TraceThread thread, public DBTraceEquateSpace getEquateRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent); return getForRegisterSpace(thread, 0, createIfAbsent);
} }
@Override @Override
public DBTraceEquateRegisterSpace getEquateRegisterSpace(TraceStackFrame frame, public DBTraceEquateSpace getEquateRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(frame, createIfAbsent); return getForRegisterSpace(frame, createIfAbsent);
} }
@ -110,13 +109,13 @@ public class DBTraceEquateManager
@Override @Override
protected DBTraceEquateSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceEquateSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceEquateSpace(this, dbh, space, ent); return new DBTraceEquateSpace(this, dbh, space, ent, null);
} }
@Override @Override
protected DBTraceEquateRegisterSpace createRegisterSpace(AddressSpace space, protected DBTraceEquateSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceEquateRegisterSpace(this, dbh, space, ent, thread); return new DBTraceEquateSpace(this, dbh, space, ent, thread);
} }
@Override @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 DBTraceEquateManager manager;
protected final DBHandle dbh; protected final DBHandle dbh;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final Language baseLanguage; protected final Language baseLanguage;
protected final DBTrace trace; protected final DBTrace trace;
@ -110,10 +112,12 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceEquateReference, DBTraceEquateReference> equateMapSpace; protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceEquateReference, DBTraceEquateReference> equateMapSpace;
public DBTraceEquateSpace(DBTraceEquateManager manager, DBHandle dbh, AddressSpace space, public DBTraceEquateSpace(DBTraceEquateManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws VersionException, IOException { DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
this.manager = manager; this.manager = manager;
this.dbh = dbh; this.dbh = dbh;
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock(); this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage(); this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
@ -126,7 +130,8 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
int frameLevel = ent.getFrameLevel(); int frameLevel = ent.getFrameLevel();
this.equateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( this.equateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceEquateReference.tableName(space, threadKey, frameLevel), factory, lock, space, 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 @Override
@ -136,12 +141,12 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
@Override @Override
public TraceThread getThread() { public TraceThread getThread() {
return null; return thread;
} }
@Override @Override
public int getFrameLevel() { public int getFrameLevel() {
return 0; return frameLevel;
} }
@Override @Override

View file

@ -44,8 +44,7 @@ import ghidra.util.database.DBOpenMode;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceReferenceManager extends public class DBTraceReferenceManager extends AbstractDBTraceSpaceBasedManager<DBTraceReferenceSpace>
AbstractDBTraceSpaceBasedManager<DBTraceReferenceSpace, DBTraceReferenceRegisterSpace>
implements TraceReferenceManager, DBTraceDelegatingManager<DBTraceReferenceSpace> { implements TraceReferenceManager, DBTraceDelegatingManager<DBTraceReferenceSpace> {
public static final String NAME = "Reference"; public static final String NAME = "Reference";
@ -64,13 +63,13 @@ public class DBTraceReferenceManager extends
@Override @Override
protected DBTraceReferenceSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceReferenceSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceReferenceSpace(this, dbh, space, ent); return new DBTraceReferenceSpace(this, dbh, space, ent, null);
} }
@Override @Override
protected DBTraceReferenceRegisterSpace createRegisterSpace(AddressSpace space, protected DBTraceReferenceSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { 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 @Override
public DBTraceReferenceRegisterSpace getReferenceRegisterSpace(TraceThread thread, public DBTraceReferenceSpace getReferenceRegisterSpace(TraceThread thread,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(thread, 0, createIfAbsent); return getForRegisterSpace(thread, 0, createIfAbsent);
} }
@Override @Override
public DBTraceReferenceRegisterSpace getReferenceRegisterSpace(TraceStackFrame frame, public DBTraceReferenceSpace getReferenceRegisterSpace(TraceStackFrame frame,
boolean createIfAbsent) { boolean createIfAbsent) {
return getForRegisterSpace(frame, 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 DBTraceReferenceManager manager;
protected final DBHandle dbh; protected final DBHandle dbh;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final Language baseLanguage; protected final Language baseLanguage;
protected final DBTrace trace; protected final DBTrace trace;
@ -347,10 +349,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
protected final DBCachedObjectIndex<Long, DBTraceXRefEntry> xrefsByRefKey; protected final DBCachedObjectIndex<Long, DBTraceXRefEntry> xrefsByRefKey;
public DBTraceReferenceSpace(DBTraceReferenceManager manager, DBHandle dbh, AddressSpace space, public DBTraceReferenceSpace(DBTraceReferenceManager manager, DBHandle dbh, AddressSpace space,
DBTraceSpaceEntry ent) throws VersionException, IOException { DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
this.manager = manager; this.manager = manager;
this.dbh = dbh; this.dbh = dbh;
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock(); this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage(); this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
@ -363,13 +367,14 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
int frameLevel = ent.getFrameLevel(); int frameLevel = ent.getFrameLevel();
this.referenceMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( this.referenceMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceReferenceEntry.tableName(space, threadKey, frameLevel), factory, lock, space, 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 = this.refsBySymbolId =
referenceMapSpace.getUserIndex(long.class, DBTraceReferenceEntry.SYMBOL_ID_COLUMN); referenceMapSpace.getUserIndex(long.class, DBTraceReferenceEntry.SYMBOL_ID_COLUMN);
this.xrefMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( this.xrefMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space, DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space, thread,
DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r)); frameLevel, DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r));
this.xrefsByRefKey = xrefMapSpace.getUserIndex(long.class, DBTraceXRefEntry.REF_KEY_COLUMN); this.xrefsByRefKey = xrefMapSpace.getUserIndex(long.class, DBTraceXRefEntry.REF_KEY_COLUMN);
} }
@ -409,12 +414,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
@Override @Override
public TraceThread getThread() { public TraceThread getThread() {
return null; return thread;
} }
@Override @Override
public int getFrameLevel() { public int getFrameLevel() {
return 0; return frameLevel;
} }
@Override @Override

View file

@ -27,9 +27,9 @@ import ghidra.trace.model.thread.TraceThread;
public interface TraceBookmarkManager extends TraceBookmarkOperations { public interface TraceBookmarkManager extends TraceBookmarkOperations {
TraceBookmarkSpace getBookmarkSpace(AddressSpace space, boolean createIfAbsent); 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); 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; package ghidra.trace.model.bookmark;
import com.google.common.collect.Range;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceRegisterUtils;
public interface TraceBookmarkSpace extends TraceBookmarkOperations { public interface TraceBookmarkSpace extends TraceBookmarkOperations {
AddressSpace getAddressSpace(); AddressSpace getAddressSpace();
TraceThread getThread(); 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; package ghidra.trace.model.listing;
import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.Range; import com.google.common.collect.Range;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceRegisterUtils;
import ghidra.util.IntersectionAddressSetView; import ghidra.util.IntersectionAddressSetView;
import ghidra.util.UnionAddressSetView; import ghidra.util.UnionAddressSetView;
/** /**
* A view of code units stored in a trace, possibly restricted to a particular subset by type, * 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 * @param <T> the type of units in the view
*/ */
@ -38,6 +44,20 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
*/ */
Trace getTrace(); 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 * 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 * 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 * Note that the ranges in this set may not be coalesced. If a coalesced set is required, wrap
* it with {@link UnionAddressSetView}. * 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 * 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 * 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 * 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 * {@code within}, but they will intersect it. If strict enclosure is required, wrap the set
* {@link IntersectionAddressSetView}. * with {@link IntersectionAddressSetView}.
* *
* @param snap the snap during which the units must be alive * @param snap the snap during which the units must be alive
* @param within the range to restrict the view * @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 * 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 * This checks if every (snap, address) point within the given box is contained within some code
* unit in this view. * 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 * 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 * This checks if every (snap, address) point within the given box is contained within some code
* unit in this view. * 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 * 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 * This checks if any (snap, address) point within the given box is contained within some code
* unit in this view. * 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 * 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 * This checks if any (snap, address) point within the given box is contained within some code
* unit in this view. * unit in this view.
* *
@ -239,4 +265,77 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
* @return true if intersecting, false otherwise * @return true if intersecting, false otherwise
*/ */
boolean intersectsRange(TraceAddressSnapRange range); 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