mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-12-13 06:33:02 +00:00
GP-2479: Remove register-specific space interfaces from Trace API
This commit is contained in:
parent
1eb2e71734
commit
0459d93508
@ -300,7 +300,7 @@ public class PopulateTraceLocal extends GhidraScript {
|
||||
|
||||
Collection<? extends TraceThread> liveThreads = threads.getLiveThreads(snap);
|
||||
for (TraceThread thread : liveThreads) {
|
||||
TraceMemoryRegisterSpace regspace = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regspace = memory.getMemoryRegisterSpace(thread, true);
|
||||
ModelObject modelThread = modelThreadMap.get("0x" + thread.getName());
|
||||
if (modelThread != null) {
|
||||
Map<String, ModelObject> registers =
|
||||
|
@ -34,7 +34,7 @@ import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.program.util.DefaultLanguageService;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.listing.TraceCodeRegisterSpace;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.symbol.TraceLabelSymbol;
|
||||
import ghidra.trace.model.symbol.TraceNamespaceSymbol;
|
||||
@ -149,13 +149,13 @@ public class PopulateDemoTrace extends GhidraScript {
|
||||
* Fields to store the handle to the first (main) thread and its registers
|
||||
*/
|
||||
private TraceThread thread1;
|
||||
private TraceMemoryRegisterSpace regs1;
|
||||
private TraceMemorySpace regs1;
|
||||
|
||||
/**
|
||||
* Fields to store the handle to the second (cloned) thread and its registers
|
||||
*/
|
||||
private TraceThread thread2;
|
||||
private TraceMemoryRegisterSpace regs2;
|
||||
private TraceMemorySpace regs2;
|
||||
|
||||
/**
|
||||
* Create an address in the processor's (x86_64) default space.
|
||||
@ -195,7 +195,7 @@ public class PopulateDemoTrace extends GhidraScript {
|
||||
* @param regs the register space for a given thread
|
||||
* @param ins the instructions
|
||||
*/
|
||||
protected void putRIP(long tick, TraceMemoryRegisterSpace regs, Instruction ins) {
|
||||
protected void putRIP(long tick, TraceMemorySpace regs, Instruction ins) {
|
||||
regs.setValue(tick,
|
||||
new RegisterValue(reg("RIP"), ins.getAddress().getOffsetAsBigInteger()));
|
||||
}
|
||||
@ -224,7 +224,7 @@ public class PopulateDemoTrace extends GhidraScript {
|
||||
// NOTE: This is compensating for a TODO in the memory and code managers
|
||||
|
||||
// TODO: Consider convenience methods TraceThread#getMemorySpace(boolean), etc
|
||||
TraceMemoryRegisterSpace mem =
|
||||
TraceMemorySpace mem =
|
||||
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
// First check if the value was set at all
|
||||
if (mem.getState(tick, reg) != TraceMemoryState.KNOWN) {
|
||||
@ -237,7 +237,7 @@ public class PopulateDemoTrace extends GhidraScript {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceCodeRegisterSpace code =
|
||||
TraceCodeSpace code =
|
||||
thread.getTrace().getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
code.definedUnits().clear(Range.atLeast(tick), reg, TaskMonitor.DUMMY);
|
||||
code.definedData().create(Range.atLeast(tick), reg, PointerDataType.dataType);
|
||||
|
@ -22,7 +22,7 @@ import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
@ -58,7 +58,7 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
|
||||
if (!thread.getLifespan().contains(snap)) {
|
||||
return null;
|
||||
}
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, frame, false);
|
||||
if (regs == null) {
|
||||
return null;
|
||||
|
@ -71,7 +71,7 @@ import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.Trace.*;
|
||||
import ghidra.trace.model.listing.*;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
@ -281,7 +281,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
}
|
||||
|
||||
private void refreshRange(AddressRange range) {
|
||||
TraceMemoryRegisterSpace space = getRegisterMemorySpace(false);
|
||||
TraceMemorySpace space = getRegisterMemorySpace(false);
|
||||
// ... If I got an event for it, it ought to exist.
|
||||
assert space != null;
|
||||
|
||||
@ -857,7 +857,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
}
|
||||
|
||||
BigInteger getRegisterValue(Register register) {
|
||||
TraceMemoryRegisterSpace regs = getRegisterMemorySpace(false);
|
||||
TraceMemorySpace regs = getRegisterMemorySpace(false);
|
||||
if (regs == null) {
|
||||
return BigInteger.ZERO;
|
||||
}
|
||||
@ -901,7 +901,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
}
|
||||
|
||||
private RegisterValue combineWithTraceBaseRegisterValue(RegisterValue rv) {
|
||||
TraceMemoryRegisterSpace regs = getRegisterMemorySpace(false);
|
||||
TraceMemorySpace regs = getRegisterMemorySpace(false);
|
||||
long snap = current.getViewSnap();
|
||||
return TraceRegisterUtils.combineWithTraceBaseRegisterValue(rv, snap, regs, true);
|
||||
}
|
||||
@ -914,7 +914,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
void writeRegisterDataType(Register register, DataType dataType) {
|
||||
try (UndoableTransaction tid =
|
||||
UndoableTransaction.start(current.getTrace(), "Edit Register Type")) {
|
||||
TraceCodeRegisterSpace space = getRegisterMemorySpace(true).getCodeSpace(true);
|
||||
TraceCodeSpace space = getRegisterMemorySpace(true).getCodeSpace(true);
|
||||
long snap = current.getViewSnap();
|
||||
space.definedUnits().clear(Range.closed(snap, snap), register, TaskMonitor.DUMMY);
|
||||
if (dataType != null) {
|
||||
@ -927,7 +927,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
}
|
||||
|
||||
TraceData getRegisterData(Register register) {
|
||||
TraceCodeRegisterSpace space = getRegisterCodeSpace(false);
|
||||
TraceCodeSpace space = getRegisterCodeSpace(false);
|
||||
if (space == null) {
|
||||
return null;
|
||||
}
|
||||
@ -985,7 +985,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
viewKnown = null;
|
||||
return;
|
||||
}
|
||||
TraceMemoryRegisterSpace regs = getRegisterMemorySpace(false);
|
||||
TraceMemorySpace regs = getRegisterMemorySpace(false);
|
||||
TraceProgramView view = current.getView();
|
||||
if (regs == null || view == null) {
|
||||
viewKnown = null;
|
||||
@ -1014,8 +1014,8 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
if (!isRegisterKnown(register)) {
|
||||
return false;
|
||||
}
|
||||
TraceMemoryRegisterSpace curSpace = getRegisterMemorySpace(current, false);
|
||||
TraceMemoryRegisterSpace prevSpace = getRegisterMemorySpace(previous, false);
|
||||
TraceMemorySpace curSpace = getRegisterMemorySpace(current, false);
|
||||
TraceMemorySpace prevSpace = getRegisterMemorySpace(previous, false);
|
||||
if (prevSpace == null) {
|
||||
return false;
|
||||
}
|
||||
@ -1104,7 +1104,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
return viewKnown;
|
||||
}
|
||||
|
||||
protected static TraceMemoryRegisterSpace getRegisterMemorySpace(DebuggerCoordinates coords,
|
||||
protected static TraceMemorySpace getRegisterMemorySpace(DebuggerCoordinates coords,
|
||||
boolean createIfAbsent) {
|
||||
TraceThread thread = coords.getThread();
|
||||
if (thread == null) {
|
||||
@ -1115,11 +1115,11 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
.getMemoryRegisterSpace(thread, coords.getFrame(), createIfAbsent);
|
||||
}
|
||||
|
||||
protected TraceMemoryRegisterSpace getRegisterMemorySpace(boolean createIfAbsent) {
|
||||
protected TraceMemorySpace getRegisterMemorySpace(boolean createIfAbsent) {
|
||||
return getRegisterMemorySpace(current, createIfAbsent);
|
||||
}
|
||||
|
||||
protected TraceCodeRegisterSpace getRegisterCodeSpace(boolean createIfAbsent) {
|
||||
protected TraceCodeSpace getRegisterCodeSpace(boolean createIfAbsent) {
|
||||
TraceThread curThread = current.getThread();
|
||||
if (curThread == null) {
|
||||
return null;
|
||||
@ -1132,7 +1132,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
||||
protected Set<Register> collectBaseRegistersWithKnownValues(TraceThread thread) {
|
||||
// TODO: Other registers may acquire known values.
|
||||
// TODO: How to best alert the user? Just add to view?
|
||||
TraceMemoryRegisterSpace mem =
|
||||
TraceMemorySpace mem =
|
||||
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
Set<Register> result = new LinkedHashSet<>();
|
||||
if (mem == null) {
|
||||
|
@ -45,7 +45,7 @@ import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.Trace.TraceMemoryBytesChangeType;
|
||||
import ghidra.trace.model.Trace.TraceStackChangeType;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
@ -194,7 +194,7 @@ public class DebuggerStackProvider extends ComponentProviderAdapter {
|
||||
if (!TraceRegisterUtils.rangeForRegister(pc).intersects(range.getRange())) {
|
||||
return;
|
||||
}
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(curThread, false);
|
||||
RegisterValue value = regs.getViewValue(current.getViewSnap(), pc);
|
||||
Address address = trace.getBaseLanguage()
|
||||
@ -427,7 +427,7 @@ public class DebuggerStackProvider extends ComponentProviderAdapter {
|
||||
currentStack = null;
|
||||
|
||||
Trace curTrace = current.getTrace();
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
curTrace.getMemoryManager().getMemoryRegisterSpace(current.getThread(), false);
|
||||
if (regs == null) {
|
||||
contextChanged();
|
||||
|
@ -24,7 +24,7 @@ import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.Msg;
|
||||
@ -78,8 +78,7 @@ public class ArmDisassemblyInject implements DisassemblyInject {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceMemoryRegisterSpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
/**
|
||||
* Some variants (particularly Cortex-M) are missing cpsr. This seems to indicate it only
|
||||
* supports THUMB. There is an epsr (xpsr in gdb), but we don't have it in our models, and
|
||||
|
@ -216,7 +216,7 @@ public enum ProgramEmulationUtils {
|
||||
*/
|
||||
public static void initializeRegisters(Trace trace, long snap, TraceThread thread,
|
||||
Program program, Address tracePc, Address programPc, TraceMemoryRegion stack) {
|
||||
TraceMemoryRegisterSpace space =
|
||||
TraceMemorySpace space =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
if (program != null) {
|
||||
ProgramContext ctx = program.getProgramContext();
|
||||
|
@ -266,11 +266,11 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
|
||||
TimedMsg.debug(this, "Reg values changed: " + updates.keySet());
|
||||
recorder.parTx.execute("Registers " + path + " changed", () -> {
|
||||
TraceCodeManager codeManager = trace.getCodeManager();
|
||||
TraceCodeRegisterSpace codeRegisterSpace =
|
||||
TraceCodeSpace codeRegisterSpace =
|
||||
codeManager.getCodeRegisterSpace(traceThread, false);
|
||||
TraceDefinedDataRegisterView definedData =
|
||||
TraceDefinedDataView definedData =
|
||||
codeRegisterSpace == null ? null : codeRegisterSpace.definedData();
|
||||
TraceMemoryRegisterSpace regSpace =
|
||||
TraceMemorySpace regSpace =
|
||||
memoryManager.getMemoryRegisterSpace(traceThread, frameLevel, true);
|
||||
for (Entry<String, byte[]> ent : updates.entrySet()) {
|
||||
RegisterValue rv = regMapper.targetToTrace(ent.getKey(), ent.getValue());
|
||||
@ -304,11 +304,11 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
|
||||
//TimedMsg.info(this, "Register value changed: " + targetRegister);
|
||||
recorder.parTx.execute("Register " + path + " changed", () -> {
|
||||
TraceCodeManager codeManager = trace.getCodeManager();
|
||||
TraceCodeRegisterSpace codeRegisterSpace =
|
||||
TraceCodeSpace codeRegisterSpace =
|
||||
codeManager.getCodeRegisterSpace(traceThread, false);
|
||||
TraceDefinedDataRegisterView definedData =
|
||||
TraceDefinedDataView definedData =
|
||||
codeRegisterSpace == null ? null : codeRegisterSpace.definedData();
|
||||
TraceMemoryRegisterSpace regSpace =
|
||||
TraceMemorySpace regSpace =
|
||||
memoryManager.getMemoryRegisterSpace(traceThread, frameLevel, true);
|
||||
String key = targetRegister.getName();
|
||||
if (PathUtils.isIndex(key)) {
|
||||
@ -337,7 +337,7 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
|
||||
String path = bank.getJoinedPath(".");
|
||||
|
||||
recorder.parTx.execute("Registers invalidated: " + path, () -> {
|
||||
TraceMemoryRegisterSpace regSpace =
|
||||
TraceMemorySpace regSpace =
|
||||
memoryManager.getMemoryRegisterSpace(traceThread, frameLevel, false);
|
||||
if (regSpace == null) {
|
||||
return;
|
||||
|
@ -227,8 +227,7 @@ public class DisassembleAtPcDebuggerBot implements DebuggerBot {
|
||||
TraceData pcUnit = null;
|
||||
try (UndoableTransaction tid =
|
||||
UndoableTransaction.start(trace, "Disassemble: PC is code pointer")) {
|
||||
TraceCodeRegisterSpace regCode =
|
||||
codeManager.getCodeRegisterSpace(thread, frameLevel, true);
|
||||
TraceCodeSpace regCode = codeManager.getCodeRegisterSpace(thread, frameLevel, true);
|
||||
try {
|
||||
pcUnit = regCode.definedData()
|
||||
.create(Range.atLeast(pcSnap), pc, PointerDataType.dataType);
|
||||
|
@ -32,7 +32,7 @@ import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.modules.TraceSection;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
@ -365,7 +365,7 @@ public interface TraceRecorder {
|
||||
|
||||
RegisterValue rv = new RegisterValue(register,
|
||||
Utils.bytesToBigInteger(data, data.length, lang.isBigEndian(), false));
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frameLevel, false);
|
||||
rv = TraceRegisterUtils.combineWithTraceBaseRegisterValue(rv, getSnap(), regs, true);
|
||||
return writeThreadRegisters(thread, frameLevel, Map.of(rv.getRegister(), rv));
|
||||
|
@ -48,7 +48,7 @@ import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
||||
import ghidra.trace.model.memory.TraceMemoryOperations;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
@ -947,7 +947,7 @@ public interface FlatDebuggerAPI {
|
||||
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
return null;
|
||||
}
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, frame, false);
|
||||
if (regs == null) {
|
||||
return registers.stream().map(RegisterValue::new).collect(Collectors.toList());
|
||||
|
@ -31,7 +31,7 @@ import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.symbol.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
@ -110,7 +110,7 @@ public class DebuggerListingPluginScreenShots extends GhidraScreenShotGenerator
|
||||
|
||||
TraceThread thread = tb.getOrAddThread("[1]", snap);
|
||||
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(),
|
||||
childLabel.getAddress().getOffsetAsBigInteger()));
|
||||
|
@ -31,7 +31,7 @@ import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.symbol.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
@ -114,7 +114,7 @@ public class DebuggerMemoryBytesPluginScreenShots extends GhidraScreenShotGenera
|
||||
|
||||
TraceThread thread = tb.getOrAddThread("[1]", snap);
|
||||
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(),
|
||||
childLabel.getAddress().getOffsetAsBigInteger()));
|
||||
|
@ -28,7 +28,7 @@ import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
@ -62,7 +62,7 @@ public class DebuggerRegistersPluginScreenShots extends GhidraScreenShotGenerato
|
||||
long snap1 = tb.trace.getTimeManager().createSnapshot("Second").getKey();
|
||||
|
||||
TraceThread thread = tb.getOrAddThread("[1]", snap0);
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
Language lang = tb.trace.getBaseLanguage();
|
||||
regs.setValue(snap0,
|
||||
|
@ -56,7 +56,7 @@ import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.trace.database.listing.DBTraceInstruction;
|
||||
import ghidra.trace.database.listing.DBTraceInstructionsMemoryView;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.database.program.DBTraceVariableSnapProgramView;
|
||||
import ghidra.trace.database.target.DBTraceObject;
|
||||
import ghidra.trace.database.target.DBTraceObjectManager;
|
||||
@ -225,7 +225,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
|
||||
TraceThread thread;
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
thread = tb.getOrAddThread("Threads[0]", 0);
|
||||
DBTraceMemoryRegisterSpace regs =
|
||||
DBTraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO));
|
||||
}
|
||||
@ -259,7 +259,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerGUITest
|
||||
TraceThread thread;
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
thread = tb.getOrAddThread("Threads[0]", 0);
|
||||
DBTraceMemoryRegisterSpace regs =
|
||||
DBTraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0,
|
||||
new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ONE.shiftLeft(5)));
|
||||
|
@ -68,7 +68,7 @@ import ghidra.test.TestEnv;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.Trace.TraceMemoryBytesChangeType;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.util.InvalidNameException;
|
||||
@ -750,7 +750,7 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
|
||||
if (space.getThread() != traceThread) {
|
||||
return;
|
||||
}
|
||||
TraceMemoryRegisterSpace regSpace =
|
||||
TraceMemorySpace regSpace =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false);
|
||||
assertNotNull(regSpace);
|
||||
for (Map.Entry<String, byte[]> ent : values.entrySet()) {
|
||||
|
@ -182,7 +182,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main dynamic listing
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -208,7 +208,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main dynamic listing
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -237,9 +237,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main dynamic listing
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -282,9 +282,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main dynamic listing
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -322,7 +322,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
assertEquals(tb.trace.getProgramView(), listingProvider.getProgram());
|
||||
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
|
||||
regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800)));
|
||||
}
|
||||
@ -356,7 +356,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
t1 = b1.getOrAddThread("Thread1", 0);
|
||||
|
||||
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -368,7 +368,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
t2 = b2.getOrAddThread("Thread2", 0);
|
||||
|
||||
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -412,7 +412,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
t1 = b1.getOrAddThread("Thread1", 0);
|
||||
|
||||
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -424,7 +424,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
t2 = b2.getOrAddThread("Thread2", 0);
|
||||
|
||||
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -505,7 +505,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
thread = tb.getOrAddThread("Thread1", 0);
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForProgram(program);
|
||||
@ -582,7 +582,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
thread = tb.getOrAddThread("Thread1", 0);
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -618,7 +618,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
thread = tb.getOrAddThread("Thread1", 0);
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00408765)));
|
||||
}
|
||||
@ -823,7 +823,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
Register r0 = tb.language.getRegister("r0");
|
||||
regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16)));
|
||||
mm.putBytes(0, tb.addr(0x00401234), tb.buf(0x00, 0x40, 0x43, 0x21));
|
||||
@ -863,7 +863,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
mm.addRegion("[stack]", Range.atLeast(0L), tb.range(0x1f000000, 0x1fffffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
Register pc = tb.language.getProgramCounter();
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
|
||||
@ -1009,9 +1009,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main dynamic listing
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -1309,9 +1309,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread1 = tb.getOrAddThread("Thread 1", 0);
|
||||
thread2 = tb.getOrAddThread("Thread 2", 0);
|
||||
TraceMemoryRegisterSpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
TraceMemoryRegisterSpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -1338,7 +1338,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
@ -1394,7 +1394,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -1404,7 +1404,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -1424,7 +1424,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
|
||||
DBTraceStackManager sm = tb.trace.getStackManager();
|
||||
@ -1438,7 +1438,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
|
@ -158,7 +158,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main bytes viewer
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -184,7 +184,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main bytes viewer
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -214,9 +214,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main bytes viewer
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -259,9 +259,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main bytes viewer
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -299,7 +299,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
assertEquals(tb.trace.getProgramView(), memBytesProvider.getProgram());
|
||||
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
|
||||
regs.setValue(0, new RegisterValue(sp, BigInteger.valueOf(0x01fff800)));
|
||||
}
|
||||
@ -332,7 +332,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
t1 = b1.getOrAddThread("Thread1", 0);
|
||||
|
||||
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -344,7 +344,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
t2 = b2.getOrAddThread("Thread2", 0);
|
||||
|
||||
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -383,7 +383,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
t1 = b1.getOrAddThread("Thread1", 0);
|
||||
|
||||
Register pc = b1.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -395,7 +395,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
t2 = b2.getOrAddThread("Thread2", 0);
|
||||
|
||||
Register pc = b2.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(b1.trace);
|
||||
@ -456,7 +456,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
thread = tb.getOrAddThread("Thread1", 0);
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -616,7 +616,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
Register r0 = tb.language.getRegister("r0");
|
||||
regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16)));
|
||||
mm.putBytes(0, tb.addr(0x00401234), tb.buf(0x00, 0x40, 0x43, 0x21));
|
||||
@ -656,7 +656,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
mm.addRegion("[stack]", Range.atLeast(0L), tb.range(0x1f000000, 0x1fffffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
Register pc = tb.language.getProgramCounter();
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
Register sp = tb.trace.getBaseCompilerSpec().getStackPointer();
|
||||
@ -708,9 +708,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
|
||||
// NOTE: PC-tracking should be the default for the main dynamic listing
|
||||
Register pc = tb.trace.getBaseLanguage().getProgramCounter();
|
||||
TraceMemoryRegisterSpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = memory.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234)));
|
||||
TraceMemoryRegisterSpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = memory.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00405678)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -911,9 +911,9 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread1 = tb.getOrAddThread("Thread 1", 0);
|
||||
thread2 = tb.getOrAddThread("Thread 2", 0);
|
||||
TraceMemoryRegisterSpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
|
||||
TraceMemorySpace regs1 = mm.getMemoryRegisterSpace(thread1, true);
|
||||
regs1.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
TraceMemoryRegisterSpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
|
||||
TraceMemorySpace regs2 = mm.getMemoryRegisterSpace(thread2, true);
|
||||
regs2.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -940,7 +940,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
@ -996,7 +996,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -1006,7 +1006,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
@ -1026,7 +1026,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||
|
||||
DBTraceStackManager sm = tb.trace.getStackManager();
|
||||
@ -1040,7 +1040,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
||||
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00404321", 16)));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
|
@ -46,10 +46,10 @@ import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
|
||||
import ghidra.trace.database.listing.DBTraceCodeSpace;
|
||||
import ghidra.trace.model.listing.*;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
@ -122,7 +122,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
}
|
||||
|
||||
protected void addRegisterValues(TraceThread thread, UndoableTransaction tid) {
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regVals.putBytes(0, pc, tb.buf(0, 0, 0, 0, 0, 0x40, 0, 0));
|
||||
regVals.putBytes(0, sp, tb.buf(0x1f, 0, 0, 0, 0, 0, 0, 0));
|
||||
@ -131,7 +131,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
|
||||
protected void addRegisterTypes(TraceThread thread, UndoableTransaction tid)
|
||||
throws CodeUnitInsertionException {
|
||||
TraceCodeRegisterSpace regCode =
|
||||
TraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
regCode.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
|
||||
// TODO: Pointer needs to be to ram, not register space
|
||||
@ -384,7 +384,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
addRegisterValues(thread);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
|
||||
RegisterRow row = findRegisterRow(r0);
|
||||
@ -422,7 +422,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
addRegisterValues(thread);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
|
||||
RegisterRow row = findRegisterRow(r0);
|
||||
@ -456,7 +456,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
row.setDataType(PointerDataType.dataType);
|
||||
waitForSwing();
|
||||
|
||||
DBTraceCodeRegisterSpace regCode =
|
||||
DBTraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
|
||||
assertNotNull(regCode);
|
||||
TraceData data = regCode.data().getForRegister(0L, pc);
|
||||
@ -478,7 +478,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
row.setDataType(LongLongDataType.dataType);
|
||||
waitForSwing();
|
||||
|
||||
DBTraceCodeRegisterSpace regCode =
|
||||
DBTraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
|
||||
assertNotNull(regCode);
|
||||
TraceData data = regCode.data().getForRegister(0L, pc);
|
||||
@ -514,7 +514,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
rowH.setDataType(SignedDWordDataType.dataType);
|
||||
waitForSwing();
|
||||
|
||||
DBTraceCodeRegisterSpace regCode =
|
||||
DBTraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, false);
|
||||
assertNotNull(regCode);
|
||||
// It's two units, not a struct with two components
|
||||
@ -621,9 +621,9 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
assertR0RowValuePopulated();
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
TraceCodeRegisterSpace regCode =
|
||||
TraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
regVals.putBytes(1, r0, tb.buf(1, 1, 2, 2, 3, 3, 4, 4));
|
||||
regCode.definedData().create(Range.atLeast(1L), r0, r0Struct);
|
||||
@ -649,7 +649,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
assertR0RowTypePopulated();
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceCodeRegisterSpace regCode =
|
||||
TraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0);
|
||||
code.setEndSnap(0);
|
||||
@ -679,7 +679,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
assertR0RowTypePopulated();
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceCodeRegisterSpace regCode =
|
||||
TraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
TraceCodeUnit code = regCode.codeUnits().getContaining(1, r0);
|
||||
code.delete();
|
||||
@ -890,9 +890,9 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
assertR0RowTypePopulated();
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
TraceCodeRegisterSpace regCode =
|
||||
TraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
regVals.putBytes(10, r0, tb.buf(0, 0, 0, 0, 0, 0, 0, 0));
|
||||
// NB. the manager should have split the data unit at the value change
|
||||
@ -932,11 +932,11 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
||||
assertR0RowTypePopulated();
|
||||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, 1, true);
|
||||
regVals.putBytes(0, pc, tb.buf(0, 0, 0, 0, 0, 0x50, 0, 0));
|
||||
|
||||
TraceCodeRegisterSpace regCode =
|
||||
TraceCodeSpace regCode =
|
||||
tb.trace.getCodeManager().getCodeRegisterSpace(thread, 1, true);
|
||||
regCode.definedData().create(Range.atLeast(0L), pc, QWordDataType.dataType);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.DefaultTraceLocation;
|
||||
import ghidra.trace.model.TraceLocation;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
@ -73,7 +73,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
||||
|
||||
protected void addRegVals(TraceThread thread) {
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00400123", 16)));
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
private void setRegisterValues(TraceThread thread) {
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x00400000)));
|
||||
}
|
||||
@ -318,7 +318,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
waitForSwing();
|
||||
|
||||
// Verify no target read has occurred yet
|
||||
TraceMemoryRegisterSpace regs =
|
||||
TraceMemorySpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
if (regs != null) {
|
||||
assertEquals(BigInteger.ZERO, regs.getValue(0, r0).getUnsignedValue());
|
||||
@ -402,7 +402,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
@Test
|
||||
public void testEditRegisterEmu() {
|
||||
WatchRow row = prepareTestEditEmu("r0");
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
|
||||
row.setRawValueString("0x1234");
|
||||
@ -433,7 +433,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
waitForSwing();
|
||||
assertTrue(row.isValueEditable());
|
||||
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
|
||||
row.setValueString("1234");
|
||||
@ -748,7 +748,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
.createLabel(tb.addr(0x00601234), "my_symbol", SourceType.USER_DEFINED);
|
||||
}
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryRegisterSpace regVals =
|
||||
TraceMemorySpace regVals =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regVals.setValue(0, new RegisterValue(r0, BigInteger.valueOf(0x55751234)));
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ import ghidra.pcode.exec.DebuggerPcodeUtils;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
@ -366,8 +366,8 @@ public class DebuggerStateEditingServiceTest extends AbstractGhidraHeadedDebugge
|
||||
StateEditor editor = editingService.createStateEditor(tb.trace);
|
||||
waitOn(editor.setRegister(rv1234));
|
||||
waitForPass(() -> {
|
||||
DBTraceMemoryRegisterSpace regs = tb.trace.getMemoryManager()
|
||||
.getMemoryRegisterSpace(thread, false);
|
||||
TraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
assertNotNull(regs);
|
||||
RegisterValue value = regs.getValue(traceManager.getCurrentSnap(), r0);
|
||||
assertEquals(rv1234, value);
|
||||
|
@ -36,7 +36,7 @@ import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
@ -89,8 +89,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
|
||||
assertNotNull(trace);
|
||||
|
||||
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
|
||||
TraceMemoryRegisterSpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
assertEquals(new BigInteger("00400000", 16),
|
||||
regs.getViewValue(0, regPC).getUnsignedValue());
|
||||
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue());
|
||||
@ -146,8 +145,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
|
||||
assertNotNull(trace);
|
||||
|
||||
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
|
||||
TraceMemoryRegisterSpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
assertEquals(new BigInteger("00000400", 16),
|
||||
regs.getViewValue(0, regPC).getUnsignedValue());
|
||||
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regR0).getUnsignedValue());
|
||||
@ -205,8 +203,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerGU
|
||||
assertNotNull(trace);
|
||||
|
||||
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
|
||||
TraceMemoryRegisterSpace regs =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
assertEquals(new BigInteger("000100", 16),
|
||||
regs.getViewValue(0, regPC).getUnsignedValue());
|
||||
assertEquals(new BigInteger("0000", 16), regs.getViewValue(0, regW0).getUnsignedValue());
|
||||
|
@ -36,7 +36,7 @@ import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceCodeRegisterSpace;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
@ -75,7 +75,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
});
|
||||
}
|
||||
|
||||
protected TraceMemoryRegisterSpace createRegSpace(TraceThread thread) {
|
||||
protected TraceMemorySpace createRegSpace(TraceThread thread) {
|
||||
try (UndoableTransaction tid =
|
||||
UndoableTransaction.start(thread.getTrace(), "Create register space")) {
|
||||
return thread.getTrace().getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
@ -105,7 +105,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
Register r1 = lang.getRegister("r1");
|
||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||
//TraceThread thread = recorder.getTraceThread(mb.testThread1);
|
||||
TraceMemoryRegisterSpace rs = createRegSpace(thread);
|
||||
TraceMemorySpace rs = createRegSpace(thread);
|
||||
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
|
||||
Register::isBaseRegister);
|
||||
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
|
||||
@ -138,13 +138,13 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
Register pc = lang.getRegister("pc");
|
||||
Register sp = lang.getRegister("sp");
|
||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||
TraceMemoryRegisterSpace rs = createRegSpace(thread);
|
||||
TraceMemorySpace rs = createRegSpace(thread);
|
||||
mb.testProcess1.addRegion("bin:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
|
||||
r -> r.isBaseRegister() && r != pc && r != sp);
|
||||
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add PC type")) {
|
||||
TraceCodeRegisterSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
TraceCodeSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
code.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
|
||||
}
|
||||
|
||||
@ -187,13 +187,13 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
Register pc = lang.getRegister("pc");
|
||||
Register sp = lang.getRegister("sp");
|
||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||
TraceMemoryRegisterSpace rs = createRegSpace(thread);
|
||||
TraceMemorySpace rs = createRegSpace(thread);
|
||||
mb.testProcess1.addRegion("[stack]", mb.rng(0x22220000, 0x2222ffff), "rw");
|
||||
mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(),
|
||||
r -> r.isBaseRegister() && r != pc && r != sp);
|
||||
TestTargetRegisterBankInThread regs = mb.testThread1.addRegisterBank();
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add SP type")) {
|
||||
TraceCodeRegisterSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
TraceCodeSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
code.definedData().create(Range.atLeast(0L), sp, PointerDataType.dataType);
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
//waitForCondition(() -> registerMapped(recorder, thread, pc));
|
||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Add PC type")) {
|
||||
TraceCodeRegisterSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
TraceCodeSpace code = trace.getCodeManager().getCodeRegisterSpace(thread, true);
|
||||
code.definedData().create(Range.atLeast(0L), pc, PointerDataType.dataType);
|
||||
}
|
||||
regs.writeRegister("pc", tb.arr(0x55, 0x55, 0x02, 0x22));
|
||||
|
@ -59,7 +59,7 @@ import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
||||
@ -718,7 +718,7 @@ public class FlatDebuggerAPITest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
waitForSwing();
|
||||
|
||||
assertTrue(flat.writeRegister(thread, 0, 0, "r0", BigInteger.valueOf(0x0102030405060708L)));
|
||||
DBTraceMemoryRegisterSpace regs =
|
||||
DBTraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
assertNotNull(regs);
|
||||
Register r0 = tb.language.getRegister("r0");
|
||||
@ -734,7 +734,7 @@ public class FlatDebuggerAPITest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
waitForSwing();
|
||||
|
||||
assertTrue(flat.writeRegister("r0", BigInteger.valueOf(0x0102030405060708L)));
|
||||
DBTraceMemoryRegisterSpace regs =
|
||||
DBTraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
assertNotNull(regs);
|
||||
Register r0 = tb.language.getRegister("r0");
|
||||
|
@ -21,7 +21,7 @@ import ghidra.pcode.emu.PcodeThread;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegisterSpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.thread.TraceThreadManager;
|
||||
@ -88,7 +88,7 @@ public interface TracePcodeMachine<T> extends PcodeMachine<T> {
|
||||
long snap = getSnap();
|
||||
TraceThread traceThread =
|
||||
trace.getThreadManager().getLiveThreadByPath(snap, thread.getName());
|
||||
TraceMemoryRegisterSpace space =
|
||||
TraceMemorySpace space =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(traceThread, false);
|
||||
if (space == null) {
|
||||
return false;
|
||||
|
@ -44,8 +44,7 @@ import ghidra.util.database.DBOpenMode;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceBookmarkManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceBookmarkSpace, DBTraceBookmarkRegisterSpace>
|
||||
public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBTraceBookmarkSpace>
|
||||
implements TraceBookmarkManager, DBTraceDelegatingManager<DBTraceBookmarkSpace> {
|
||||
public static final String NAME = "Bookmark";
|
||||
|
||||
@ -180,13 +179,13 @@ public class DBTraceBookmarkManager
|
||||
@Override
|
||||
protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceBookmarkSpace(this, space);
|
||||
return new DBTraceBookmarkSpace(this, space, null, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceBookmarkRegisterSpace createRegisterSpace(AddressSpace space,
|
||||
protected DBTraceBookmarkSpace createRegisterSpace(AddressSpace space,
|
||||
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceBookmarkRegisterSpace(this, space, thread, ent.getFrameLevel());
|
||||
return new DBTraceBookmarkSpace(this, space, thread, ent.getFrameLevel());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -195,13 +194,13 @@ public class DBTraceBookmarkManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceThread thread,
|
||||
public DBTraceBookmarkSpace getBookmarkRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceStackFrame frame,
|
||||
public DBTraceBookmarkSpace getBookmarkRegisterSpace(TraceStackFrame frame,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame, createIfAbsent);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -39,20 +39,27 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
|
||||
protected final DBTraceBookmarkManager manager;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTrace trace;
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
|
||||
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBookmark, DBTraceBookmark> bookmarkMapSpace;
|
||||
protected final DBCachedObjectIndex<String, DBTraceBookmark> bookmarksByTypeName;
|
||||
protected final Collection<DBTraceBookmark> bookmarkView;
|
||||
|
||||
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space)
|
||||
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space,
|
||||
TraceThread thread, int frameLevel)
|
||||
throws VersionException, IOException {
|
||||
this.manager = manager;
|
||||
this.lock = manager.getLock();
|
||||
this.trace = manager.getTrace();
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = frameLevel;
|
||||
|
||||
this.bookmarkMapSpace =
|
||||
new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space, -1, 0),
|
||||
trace.getStoreFactory(), lock, space, DBTraceBookmark.class,
|
||||
trace.getStoreFactory(), lock, space, null, 0, DBTraceBookmark.class,
|
||||
(t, s, r) -> new DBTraceBookmark(this, t, s, r));
|
||||
this.bookmarksByTypeName =
|
||||
bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN);
|
||||
@ -61,17 +68,17 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
|
||||
|
||||
@Override
|
||||
public AddressSpace getAddressSpace() {
|
||||
return bookmarkMapSpace.getAddressSpace();
|
||||
return space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
return thread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) {
|
||||
|
@ -40,7 +40,7 @@ import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceBreakpointManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceBreakpointSpace, DBTraceBreakpointSpace>
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceBreakpointSpace>
|
||||
implements TraceBreakpointManager, DBTraceDelegatingManager<DBTraceBreakpointSpace> {
|
||||
protected static final String NAME = "Breakpoint";
|
||||
|
||||
|
@ -67,7 +67,7 @@ public class DBTraceBreakpointSpace implements DBTraceSpaceBased {
|
||||
assert threadKey == -1; // No breakpoints on registers
|
||||
breakpointMapSpace =
|
||||
new DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint>(
|
||||
DBTraceBreakpoint.tableName(space, threadKey), factory, lock, space,
|
||||
DBTraceBreakpoint.tableName(space, threadKey), factory, lock, space, null, 0,
|
||||
DBTraceBreakpoint.class, (t, s, r) -> new DBTraceBreakpoint(this, t, s, r));
|
||||
breakpointsByPath =
|
||||
breakpointMapSpace.getUserIndex(String.class, DBTraceBreakpoint.PATH_COLUMN);
|
||||
|
@ -45,8 +45,8 @@ import ghidra.util.database.annot.*;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceRegisterContextManager extends
|
||||
AbstractDBTraceSpaceBasedManager<DBTraceRegisterContextSpace, DBTraceRegisterContextRegisterSpace>
|
||||
public class DBTraceRegisterContextManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceRegisterContextSpace>
|
||||
implements TraceRegisterContextManager,
|
||||
DBTraceDelegatingManager<DBTraceRegisterContextSpace> {
|
||||
public static final String NAME = "RegisterContext";
|
||||
@ -100,14 +100,14 @@ public class DBTraceRegisterContextManager extends
|
||||
@Override
|
||||
protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceRegisterContextSpace(this, dbh, space, ent);
|
||||
return new DBTraceRegisterContextSpace(this, dbh, space, ent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceRegisterContextRegisterSpace createRegisterSpace(AddressSpace space,
|
||||
protected DBTraceRegisterContextSpace createRegisterSpace(AddressSpace space,
|
||||
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
// TODO: Should I just forbid this? It doesn't seem sane. Then again, what do I know?
|
||||
return new DBTraceRegisterContextRegisterSpace(this, dbh, space, ent, thread);
|
||||
return new DBTraceRegisterContextSpace(this, dbh, space, ent, thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -132,7 +132,7 @@ public class DBTraceRegisterContextManager extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceRegisterContextRegisterSpace getRegisterContextRegisterSpace(TraceThread thread,
|
||||
public DBTraceRegisterContextSpace getRegisterContextRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -81,6 +81,8 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
||||
protected final DBTraceRegisterContextManager manager;
|
||||
protected final DBHandle dbh;
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final Language baseLanguage;
|
||||
protected final DBTrace trace;
|
||||
@ -91,10 +93,13 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
||||
new HashMap<>();
|
||||
|
||||
public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh,
|
||||
AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
|
||||
throws VersionException, IOException {
|
||||
this.manager = manager;
|
||||
this.dbh = dbh;
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = ent.getFrameLevel();
|
||||
this.lock = manager.getLock();
|
||||
this.baseLanguage = manager.getBaseLanguage();
|
||||
this.trace = manager.getTrace();
|
||||
@ -129,7 +134,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
return thread;
|
||||
}
|
||||
|
||||
protected long getThreadKey() {
|
||||
@ -139,7 +144,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
protected String tableName(Language language, Register register) {
|
||||
@ -152,7 +157,8 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
||||
String name = tableName(lr.getLeft(), lr.getRight());
|
||||
try {
|
||||
return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(),
|
||||
lock, space, DBTraceRegisterContextEntry.class, DBTraceRegisterContextEntry::new);
|
||||
lock, space, thread, frameLevel, DBTraceRegisterContextEntry.class,
|
||||
DBTraceRegisterContextEntry::new);
|
||||
}
|
||||
catch (IOException e) {
|
||||
manager.dbError(e);
|
||||
|
@ -159,29 +159,8 @@ public class DBTraceDataSettingsAdapter
|
||||
DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
|
||||
implements DBTraceDataSettingsOperations {
|
||||
public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
|
||||
ReadWriteLock lock, AddressSpace space, Class<DBTraceSettingsEntry> dataType,
|
||||
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
|
||||
throws VersionException, IOException {
|
||||
super(tableName, storeFactory, lock, space, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeWay(DBTraceSettingsEntry entry, Range<Long> span) {
|
||||
DBTraceUtils.makeWay(entry, span, (e, s) -> e.setLifespan(s), e -> deleteData(e));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadWriteLock getLock() {
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
public class DBTraceDataSettingsRegisterSpace extends
|
||||
DBTraceAddressSnapRangePropertyMapRegisterSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
|
||||
implements DBTraceDataSettingsOperations {
|
||||
public DBTraceDataSettingsRegisterSpace(String tableName,
|
||||
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
|
||||
TraceThread thread, int frameLevel, Class<DBTraceSettingsEntry> dataType,
|
||||
ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
|
||||
Class<DBTraceSettingsEntry> dataType,
|
||||
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
|
||||
throws VersionException, IOException {
|
||||
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
|
||||
@ -206,20 +185,20 @@ public class DBTraceDataSettingsAdapter
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
protected DBTraceDataSettingsSpace createSpace(
|
||||
AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceDataSettingsSpace(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()),
|
||||
trace.getStoreFactory(), lock, space, dataType, dataFactory);
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, null, 0, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceDataSettingsRegisterSpace createRegisterSpace(AddressSpace space,
|
||||
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceDataSettingsRegisterSpace(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()),
|
||||
trace.getStoreFactory(), lock, space, thread, ent.getFrameLevel(), dataType,
|
||||
dataFactory);
|
||||
protected DBTraceDataSettingsSpace createRegisterSpace(
|
||||
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceDataSettingsSpace(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -228,9 +207,9 @@ public class DBTraceDataSettingsAdapter
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceDataSettingsRegisterSpace getRegisterSpace(TraceThread thread,
|
||||
public DBTraceDataSettingsSpace getRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return (DBTraceDataSettingsRegisterSpace) super.getRegisterSpace(thread, createIfAbsent);
|
||||
return (DBTraceDataSettingsSpace) super.getRegisterSpace(thread, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,42 +28,126 @@ import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.space.DBTraceDelegatingManager;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.LockHold;
|
||||
|
||||
/**
|
||||
* An abstract implementation of {@link TraceBaseCodeUnitsView} for composing views of many address
|
||||
* spaces
|
||||
*
|
||||
* @param <T> the implementation type of the units contained in the view
|
||||
* @param <M> the implementation type of the views being composed
|
||||
*/
|
||||
public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>>
|
||||
implements DBTraceDelegatingManager<M> {
|
||||
protected final DBTraceCodeManager manager;
|
||||
protected final Collection<M> activeSpacesView;
|
||||
|
||||
/**
|
||||
* Construct a composite view
|
||||
*
|
||||
* @param manager the code manager, from which individual views are retrieved
|
||||
*/
|
||||
public AbstractBaseDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
|
||||
this.manager = manager;
|
||||
this.activeSpacesView =
|
||||
Collections2.transform(manager.getActiveMemorySpaces(), this::getView);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getTrace()
|
||||
*/
|
||||
public Trace getTrace() {
|
||||
return manager.getTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getThread()
|
||||
*/
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getFrameLevel()
|
||||
*/
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the individual view from the given space
|
||||
*
|
||||
* @param space the space, bound to a specific address space
|
||||
* @return the view
|
||||
*/
|
||||
protected abstract M getView(DBTraceCodeSpace space);
|
||||
|
||||
/**
|
||||
* Create the appropriate unit (possibly caching) when there is no view or space for the given
|
||||
* address's space
|
||||
*
|
||||
* <p>
|
||||
* Views composing undefined units should generate (possibly delegating to a view) an undefined
|
||||
* unit. Others should leave this null.
|
||||
*
|
||||
* @param snap the snap the client requested
|
||||
* @param address the address the client requested
|
||||
* @return the unit or null
|
||||
*/
|
||||
protected T nullOrUndefined(long snap, Address address) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The address set when there is no view or space for the given range's space
|
||||
*
|
||||
* <p>
|
||||
* Views composing undefined units should return the whole range. Others should leave this
|
||||
* empty.
|
||||
*
|
||||
* @param within the range the client requested
|
||||
* @return the full range or empty
|
||||
*/
|
||||
protected AddressSetView emptyOrFullAddressSetUndefined(AddressRange within) {
|
||||
return new AddressSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* The result of contains, covers, or intersects when there is no view or space for an address
|
||||
* space
|
||||
*
|
||||
* <p>
|
||||
* Views composing undefined units should return true, since the address is known to be in an
|
||||
* unpopulated space. Others should leave this false.
|
||||
*
|
||||
* @return true if an undefined unit implicitly contains the address, false otherwise.
|
||||
*/
|
||||
protected boolean falseOrTrueUndefined() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The result of iteration when there is no view or space for the given range's space
|
||||
*
|
||||
* <p>
|
||||
* Views composing undefiend units should return an iterable that generates (possibly caching)
|
||||
* undefined units. Others should leave this empty.
|
||||
*
|
||||
* @param snap the snap the client requested
|
||||
* @param range the range of iteration
|
||||
* @param forward true to iterate forward (min to max), false for backward (max to min)
|
||||
* @return the iterator
|
||||
*/
|
||||
public Iterable<? extends T> emptyOrFullIterableUndefined(long snap, AddressRange range,
|
||||
boolean forward) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #emptyOrFullIterableUndefined(long, AddressRange, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> emptyOrFullIterableUndefined(TraceAddressSnapRange tasr) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -84,6 +168,16 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return codeSpace == null ? null : getView(codeSpace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the address preceding the given
|
||||
*
|
||||
* <p>
|
||||
* If this address is the minimum in its space, then this will choose the maximum address of the
|
||||
* previous space, if it exists.
|
||||
*
|
||||
* @param address the address
|
||||
* @return the previous address or null
|
||||
*/
|
||||
protected Address prevAddress(Address address) {
|
||||
Address prev = address.previous();
|
||||
if (prev != null) {
|
||||
@ -108,6 +202,15 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return prevRange.getMaxAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the address following the given
|
||||
*
|
||||
* <p>
|
||||
* If the address is the maximum in its space, then this will choose the minimum address of the
|
||||
* next space, if it exists.
|
||||
*
|
||||
* @return the next address or null
|
||||
*/
|
||||
protected Address nextAddress(Address address) {
|
||||
Address next = address.next();
|
||||
if (next != null) {
|
||||
@ -132,6 +235,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return nextRange.getMinAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#size()
|
||||
*/
|
||||
public int size() {
|
||||
int sum = 0;
|
||||
for (M m : activeSpacesView) {
|
||||
@ -140,6 +246,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getBefore(long, Address)
|
||||
*/
|
||||
public T getBefore(long snap, Address address) {
|
||||
Address prev = prevAddress(address);
|
||||
if (prev == null) {
|
||||
@ -148,6 +257,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return getFloor(snap, prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getFloor(long, Address)
|
||||
*/
|
||||
public T getFloor(long snap, Address address) {
|
||||
try (LockHold hold = LockHold.lock(readLock())) {
|
||||
for (AddressRange range : DBTraceUtils.getAddressSet(
|
||||
@ -163,6 +275,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getContaining(long, Address)
|
||||
*/
|
||||
public T getContaining(long snap, Address address) {
|
||||
try (LockHold hold = LockHold.lock(readLock())) {
|
||||
M m = getForSpace(address.getAddressSpace(), false);
|
||||
@ -173,6 +288,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAt(long, Address)
|
||||
*/
|
||||
public T getAt(long snap, Address address) {
|
||||
try (LockHold hold = LockHold.lock(readLock())) {
|
||||
M m = getForSpace(address.getAddressSpace(), false);
|
||||
@ -183,6 +301,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getCeiling(long, Address)
|
||||
*/
|
||||
public T getCeiling(long snap, Address address) {
|
||||
try (LockHold hold = LockHold.lock(readLock())) {
|
||||
for (AddressRange range : DBTraceUtils.getAddressSet(
|
||||
@ -198,6 +319,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAfter(long, Address)
|
||||
*/
|
||||
public T getAfter(long snap, Address address) {
|
||||
Address next = nextAddress(address);
|
||||
if (next == null) {
|
||||
@ -206,6 +330,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return getCeiling(snap, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, Address, Address, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, Address min, Address max, boolean forward) {
|
||||
if (min.hasSameAddressSpace(max)) {
|
||||
return get(snap, new AddressRangeImpl(min, max), forward);
|
||||
@ -214,11 +341,17 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, AddressSetView, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) {
|
||||
return () -> NestedIterator.start(set.iterator(forward),
|
||||
r -> get(snap, r, forward).iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, AddressRange, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) {
|
||||
M m = getForSpace(range.getAddressSpace(), false);
|
||||
if (m == null) {
|
||||
@ -227,15 +360,24 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return m.get(snap, range, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, Address, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, Address start, boolean forward) {
|
||||
AddressFactory factory = manager.getBaseLanguage().getAddressFactory();
|
||||
return get(snap, DBTraceUtils.getAddressSet(factory, start, forward), forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, boolean forward) {
|
||||
return get(snap, manager.getBaseLanguage().getAddressFactory().getAddressSet(), forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getIntersecting(TraceAddressSnapRange)
|
||||
*/
|
||||
public Iterable<? extends T> getIntersecting(TraceAddressSnapRange tasr) {
|
||||
M m = getForSpace(tasr.getX1().getAddressSpace(), false);
|
||||
if (m == null) {
|
||||
@ -244,6 +386,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return m.getIntersecting(tasr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAddressSetView(long, AddressRange)
|
||||
*/
|
||||
public AddressSetView getAddressSetView(long snap, AddressRange within) {
|
||||
M m = getForSpace(within.getAddressSpace(), false);
|
||||
if (m == null) {
|
||||
@ -252,6 +397,9 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return m.getAddressSetView(snap, within);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAddressSetView(long)
|
||||
*/
|
||||
public AddressSetView getAddressSetView(long snap) {
|
||||
AddressSet result = new AddressSet();
|
||||
for (AddressRange range : manager.getBaseLanguage().getAddressFactory().getAddressSet()) {
|
||||
@ -266,26 +414,41 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView<T extends DBTraceCo
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#containsAddress(long, Address)
|
||||
*/
|
||||
public boolean containsAddress(long snap, Address address) {
|
||||
return delegateRead(address.getAddressSpace(), m -> m.containsAddress(snap, address),
|
||||
falseOrTrueUndefined());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#coversRange(Range, AddressRange)
|
||||
*/
|
||||
public boolean coversRange(Range<Long> span, AddressRange range) {
|
||||
return delegateRead(range.getAddressSpace(), m -> m.coversRange(span, range),
|
||||
falseOrTrueUndefined());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#coversRange(TraceAddressSnapRange)
|
||||
*/
|
||||
public boolean coversRange(TraceAddressSnapRange range) {
|
||||
return delegateRead(range.getRange().getAddressSpace(), m -> m.coversRange(range),
|
||||
falseOrTrueUndefined());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#intersectsRange(Range, AddressRange)
|
||||
*/
|
||||
public boolean intersectsRange(Range<Long> span, AddressRange range) {
|
||||
return delegateRead(range.getAddressSpace(), m -> m.intersectsRange(span, range),
|
||||
falseOrTrueUndefined());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#intersectsRange(TraceAddressSnapRange)
|
||||
*/
|
||||
public boolean intersectsRange(TraceAddressSnapRange range) {
|
||||
return delegateRead(range.getRange().getAddressSpace(), m -> m.intersectsRange(range),
|
||||
falseOrTrueUndefined());
|
||||
|
@ -21,21 +21,70 @@ import generic.NestedIterator;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a {@link TraceBaseCodeUnitsView} for a specific address space
|
||||
*
|
||||
* <p>
|
||||
* Note that this class does not declare {@link TraceBaseCodeUnitsView} as an implemented interface,
|
||||
* thought it does implement it structurally. If it were implemented nominally, the realizations
|
||||
* would inherit the same interface twice, with different type parameters, which is not allowed.
|
||||
*
|
||||
* @param <T> the implementation type of the units contained in the view
|
||||
*/
|
||||
public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter> {
|
||||
|
||||
protected final DBTraceCodeSpace space;
|
||||
|
||||
/**
|
||||
* Construct a view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public AbstractBaseDBTraceCodeUnitsView(DBTraceCodeSpace space) {
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address space for this view
|
||||
*
|
||||
* @return the address space
|
||||
*/
|
||||
protected AddressSpace getAddressSpace() {
|
||||
return space.space;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getTrace()
|
||||
*/
|
||||
public Trace getTrace() {
|
||||
return space.manager.getTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getThread()
|
||||
*/
|
||||
public TraceThread getThread() {
|
||||
return space.getThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getFrameLevel()
|
||||
*/
|
||||
public int getFrameLevel() {
|
||||
return space.getFrameLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#size()
|
||||
*/
|
||||
public abstract int size();
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getBefore(long, Address)
|
||||
*/
|
||||
public T getBefore(long snap, Address address) {
|
||||
Address previous = address.previous();
|
||||
if (previous == null) {
|
||||
@ -44,14 +93,29 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
|
||||
return getFloor(snap, previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getFloor(long, Address)
|
||||
*/
|
||||
public abstract T getFloor(long snap, Address address);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getContaining(long, Address)
|
||||
*/
|
||||
public abstract T getContaining(long snap, Address address);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAt(long, Address)
|
||||
*/
|
||||
public abstract T getAt(long snap, Address address);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getCeiling(long, Address)
|
||||
*/
|
||||
public abstract T getCeiling(long snap, Address address);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAfter(long, Address)
|
||||
*/
|
||||
public T getAfter(long snap, Address address) {
|
||||
Address next = address.next();
|
||||
if (next == null) {
|
||||
@ -60,50 +124,85 @@ public abstract class AbstractBaseDBTraceCodeUnitsView<T extends DBTraceCodeUnit
|
||||
return getCeiling(snap, next);
|
||||
}
|
||||
|
||||
public AddressSpace getAddressSpace() {
|
||||
return space.space;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, Address, Address, boolean)
|
||||
*/
|
||||
public abstract Iterable<? extends T> get(long snap, Address min, Address max, boolean forward);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getIntersecting(TraceAddressSnapRange)
|
||||
*/
|
||||
public abstract Iterable<? extends T> getIntersecting(TraceAddressSnapRange tasr);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, AddressSetView, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, AddressSetView set, boolean forward) {
|
||||
return () -> NestedIterator.start(set.iterator(forward),
|
||||
r -> this.get(snap, r, forward).iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, AddressRange, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, AddressRange range, boolean forward) {
|
||||
return get(snap, range.getMinAddress(), range.getMaxAddress(), forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, Address, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, Address start, boolean forward) {
|
||||
return forward //
|
||||
? get(snap, start, getAddressSpace().getMaxAddress(), forward)
|
||||
: get(snap, getAddressSpace().getMinAddress(), start, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#get(long, boolean)
|
||||
*/
|
||||
public Iterable<? extends T> get(long snap, boolean forward) {
|
||||
return get(snap, getAddressSpace().getMinAddress(), getAddressSpace().getMaxAddress(),
|
||||
forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAddressSetView(long, AddressRange)
|
||||
*/
|
||||
public abstract AddressSetView getAddressSetView(long snap, AddressRange within);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#getAddressSetView(long)
|
||||
*/
|
||||
public AddressSetView getAddressSetView(long snap) {
|
||||
return getAddressSetView(snap, space.all);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#containsAddress(long, Address)
|
||||
*/
|
||||
public abstract boolean containsAddress(long snap, Address address);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#coversRange(Range, AddressRange)
|
||||
*/
|
||||
public abstract boolean coversRange(Range<Long> span, AddressRange range);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#coversRange(TraceAddressSnapRange)
|
||||
*/
|
||||
public boolean coversRange(TraceAddressSnapRange range) {
|
||||
return coversRange(range.getLifespan(), range.getRange());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#intersectsRange(Range, AddressRange)
|
||||
*/
|
||||
public abstract boolean intersectsRange(Range<Long> span, AddressRange range);
|
||||
|
||||
/**
|
||||
* @see TraceBaseCodeUnitsView#intersectsRange(TraceAddressSnapRange)
|
||||
*/
|
||||
public boolean intersectsRange(TraceAddressSnapRange range) {
|
||||
return intersectsRange(range.getLifespan(), range.getRange());
|
||||
}
|
||||
|
@ -31,12 +31,23 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAdd
|
||||
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.Trace.TraceCodeChangeType;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceBaseDefinedUnitsView;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.database.spatial.rect.Rectangle2DDirection;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a single-type view for a defined unit type
|
||||
*
|
||||
* <p>
|
||||
* This is <em>note</em> a base class of {@link DBTraceDefinedUnitsView}. This class supports the
|
||||
* implementation of one or the other: Instruction or Defined data. {@link DBTraceDefinedUnitsView}
|
||||
* is the implementation of the composition of both.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTraceCodeUnit<T>>
|
||||
extends AbstractSingleDBTraceCodeUnitsView<T> {
|
||||
|
||||
@ -44,6 +55,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
protected final static int CACHE_ADDRESS_BREADTH = 10000;
|
||||
protected final static int CACHE_MAX_POINTS = 10000;
|
||||
|
||||
/**
|
||||
* Cache for optimizing {@link AbstractBaseDBTraceDefinedUnitsView#getAt(long, Address)}
|
||||
*/
|
||||
protected class CacheForGetUnitContainingQueries
|
||||
extends DBTraceCacheForContainingQueries<GetKey, T, T> {
|
||||
|
||||
@ -64,6 +78,10 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache for optimizing {@link AbstractBaseDBTraceDefinedUnitsView#getFloor(long, Address)} and
|
||||
* similar.
|
||||
*/
|
||||
protected class CacheForGetUnitSequenceQueries extends DBTraceCacheForSequenceQueries<T> {
|
||||
public CacheForGetUnitSequenceQueries() {
|
||||
super(CACHE_MAX_REGIONS, CACHE_ADDRESS_BREADTH);
|
||||
@ -104,6 +122,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
protected final CacheForGetUnitSequenceQueries cacheForSequence =
|
||||
new CacheForGetUnitSequenceQueries();
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
* @param mapSpace the map storing the actual code unit entries
|
||||
*/
|
||||
public AbstractBaseDBTraceDefinedUnitsView(DBTraceCodeSpace space,
|
||||
DBTraceAddressSnapRangePropertyMapSpace<T, T> mapSpace) {
|
||||
super(space);
|
||||
@ -121,6 +145,30 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
return !mapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract from cur, the boxes covered by the entries intersecting the given query box
|
||||
*
|
||||
* <p>
|
||||
* Compute C = A - B, where A B and C are sets of (possibly overlapping) boxes. A is given by
|
||||
* {@code} cur, and B is the set of bounding boxes for entries intersecting the query box. Two
|
||||
* temporary sets must be provided, and {@code cur} must be identical to one of them. This
|
||||
* routine will mutate them. The returned result will be identical to one of them.
|
||||
*
|
||||
* <p>
|
||||
* If repeated subtraction is needed, the temporary sets need only be constructed once. For each
|
||||
* subsequent round of subtraction, {@code cur} should be the returned result of the previous
|
||||
* round. The final result is the return value of the final round.
|
||||
*
|
||||
* <p>
|
||||
* This is used in the implementation of {@link #coversRange(TraceAddressSnapRange)}.
|
||||
*
|
||||
* @param span the lifespan of the query box
|
||||
* @param range the address range of the query box
|
||||
* @param cur the set of boxes, identical to one of the temporary working sets.
|
||||
* @param set1 a temporary set for working
|
||||
* @param set2 a temporary set for working
|
||||
* @return the result of subtraction, identical to one of the temporary working sets
|
||||
*/
|
||||
protected Set<TraceAddressSnapRange> subtractFrom(Range<Long> span, AddressRange range,
|
||||
Set<TraceAddressSnapRange> cur, Set<TraceAddressSnapRange> set1,
|
||||
Set<TraceAddressSnapRange> set2) {
|
||||
@ -239,6 +287,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
t -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the register context in the given box
|
||||
*
|
||||
* @param span the lifespan of the box
|
||||
* @param range the address range of the box
|
||||
*/
|
||||
protected void clearContext(Range<Long> span, AddressRange range) {
|
||||
DBTraceRegisterContextSpace ctxSpace =
|
||||
space.trace.getRegisterContextManager().get(space, false);
|
||||
@ -248,6 +302,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
ctxSpace.clear(span, range);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TraceBaseDefinedUnitsView#clear(Range, AddressRange, boolean, TaskMonitor)
|
||||
*/
|
||||
public void clear(Range<Long> span, AddressRange range, boolean clearContext,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
long startSnap = DBTraceUtils.lowerEndpoint(span);
|
||||
@ -275,6 +332,11 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify domain object listeners that a unit was removed
|
||||
*
|
||||
* @param unit the removed unit
|
||||
*/
|
||||
protected void unitRemoved(T unit) {
|
||||
cacheForContaining.notifyEntryRemoved(unit.getLifespan(), unit.getRange(), unit);
|
||||
cacheForSequence.notifyEntryRemoved(unit.getLifespan(), unit.getRange(), unit);
|
||||
@ -283,6 +345,12 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
space, unit.getBounds(), unit, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify domain object listeners taht a unit's lifespan changed
|
||||
*
|
||||
* @param oldSpan the old snap
|
||||
* @param unit the unit (having the new span)
|
||||
*/
|
||||
protected void unitSpanChanged(Range<Long> oldSpan, T unit) {
|
||||
cacheForContaining.notifyEntryShapeChanged(unit.getLifespan(), unit.getRange(), unit);
|
||||
cacheForSequence.notifyEntryShapeChanged(unit.getLifespan(), unit.getRange(), unit);
|
||||
@ -291,6 +359,18 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
space, unit, oldSpan, unit.getLifespan()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a sub-lifespan from that given so that the box does not overlap an existing unit
|
||||
*
|
||||
* <p>
|
||||
* The selected lifespan will have the same start snap at that given. The box is the bounding
|
||||
* box of a unit the client is trying to create.
|
||||
*
|
||||
* @param span the lifespan of the box
|
||||
* @param range the address range of the box
|
||||
* @return the selected sub-lifespan
|
||||
* @throws CodeUnitInsertionException if the start snap is contained in an existing unit
|
||||
*/
|
||||
protected Range<Long> truncateSoonestDefined(Range<Long> span, AddressRange range)
|
||||
throws CodeUnitInsertionException {
|
||||
T truncateBy =
|
||||
@ -308,6 +388,9 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView<T extends AbstractDBTr
|
||||
truncateBy.getStartSnap() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the query-optimizing caches for this view
|
||||
*/
|
||||
public void invalidateCache() {
|
||||
cacheForContaining.invalidate();
|
||||
cacheForSequence.invalidate();
|
||||
|
@ -26,20 +26,46 @@ import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceCodeUnit;
|
||||
import ghidra.util.*;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a multi-type view, by composing other single-type views
|
||||
*
|
||||
* @param <T> the implementation type of units contained in the view
|
||||
* @param <P> the implementation type of views composed by this view
|
||||
*/
|
||||
public abstract class AbstractComposedDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter, //
|
||||
P extends AbstractSingleDBTraceCodeUnitsView<? extends T>>
|
||||
extends AbstractBaseDBTraceCodeUnitsView<T> {
|
||||
|
||||
/**
|
||||
* Compare two code units for forward iteration
|
||||
*
|
||||
* @param a a code unit
|
||||
* @param b a code unit
|
||||
* @return as in {@link Comparable#compareTo(Object)}
|
||||
*/
|
||||
protected static int compareForward(TraceCodeUnit a, TraceCodeUnit b) {
|
||||
return a.getMinAddress().compareTo(b.getMinAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two code units for backward iteration
|
||||
*
|
||||
* @param a a code unit
|
||||
* @param b a code unit
|
||||
* @return as in {@link Comparable#compareTo(Object)}
|
||||
*/
|
||||
protected static int compareBackward(TraceCodeUnit a, TraceCodeUnit b) {
|
||||
return b.getMaxAddress().compareTo(a.getMaxAddress());
|
||||
}
|
||||
|
||||
protected final Collection<P> parts;
|
||||
|
||||
/**
|
||||
* Construct a view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
* @param parts the single-type views composed
|
||||
*/
|
||||
public AbstractComposedDBTraceCodeUnitsView(DBTraceCodeSpace space, Collection<P> parts) {
|
||||
super(space);
|
||||
this.parts = parts;
|
||||
|
@ -29,6 +29,15 @@ import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.database.DBCachedObjectStore;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a table-backed code unit
|
||||
*
|
||||
* <p>
|
||||
* This is implemented as a data entry in an address-snap-range property map. This is not suitable
|
||||
* for data components, nor for undefined units.
|
||||
*
|
||||
* @param <T> the implementation type of this unit
|
||||
*/
|
||||
public abstract class AbstractDBTraceCodeUnit<T extends AbstractDBTraceCodeUnit<T>> extends
|
||||
AbstractDBTraceAddressSnapRangePropertyMapData<T> implements DBTraceCodeUnitAdapter {
|
||||
|
||||
@ -36,6 +45,14 @@ public abstract class AbstractDBTraceCodeUnit<T extends AbstractDBTraceCodeUnit<
|
||||
|
||||
protected ByteBuffer byteCache; // NOTE: Memory cannot be changed under a code unit
|
||||
|
||||
/**
|
||||
* Construct a code unit
|
||||
*
|
||||
* @param space the space
|
||||
* @param tree the storage R*-Tree
|
||||
* @param store the object store
|
||||
* @param record the record
|
||||
*/
|
||||
public AbstractDBTraceCodeUnit(DBTraceCodeSpace space,
|
||||
DBTraceAddressSnapRangePropertyMapTree<T, ?> tree, DBCachedObjectStore<?> store,
|
||||
DBRecord record) {
|
||||
|
@ -26,9 +26,19 @@ import ghidra.program.model.lang.Language;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.data.DBTraceDataSettingsAdapter.DBTraceDataSettingsSpace;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.listing.TraceData;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.LockHold;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a {@link TraceData} for a data component, i.e., field of a struct
|
||||
* or element of an array
|
||||
*
|
||||
* <p>
|
||||
* These are not backed directly by a table. The root data unit, along with its type, is stored in
|
||||
* the table. If the type is composite, then these are generated, possibly recursively, for the
|
||||
* components therein.
|
||||
*/
|
||||
public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedDataAdapter {
|
||||
|
||||
protected final DBTraceData root;
|
||||
@ -47,6 +57,16 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
|
||||
|
||||
protected AbstractDBTraceDataComponent[] componentCache = null;
|
||||
|
||||
/**
|
||||
* Create a data component
|
||||
*
|
||||
* @param root the root data unit
|
||||
* @param parent the parent component, possibly the root
|
||||
* @param index the index of this component in its parent
|
||||
* @param address the minimum address of this component
|
||||
* @param dataType the data type of this component
|
||||
* @param length the length of this component
|
||||
*/
|
||||
public AbstractDBTraceDataComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
|
||||
int index, Address address, DataType dataType, int length) {
|
||||
this.root = root;
|
||||
@ -173,6 +193,7 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* In other words, this includes the symbol name of the root unit; whereas,
|
||||
* {@link #getComponentPathName()} omits it.
|
||||
*/
|
||||
@ -184,6 +205,7 @@ public abstract class AbstractDBTraceDataComponent implements DBTraceDefinedData
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* In other words, this omits the symbol name of the root unit; whereas, {@link #getPathName()}
|
||||
* includes it.
|
||||
*/
|
||||
|
@ -15,9 +15,22 @@
|
||||
*/
|
||||
package ghidra.trace.database.listing;
|
||||
|
||||
/**
|
||||
* An abstract implementation of a single-type view
|
||||
*
|
||||
* @implNote This class cannot be removed. Despite it appearing not to do anything, this class
|
||||
* serves as an upper bound on the views composed by
|
||||
* {@link AbstractComposedDBTraceCodeUnitsView}.
|
||||
* @param <T> the implementation type of the units contained in the view
|
||||
*/
|
||||
public abstract class AbstractSingleDBTraceCodeUnitsView<T extends DBTraceCodeUnitAdapter>
|
||||
extends AbstractBaseDBTraceCodeUnitsView<T> {
|
||||
|
||||
/**
|
||||
* Construct a view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public AbstractSingleDBTraceCodeUnitsView(DBTraceCodeSpace space) {
|
||||
super(space);
|
||||
}
|
||||
|
@ -22,16 +22,24 @@ import com.google.common.collect.Iterators;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceBaseCodeUnitsView;
|
||||
|
||||
/**
|
||||
* TODO: Document me
|
||||
* An abstract implementation of {@link TraceBaseCodeUnitsView} for composing views of many address
|
||||
* spaces, where the views include undefined units
|
||||
*
|
||||
* @param <T> type of units in the view. Must be a super-type of {@link UndefinedDBTraceData}.
|
||||
* @param <M>
|
||||
* @param <T> the implementation type of the units contained in the view. Must be a super-type of
|
||||
* {@link UndefinedDBTraceData}.
|
||||
* @param <M> the implementation type of the views being composed
|
||||
*/
|
||||
public abstract class AbstractWithUndefinedDBTraceCodeUnitsMemoryView<T extends DBTraceCodeUnitAdapter, M extends AbstractBaseDBTraceCodeUnitsView<T>>
|
||||
extends AbstractBaseDBTraceCodeUnitsMemoryView<T, M> {
|
||||
|
||||
/**
|
||||
* Construct a composite view
|
||||
*
|
||||
* @param manager the code manager, from which individual views are retrieved
|
||||
*/
|
||||
public AbstractWithUndefinedDBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ import db.DBRecord;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.ContextChangeException;
|
||||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.ByteMemBufferImpl;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.util.ProgramContextImpl;
|
||||
@ -52,8 +51,7 @@ import ghidra.trace.database.symbol.DBTraceReferenceManager;
|
||||
import ghidra.trace.database.thread.DBTraceThreadManager;
|
||||
import ghidra.trace.model.AddressSnap;
|
||||
import ghidra.trace.model.DefaultAddressSnap;
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.listing.*;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
@ -64,8 +62,119 @@ import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceCodeManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceCodeSpace, DBTraceCodeRegisterSpace>
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager} for {@link DBTrace}
|
||||
*
|
||||
* <p>
|
||||
* The "fluent" interfaces actually create quite a burden to implement here; however, we have some
|
||||
* opportunity to extract common code among the various views. There are a few concepts and nuances
|
||||
* to consider in order to handle all the fluent cases. The manager implements
|
||||
* {@link TraceCodeOperations} directly, which means it must provide a version of each
|
||||
* {@link TraceCodeUnitsView} that composes all memory address spaces. These are named with the
|
||||
* suffix {@code MemoryView} and extend {@link AbstractBaseDBTraceCodeUnitsMemoryView}.
|
||||
*
|
||||
* <p>
|
||||
* In addition, in order to support {@link #getCodeSpace(AddressSpace, boolean)}, it must provide a
|
||||
* version of each that can be bound to a single memory address space. Same for
|
||||
* {@link #getCodeRegisterSpace(TraceThread, int, boolean)}. These are named with the suffix
|
||||
* {@code View} and extend {@link AbstractBaseDBTraceCodeUnitsView}.
|
||||
*
|
||||
* <p>
|
||||
* Furthermore, there are three types of views:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Those defined by a table, i.e., defined data and instructions. These extend
|
||||
* {@link AbstractBaseDBTraceDefinedUnitsView}.</li>
|
||||
* <li>Those defined implicitly, but may have a support table, i.e., undefined units. This is
|
||||
* implemented by {@link DBTraceUndefinedDataView}.</li>
|
||||
* <li>Those defined as the composition of others, i.e., data and defined units. These extend
|
||||
* {@link AbstractComposedDBTraceCodeUnitsView}.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
* The first two types represent a view of a single code unit type, so they both extend
|
||||
* {@link AbstractSingleDBTraceCodeUnitsView}.
|
||||
*
|
||||
* <p>
|
||||
* The abstract classes do not nominally implement the trace manager's
|
||||
* {@link TraceBaseCodeUnitsView} nor {@link TraceBaseDefinedUnitsView} interfaces, because Java
|
||||
* prevents the (nominal) implementation of the same interface with different type parameters by the
|
||||
* same class. E.g., {@link DBTraceDataView} would inherit
|
||||
* {@code TraceBaseCodeUnitsView<DBTraceData>} via {@link AbstractBaseDBTraceCodeUnitsView}, but
|
||||
* also {@code TraceBaseCodeUnitsView<TraceDataUnit>} via {@link TraceDataView}. Instead, the
|
||||
* abstract classes <em>structurally</em> implement those interfaces, meaning they implement the
|
||||
* methods required by the interface, but without naming the interface in their `implements` clause.
|
||||
* The realizations, e.g., {@link DBTraceDataView}, <em>nominally</em> implement their corresponding
|
||||
* interfaces, meaning they do name the interface. Each realization will inherit the structural
|
||||
* implementation from the abstract classes, satisfying the requirements imposed by nominally
|
||||
* implementing the interface.
|
||||
*
|
||||
* <p>
|
||||
* Note, as a result, navigating from declarations in the interfaces to implementations in abstract
|
||||
* classes using your IDE may not work as expected :/ . The best way is probably to display the type
|
||||
* hierarchy of the interface declaring the desired method. Open one of the classes implementing it,
|
||||
* then display all its methods, including those inherited, and search for desired method.
|
||||
*
|
||||
* <p>
|
||||
* Here is the type hierarchy presented with notes regarding structural interface implementations:
|
||||
* <ul>
|
||||
* <li>{@link AbstractBaseDBTraceCodeUnitsView} structurally implements
|
||||
* {@link TraceBaseCodeUnitsView}</li>
|
||||
* <ul>
|
||||
* <li>{@link AbstractComposedDBTraceCodeUnitsView}</li>
|
||||
* <ul>
|
||||
* <li>{@link DBTraceCodeUnitsView} nominally implements {@link TraceCodeUnitsView}</li>
|
||||
* <li>{@link DBTraceDataView} nominally implements {@link TraceDataView}</li>
|
||||
* <li>{@link DBTraceDefinedUnitsView} nominally implements {@link TraceDefinedUnitsView}</li>
|
||||
* </ul>
|
||||
* <li>{@link AbstractSingleDBTraceCodeUnitsView}</li>
|
||||
* <ul>
|
||||
* <li>{@link AbstractBaseDBTraceDefinedUnitsView} structurally implements
|
||||
* {@link TraceBaseDefinedUnitsView}</li>
|
||||
* <ul>
|
||||
* <li>{@link DBTraceDefinedDataView} nominally implements {@link TraceDefinedDataView}</li>
|
||||
* <li>{@link DBTraceInstructionsView} nominally implements {@link TraceInstructionsView}</li>
|
||||
* </ul>
|
||||
* <li>{@link DBTraceUndefinedDataView} nominally implements {@link TraceUndefinedDataView}</li>
|
||||
* </ul>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The view composition is not hierarchical, as each may represent a different combination, and one
|
||||
* type may appear in several compositions. The single-type views are named first, then the composed
|
||||
* views:
|
||||
* <ul>
|
||||
* <li>Instructions - single-type view</li>
|
||||
* <li>Defined Data - single-type view</li>
|
||||
* <li>Undefined Data - single-type view</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Note that while the API presents separate views for defined data and undefined units, both are
|
||||
* represented by the type {@link TraceData}. Meaning, a client with a data unit in hand cannot
|
||||
* determine whether it is defined or undefined from its type alone. It must invoke
|
||||
* {@link Data#isDefined()} instead. While the implementation provides a separate type, which we see
|
||||
* mirrors the hierarchy of the views' implementation, the client interfaces do not.
|
||||
*
|
||||
* <ul>
|
||||
* <li>Code Units - Instructions, Defined Data, Undefined Data</li>
|
||||
* <li>Data - Defined Data, Undefined Data</li>
|
||||
* <li>Defined Units - Instructions, Defined Data</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The {@code MemoryView} classes compose the memory address spaces into a single view. These need
|
||||
* not mirror the same implementation hierarchy as the views they compose. Other than special
|
||||
* handling for compositions including undefined units, each memory view need not know anything
|
||||
* about the views it composes. There are two abstract classes:
|
||||
* {@link AbstractBaseDBTraceCodeUnitsMemoryView}, which is suitable for composing views without
|
||||
* undefined units, and {@link AbstractWithUndefinedDBTraceCodeUnitsMemoryView}, which extends the
|
||||
* base making it suitable for composing views with undefined units. The realizations each extend
|
||||
* from the appropriate abstract class. Again, the abstract classes do not nominally implement
|
||||
* {@link TraceBaseCodeUnitsView}. They structurally implement it, partly satisfying the
|
||||
* requirements on the realizations, which nominally implement their appropriate interfaces.
|
||||
*/
|
||||
public class DBTraceCodeManager extends AbstractDBTraceSpaceBasedManager<DBTraceCodeSpace>
|
||||
implements TraceCodeManager, DBTraceDelegatingManager<DBTraceCodeSpace> {
|
||||
public static final String NAME = "Code";
|
||||
|
||||
@ -302,13 +411,13 @@ public class DBTraceCodeManager
|
||||
@Override
|
||||
protected DBTraceCodeSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceCodeSpace(this, dbh, space, ent);
|
||||
return new DBTraceCodeSpace(this, dbh, space, ent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceCodeRegisterSpace createRegisterSpace(AddressSpace space, TraceThread thread,
|
||||
protected DBTraceCodeSpace createRegisterSpace(AddressSpace space, TraceThread thread,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceCodeRegisterSpace(this, dbh, space, ent, thread);
|
||||
return new DBTraceCodeSpace(this, dbh, space, ent, thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -337,19 +446,19 @@ public class DBTraceCodeManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceThread thread,
|
||||
public DBTraceCodeSpace getCodeRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceThread thread, int frameLevel,
|
||||
public DBTraceCodeSpace getCodeRegisterSpace(TraceThread thread, int frameLevel,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, frameLevel, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceCodeRegisterSpace getCodeRegisterSpace(TraceStackFrame frame,
|
||||
public DBTraceCodeSpace getCodeRegisterSpace(TraceStackFrame frame,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame, createIfAbsent);
|
||||
}
|
||||
@ -378,7 +487,7 @@ public class DBTraceCodeManager
|
||||
for (DBTraceCodeSpace codeSpace : memSpaces.values()) {
|
||||
codeSpace.clearPlatform(Range.all(), codeSpace.all, guest, monitor);
|
||||
}
|
||||
for (DBTraceCodeRegisterSpace codeSpace : regSpaces.values()) {
|
||||
for (DBTraceCodeSpace codeSpace : regSpaces.values()) {
|
||||
// TODO: I don't know any way to get guest instructions into register space
|
||||
// The mapping manager does (should) not allow guest register addresses
|
||||
// TODO: Test this if I ever get guest data units
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpace
|
||||
import ghidra.trace.database.space.DBTraceSpaceBased;
|
||||
import ghidra.trace.database.symbol.DBTraceReferenceManager;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.ByteArrayUtils;
|
||||
@ -48,10 +49,19 @@ import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A space managed by the {@link DBTraceCodeManager}
|
||||
*
|
||||
* <p>
|
||||
* This implements {@link TraceCodeManager#getCodeSpace(AddressSpace, boolean)} and
|
||||
* {@link TraceCodeManager#getCodeRegisterSpace(TraceThread, int, boolean)}.
|
||||
*/
|
||||
public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
|
||||
protected final DBTraceCodeManager manager;
|
||||
protected final DBHandle dbh;
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final Language baseLanguage;
|
||||
protected final DBTrace trace;
|
||||
@ -70,11 +80,24 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
|
||||
protected DBTraceDefinedUnitsView definedUnits;
|
||||
protected DBTraceCodeUnitsView codeUnits;
|
||||
|
||||
/**
|
||||
* Construct a space
|
||||
*
|
||||
* @param manager the manager
|
||||
* @param dbh the database handle
|
||||
* @param space the address space
|
||||
* @param ent an entry describing this space
|
||||
* @param thread a thread, if applicable, for a per-thread/frame space
|
||||
* @throws VersionException if there is already a table of a different version
|
||||
* @throws IOException if there is trouble accessing the database
|
||||
*/
|
||||
public DBTraceCodeSpace(DBTraceCodeManager manager, DBHandle dbh, AddressSpace space,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
|
||||
this.manager = manager;
|
||||
this.dbh = dbh;
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = ent.getFrameLevel();
|
||||
this.lock = manager.getLock();
|
||||
this.baseLanguage = manager.getBaseLanguage();
|
||||
this.trace = manager.getTrace();
|
||||
@ -88,10 +111,10 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
|
||||
int frameLevel = ent.getFrameLevel();
|
||||
|
||||
instructionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceInstruction.tableName(space, threadKey), factory, lock, space,
|
||||
DBTraceInstruction.tableName(space, threadKey), factory, lock, space, null, 0,
|
||||
DBTraceInstruction.class, (t, s, r) -> new DBTraceInstruction(this, t, s, r));
|
||||
dataMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceData.tableName(space, threadKey, frameLevel), factory, lock, space,
|
||||
DBTraceData.tableName(space, threadKey, frameLevel), factory, lock, space, null, 0,
|
||||
DBTraceData.class, (t, s, r) -> new DBTraceData(this, t, s, r));
|
||||
|
||||
instructions = createInstructionsView();
|
||||
@ -102,30 +125,57 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
|
||||
codeUnits = createCodeUnitsView(); // dep: instructions,definedData,undefinedData
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method for the instructions view
|
||||
*/
|
||||
protected DBTraceInstructionsView createInstructionsView() {
|
||||
return new DBTraceInstructionsView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method for the defined data view
|
||||
*/
|
||||
protected DBTraceDefinedDataView createDefinedDataView() {
|
||||
return new DBTraceDefinedDataView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method for the defined units view
|
||||
*/
|
||||
protected DBTraceDefinedUnitsView createDefinedUnitsView() {
|
||||
return new DBTraceDefinedUnitsView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method for the undefined data view
|
||||
*/
|
||||
protected DBTraceUndefinedDataView createUndefinedDataView() {
|
||||
return new DBTraceUndefinedDataView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method for the data view
|
||||
*/
|
||||
protected DBTraceDataView createDataView() {
|
||||
return new DBTraceDataView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method for the code units view
|
||||
*/
|
||||
protected DBTraceCodeUnitsView createCodeUnitsView() {
|
||||
return new DBTraceCodeUnitsView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all units belonging to the given guest platform
|
||||
*
|
||||
* @param span the lifespan
|
||||
* @param range the address range
|
||||
* @param guest the guest platform
|
||||
* @param monitor a monitor for progress
|
||||
* @throws CancelledException if the monitor was cancelled
|
||||
*/
|
||||
void clearPlatform(Range<Long> span, AddressRange range, DBTraceGuestPlatform guest,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
// Note "makeWay" does not apply here.
|
||||
@ -170,12 +220,12 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
return thread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -221,6 +271,20 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify this space that some bytes have changed
|
||||
*
|
||||
* <p>
|
||||
* If any unit(s) contained the changed bytes, they may need to be truncated, deleted, and/or
|
||||
* replaced. Instructions are generally truncated or deleted without replacement. A data unit
|
||||
* may be replaced if its length would match that of the original.
|
||||
*
|
||||
* @param changed the boxes whose bytes changed
|
||||
* @param snap the snap where the client requested the change
|
||||
* @param start the starting address where the client requested the change
|
||||
* @param oldBytes the old bytes
|
||||
* @param newBytes the new bytes
|
||||
*/
|
||||
public void bytesChanged(Set<TraceAddressSnapRange> changed, long snap, Address start,
|
||||
byte[] oldBytes, byte[] newBytes) {
|
||||
AddressSet diffs = ByteArrayUtils.computeDiffsAddressSet(start, oldBytes, newBytes);
|
||||
|
@ -44,6 +44,13 @@ import ghidra.util.Saveable;
|
||||
import ghidra.util.exception.NoValueException;
|
||||
import ghidra.util.prop.PropertyVisitor;
|
||||
|
||||
/**
|
||||
* A base interface for implementations of {@link TraceCodeUnit}
|
||||
*
|
||||
* <p>
|
||||
* This behaves somewhat like a mixin, allowing it to be used on code units as well as data
|
||||
* components, e.g., fields of a struct data unit.
|
||||
*/
|
||||
public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferAdapter {
|
||||
|
||||
@Override
|
||||
|
@ -16,11 +16,21 @@
|
||||
package ghidra.trace.database.listing;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceCodeUnitsView;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager#codeUnits()}
|
||||
*/
|
||||
public class DBTraceCodeUnitsMemoryView extends
|
||||
AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceCodeUnitAdapter, DBTraceCodeUnitsView>
|
||||
implements TraceCodeUnitsView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param manager the manager
|
||||
*/
|
||||
public DBTraceCodeUnitsMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -20,12 +20,21 @@ import java.util.List;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.listing.TraceCodeUnitsView;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeSpace#codeUnits()}
|
||||
*/
|
||||
public class DBTraceCodeUnitsView extends
|
||||
AbstractComposedDBTraceCodeUnitsView<DBTraceCodeUnitAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceCodeUnitAdapter>>
|
||||
implements TraceCodeUnitsView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public DBTraceCodeUnitsView(DBTraceCodeSpace space) {
|
||||
super(space, List.of(space.instructions, space.definedData, space.undefinedData));
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import db.DBRecord;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Listing;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.listing.DBTraceCommentAdapter.DBTraceCommentEntry;
|
||||
@ -46,12 +47,18 @@ import ghidra.util.database.annot.*;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A property map for storing code unit comments
|
||||
*/
|
||||
public class DBTraceCommentAdapter
|
||||
extends DBTraceAddressSnapRangePropertyMap<DBTraceCommentEntry, DBTraceCommentEntry> {
|
||||
protected static final String[] EMPTY_STRING_ARRAY = new String[] {};
|
||||
protected static final int MIN_COMMENT_TYPE = CodeUnit.EOL_COMMENT;
|
||||
protected static final int MAX_COMMENT_TYPE = CodeUnit.REPEATABLE_COMMENT;
|
||||
|
||||
/**
|
||||
* A comment entry
|
||||
*/
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
public static class DBTraceCommentEntry
|
||||
extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceCommentEntry> {
|
||||
@ -99,6 +106,9 @@ public class DBTraceCommentAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the adapter
|
||||
*/
|
||||
public DBTraceCommentAdapter(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
|
||||
DBTraceThreadManager threadManager) throws IOException, VersionException {
|
||||
@ -106,10 +116,27 @@ public class DBTraceCommentAdapter
|
||||
DBTraceCommentEntry.class, DBTraceCommentEntry::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or delete and existing comment entry
|
||||
*
|
||||
* <p>
|
||||
* It is assumed the entry intersects some implied address range.
|
||||
*
|
||||
* @param entry the entry to truncate or delete
|
||||
* @param span the span that must be clear
|
||||
*/
|
||||
protected void makeWay(DBTraceCommentEntry entry, Range<Long> span) {
|
||||
DBTraceUtils.makeWay(entry, span, (e, s) -> e.setLifespan(s), e -> deleteData(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a comment at the given address for the given lifespan
|
||||
*
|
||||
* @param lifespan the lifespan
|
||||
* @param address the address
|
||||
* @param commentType the type of comment as in {@link Listing#setComment(Address, int, String)}
|
||||
* @param comment the comment
|
||||
*/
|
||||
public void setComment(Range<Long> lifespan, Address address, int commentType, String comment) {
|
||||
if (commentType < MIN_COMMENT_TYPE || commentType > MAX_COMMENT_TYPE) {
|
||||
throw new IllegalArgumentException("commentType");
|
||||
@ -138,14 +165,34 @@ public class DBTraceCommentAdapter
|
||||
oldValue, comment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a comment from an array of lines
|
||||
*
|
||||
* @param comment the lines or null
|
||||
* @return the comment text or null
|
||||
*/
|
||||
public static String commentFromArray(String[] comment) {
|
||||
return comment == null || comment.length == 0 ? null : StringUtils.join(comment, '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a comment into an array of lines
|
||||
*
|
||||
* @param comment the comment text or null
|
||||
* @return the array of lines or null
|
||||
*/
|
||||
public static String[] arrayFromComment(String comment) {
|
||||
return comment == null || comment.length() == 0 ? EMPTY_STRING_ARRAY : comment.split("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the comment at the given point
|
||||
*
|
||||
* @param snap the snap
|
||||
* @param address the address
|
||||
* @param commentType the type of comment
|
||||
* @return the comment text
|
||||
*/
|
||||
public String getComment(long snap, Address address, int commentType) {
|
||||
try (LockHold hold = LockHold.lock(lock.readLock())) {
|
||||
for (DBTraceCommentEntry entry : reduce(
|
||||
@ -160,10 +207,10 @@ public class DBTraceCommentAdapter
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Document me
|
||||
* Clear all comments in the given box of the given type
|
||||
*
|
||||
* @param span
|
||||
* @param range
|
||||
* @param span the lifespan fo the box
|
||||
* @param range the address range of the box
|
||||
* @param commentType a comment type to clear, or {@link CodeUnit#NO_COMMENT} to clear all.
|
||||
*/
|
||||
public void clearComments(Range<Long> span, AddressRange range, int commentType) {
|
||||
|
@ -24,16 +24,21 @@ import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.data.DBTraceDataSettingsOperations;
|
||||
import ghidra.trace.database.guest.InternalTracePlatform;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.listing.TraceData;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.database.DBCachedObjectStore;
|
||||
import ghidra.util.database.DBObjectColumn;
|
||||
import ghidra.util.database.annot.*;
|
||||
|
||||
/**
|
||||
* The implementation for a defined {@link TraceData} for {@link DBTrace}
|
||||
*/
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
|
||||
implements DBTraceDefinedDataAdapter {
|
||||
@ -63,6 +68,14 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
|
||||
|
||||
protected AbstractDBTraceDataComponent[] componentCache = null;
|
||||
|
||||
/**
|
||||
* Construct a data unit
|
||||
*
|
||||
* @param space the space
|
||||
* @param tree the storage R*-Tree
|
||||
* @param store the object store
|
||||
* @param record the record
|
||||
*/
|
||||
public DBTraceData(DBTraceCodeSpace space,
|
||||
DBTraceAddressSnapRangePropertyMapTree<DBTraceData, ?> tree,
|
||||
DBCachedObjectStore<?> store, DBRecord record) {
|
||||
@ -102,6 +115,12 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fields of this record
|
||||
*
|
||||
* @param platform the platform
|
||||
* @param dataType the data type
|
||||
*/
|
||||
protected void set(InternalTracePlatform platform, DataType dataType) {
|
||||
this.platformKey = platform.getIntKey();
|
||||
this.dataTypeID = space.dataTypeManager.getResolvedID(dataType);
|
||||
@ -115,6 +134,11 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
|
||||
this.baseDataType = getBaseDataType(this.dataType);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this unit's data type has a fixed length, get that length
|
||||
*
|
||||
* @return the length, or -1
|
||||
*/
|
||||
protected int getDataTypeLength() {
|
||||
if (baseDataType instanceof Pointer) {
|
||||
// TODO: Also need to know where this address maps into the other language's spaces....
|
||||
@ -125,6 +149,12 @@ public class DBTraceData extends AbstractDBTraceCodeUnit<DBTraceData>
|
||||
return dataType.getLength(); // -1 is checked elsewhere
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base data type of the given data type, following typedefs recursively
|
||||
*
|
||||
* @param dt the data type
|
||||
* @return the base data type
|
||||
*/
|
||||
public static DataType getBaseDataType(DataType dt) {
|
||||
if (dt instanceof TypeDef) {
|
||||
return ((TypeDef) dt).getBaseDataType();
|
||||
|
@ -31,6 +31,13 @@ import ghidra.trace.model.symbol.TraceReference;
|
||||
import ghidra.trace.util.*;
|
||||
import ghidra.util.LockHold;
|
||||
|
||||
/**
|
||||
* A base interface for implementations of {@link TraceData}
|
||||
*
|
||||
* <p>
|
||||
* This behaves somewhat like a mixin, allowing it to be used on data units as well as data
|
||||
* components, e.g., fields of a struct data unit.
|
||||
*/
|
||||
public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterMinimal,
|
||||
DataAdapterFromDataType, DataAdapterFromSettings, TraceData {
|
||||
static String[] EMPTY_STRING_ARRAY = new String[] {};
|
||||
@ -67,6 +74,12 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the same space from the internal settings adapter
|
||||
*
|
||||
* @param createIfAbsent true to create the space if its not already present
|
||||
* @return the space or null
|
||||
*/
|
||||
DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent);
|
||||
|
||||
@Override
|
||||
|
@ -17,11 +17,26 @@ package ghidra.trace.database.listing;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* The implementation of an array-element data component in a {@link DBTrace}
|
||||
*/
|
||||
public class DBTraceDataArrayElementComponent extends AbstractDBTraceDataComponent {
|
||||
|
||||
/**
|
||||
* Create an array element
|
||||
*
|
||||
* @param root the root data unit
|
||||
* @param parent the parent component, possibly the root
|
||||
* @param index the index of this component in its parent
|
||||
* @param address the minimum address of this component
|
||||
* @param dataType the data type of this component
|
||||
* @param length the length of this component
|
||||
*/
|
||||
public DBTraceDataArrayElementComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
|
||||
int index, Address address, DataType dataType, int length) {
|
||||
super(root, parent, index, address, dataType, length);
|
||||
|
@ -17,13 +17,26 @@ package ghidra.trace.database.listing;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* The implementation of a field data component in a {@link DBTrace}
|
||||
*/
|
||||
public class DBTraceDataCompositeFieldComponent extends AbstractDBTraceDataComponent {
|
||||
protected final DataTypeComponent dtc;
|
||||
|
||||
/**
|
||||
* Create a field
|
||||
*
|
||||
* @param root the root data unit
|
||||
* @param parent the parent component, possibly the root
|
||||
* @param index the index of this component in its parent
|
||||
* @param address the minimum address of this component
|
||||
* @param dtc the data type component, giving the index, data type, and length
|
||||
*/
|
||||
public DBTraceDataCompositeFieldComponent(DBTraceData root, DBTraceDefinedDataAdapter parent,
|
||||
Address address, DataTypeComponent dtc) {
|
||||
super(root, parent, dtc.getOrdinal(), address, dtc.getDataType(), dtc.getLength());
|
||||
|
@ -15,11 +15,21 @@
|
||||
*/
|
||||
package ghidra.trace.database.listing;
|
||||
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceDataView;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager#data()}
|
||||
*/
|
||||
public class DBTraceDataMemoryView
|
||||
extends AbstractWithUndefinedDBTraceCodeUnitsMemoryView<DBTraceDataAdapter, DBTraceDataView>
|
||||
implements TraceDataView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param manager the manager
|
||||
*/
|
||||
public DBTraceDataMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -20,11 +20,21 @@ import java.util.List;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.listing.TraceDataView;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeSpace#data()}
|
||||
*/
|
||||
public class DBTraceDataView extends
|
||||
AbstractComposedDBTraceCodeUnitsView<DBTraceDataAdapter, AbstractSingleDBTraceCodeUnitsView<? extends DBTraceDataAdapter>>
|
||||
implements TraceDataView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public DBTraceDataView(DBTraceCodeSpace space) {
|
||||
super(space, List.of(space.definedData, space.undefinedData));
|
||||
}
|
||||
|
@ -20,9 +20,17 @@ import java.util.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.trace.model.listing.TraceData;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A base interface for implementations of {@link TraceData}
|
||||
*
|
||||
* <p>
|
||||
* This behaves somewhat like a mixin, allowing it to be used on defined data units as well as data
|
||||
* components, e.g., fields of a struct data unit.
|
||||
*/
|
||||
public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
|
||||
@Override
|
||||
@ -121,7 +129,7 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
default DBTraceDefinedDataAdapter getComponentAt(int offset) {
|
||||
return getComponentContaining(offset);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default DBTraceDefinedDataAdapter getComponentContaining(int offset) {
|
||||
// We may write to the cache
|
||||
|
@ -21,13 +21,23 @@ import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceDefinedDataView;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager#definedData()}
|
||||
*/
|
||||
public class DBTraceDefinedDataMemoryView
|
||||
extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceData, DBTraceDefinedDataView>
|
||||
implements TraceDefinedDataView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param manager the manager
|
||||
*/
|
||||
public DBTraceDefinedDataMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -27,12 +27,21 @@ import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.Trace.TraceCodeChangeType;
|
||||
import ghidra.trace.model.Trace.TraceCompositeDataChangeType;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.listing.TraceDefinedDataView;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.util.LockHold;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeSpace#definedData()}
|
||||
*/
|
||||
public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceData>
|
||||
implements TraceDefinedDataView {
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public DBTraceDefinedDataView(DBTraceCodeSpace space) {
|
||||
super(space, space.dataMapSpace);
|
||||
}
|
||||
@ -43,6 +52,15 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
|
||||
return create(lifespan, address, dataType, dataType.getLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given data type represents a function definition
|
||||
*
|
||||
* <p>
|
||||
* This recursively resolves typedefs and checks each.
|
||||
*
|
||||
* @param dt the data type
|
||||
* @return true if it is a function definition, false otherwise
|
||||
*/
|
||||
protected boolean isFunctionDefinition(DataType dt) {
|
||||
if (dt instanceof FunctionDefinition) {
|
||||
return true;
|
||||
|
@ -18,13 +18,23 @@ package ghidra.trace.database.listing;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceDefinedUnitsView;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager#definedUnits()}
|
||||
*/
|
||||
public class DBTraceDefinedUnitsMemoryView extends
|
||||
AbstractBaseDBTraceCodeUnitsMemoryView<AbstractDBTraceCodeUnit<?>, DBTraceDefinedUnitsView>
|
||||
implements TraceDefinedUnitsView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param manager the manager
|
||||
*/
|
||||
public DBTraceDefinedUnitsMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -22,15 +22,24 @@ import com.google.common.collect.Range;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.listing.TraceDefinedUnitsView;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeSpace#data()}
|
||||
*/
|
||||
public class DBTraceDefinedUnitsView extends
|
||||
AbstractComposedDBTraceCodeUnitsView<AbstractDBTraceCodeUnit<?>, AbstractBaseDBTraceDefinedUnitsView<? extends AbstractDBTraceCodeUnit<?>>>
|
||||
implements TraceDefinedUnitsView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public DBTraceDefinedUnitsView(DBTraceCodeSpace space) {
|
||||
super(space, List.of(space.instructions, space.definedData));
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import ghidra.program.model.listing.FlowOverride;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.context.DBTraceRegisterContextManager;
|
||||
import ghidra.trace.database.context.DBTraceRegisterContextSpace;
|
||||
@ -48,6 +49,9 @@ import ghidra.util.database.DBCachedObjectStore;
|
||||
import ghidra.util.database.DBObjectColumn;
|
||||
import ghidra.util.database.annot.*;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceInstruction} for {@link DBTrace}
|
||||
*/
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstruction> implements
|
||||
TraceInstruction, InstructionAdapterFromPrototype, InstructionContext {
|
||||
@ -76,6 +80,9 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A context for guest instructions that maps addresses appropriately
|
||||
*/
|
||||
protected class GuestInstructionContext implements InstructionContext {
|
||||
@Override
|
||||
public Address getAddress() {
|
||||
@ -121,12 +128,25 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
|
||||
protected InternalTracePlatform platform;
|
||||
protected InstructionContext instructionContext;
|
||||
|
||||
/**
|
||||
* Construct an instruction unit
|
||||
*
|
||||
* @param space the space
|
||||
* @param tree the storage R*-Tree
|
||||
* @param store the object store
|
||||
* @param record the record
|
||||
*/
|
||||
public DBTraceInstruction(DBTraceCodeSpace space,
|
||||
DBTraceAddressSnapRangePropertyMapTree<DBTraceInstruction, ?> tree,
|
||||
DBCachedObjectStore<?> store, DBRecord record) {
|
||||
super(space, tree, store, record);
|
||||
}
|
||||
|
||||
/**
|
||||
* At load/create time: set the platform and context (which may map addresses)
|
||||
*
|
||||
* @param platform the platform
|
||||
*/
|
||||
protected void doSetPlatformMapping(final InternalTracePlatform platform) {
|
||||
this.platform = platform;
|
||||
if (platform.isHost()) {
|
||||
@ -137,6 +157,13 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit<DBTraceInstructi
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fields of this record
|
||||
*
|
||||
* @param platform the platform
|
||||
* @param prototype the instruction prototype
|
||||
* @param context the context for locating or creating the prototype entry
|
||||
*/
|
||||
protected void set(InternalTracePlatform platform, InstructionPrototype prototype,
|
||||
ProcessorContextView context) {
|
||||
this.platformKey = platform.getIntKey();
|
||||
|
@ -25,14 +25,24 @@ import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceInstructionsView;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager#definedData()}
|
||||
*/
|
||||
public class DBTraceInstructionsMemoryView
|
||||
extends AbstractBaseDBTraceCodeUnitsMemoryView<DBTraceInstruction, DBTraceInstructionsView>
|
||||
implements TraceInstructionsView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param manager the manager
|
||||
*/
|
||||
public DBTraceInstructionsMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -35,14 +35,16 @@ import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.Trace.TraceCodeChangeType;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.listing.TraceInstruction;
|
||||
import ghidra.trace.model.listing.TraceInstructionsView;
|
||||
import ghidra.trace.model.listing.*;
|
||||
import ghidra.trace.util.OverlappingObjectIterator;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeSpace#instructions()}
|
||||
*/
|
||||
public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView<DBTraceInstruction>
|
||||
implements TraceInstructionsView {
|
||||
|
||||
@ -50,6 +52,9 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
return rep != null ? rep : cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* A mechanism for adding a block of instructions
|
||||
*/
|
||||
protected class InstructionBlockAdder {
|
||||
private final Set<Address> skipDelaySlots;
|
||||
private final Range<Long> lifespan;
|
||||
@ -61,6 +66,20 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
|
||||
protected int count = 0;
|
||||
|
||||
/**
|
||||
* Construct an adder
|
||||
*
|
||||
* <p>
|
||||
* This should only be done after the entire instruction set has been checked
|
||||
*
|
||||
* @param skipDelaySlots addresses of delay slotted instructions to skip
|
||||
* @param lifespan the lifespan for each instruction
|
||||
* @param platform the platform (language, compiler) for the instructions
|
||||
* @param block the block to add
|
||||
* @param errorAddress the address of the first error in the block, if any
|
||||
* @param conflict a description of the error, if any
|
||||
* @param conflictCodeUnit if a conflict, the code unit that already exists
|
||||
*/
|
||||
private InstructionBlockAdder(Set<Address> skipDelaySlots, Range<Long> lifespan,
|
||||
InternalTracePlatform platform, InstructionBlock block, Address errorAddress,
|
||||
InstructionError conflict, CodeUnit conflictCodeUnit) {
|
||||
@ -73,6 +92,14 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
this.conflictCodeUnit = conflictCodeUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the given instruction in the database
|
||||
*
|
||||
* @param address the address of the instruction
|
||||
* @param prototype the instruction prototype
|
||||
* @param protoInstr the parsed (usually pseudo) instruction
|
||||
* @return the created instruction
|
||||
*/
|
||||
protected Instruction doCreateInstruction(Address address,
|
||||
InstructionPrototype prototype, Instruction protoInstr) {
|
||||
try {
|
||||
@ -97,12 +124,14 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
/**
|
||||
* Adds the instructions and returns the last instruction added
|
||||
*
|
||||
* <p>
|
||||
* If it encounters a delay-slotted instruction, it will recurse on the group, iterating in
|
||||
* reverse order.
|
||||
*
|
||||
* @param instructions
|
||||
* @param areDelaySlots
|
||||
* @return
|
||||
* @param instructions the instructions to add
|
||||
* @param areDelaySlots true if the instructions are already reversed from being
|
||||
* delay-slotted
|
||||
* @return the last instruction added
|
||||
*/
|
||||
protected Instruction doAddInstructions(Iterator<Instruction> it, boolean areDelaySlots) {
|
||||
Instruction lastInstruction = null;
|
||||
@ -158,13 +187,38 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
}
|
||||
return lastInstruction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the instructions and return the last one added
|
||||
*
|
||||
* @return the last instruction added
|
||||
*/
|
||||
protected Instruction doAddInstructions() {
|
||||
return doAddInstructions(block.iterator(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public DBTraceInstructionsView(DBTraceCodeSpace space) {
|
||||
super(space, space.instructionMapSpace);
|
||||
}
|
||||
|
||||
protected void doSetContexts(TraceAddressSnapRange tasr, Language language,
|
||||
/**
|
||||
* Set the context over the given box
|
||||
*
|
||||
* <p>
|
||||
* If the given context matches the language's default at the mininum address of the box, the
|
||||
* context is cleared.
|
||||
*
|
||||
* @param tasr the box
|
||||
* @param language the language for the instruction
|
||||
* @param context the desired context
|
||||
*/
|
||||
protected void doSetContext(TraceAddressSnapRange tasr, Language language,
|
||||
ProcessorContextView context) {
|
||||
Register contextReg = language.getContextBaseRegister();
|
||||
if (contextReg == null || contextReg == Register.NO_CONTEXT) {
|
||||
@ -185,6 +239,19 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
ctxSpace.setValue(language, newValue, tasr.getLifespan(), tasr.getRange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instruction
|
||||
*
|
||||
* @param lifespan the lifespan of the instruction
|
||||
* @param address the minimum address of the instruction
|
||||
* @param platform the platform (language, compiler) for the instruction
|
||||
* @param prototype the instruction's prototype
|
||||
* @param context the initial context for parsing the instruction
|
||||
* @return the new instructions
|
||||
* @throws CodeUnitInsertionException if the instruction cannot be created due to an existing
|
||||
* unit
|
||||
* @throws AddressOverflowException if the instruction would fall off the address space
|
||||
*/
|
||||
protected DBTraceInstruction doCreate(Range<Long> lifespan, Address address,
|
||||
InternalTracePlatform platform, InstructionPrototype prototype,
|
||||
ProcessorContextView context)
|
||||
@ -221,7 +288,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
throw new CodeUnitInsertionException("Code units cannot overlap");
|
||||
}
|
||||
|
||||
doSetContexts(tasr, prototype.getLanguage(), context);
|
||||
doSetContext(tasr, prototype.getLanguage(), context);
|
||||
|
||||
DBTraceInstruction created = space.instructionMapSpace.put(tasr, null);
|
||||
created.set(platform, prototype, context);
|
||||
@ -253,6 +320,13 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare to check a block for conflicts
|
||||
*
|
||||
* @param startSnap the minimum snap for each instruction
|
||||
* @param block the block of instructions
|
||||
* @return an iterator for overlapping object pairs
|
||||
*/
|
||||
protected OverlappingObjectIterator<Instruction, CodeUnit> startCheckingBlock(long startSnap,
|
||||
InstructionBlock block) {
|
||||
Address startAddress = block.getStartAddress();
|
||||
@ -267,6 +341,19 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
OverlappingObjectIterator.CODE_UNIT, existing, OverlappingObjectIterator.CODE_UNIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start adding the given block to the database
|
||||
*
|
||||
* <p>
|
||||
* If this returns non-null, it should be immediately followed by
|
||||
* {@link InstructionBlockAdder#doAddInstructions()}.
|
||||
*
|
||||
* @param lifespan the lifespan of each instruction
|
||||
* @param skipDelaySlots the addresses of delay-slotted instructions to skip
|
||||
* @param platform the instructions' platform (language, compiler)
|
||||
* @param block the block of instructions to add
|
||||
* @return the adder, or null
|
||||
*/
|
||||
protected InstructionBlockAdder startAddingBlock(Range<Long> lifespan,
|
||||
Set<Address> skipDelaySlots, InternalTracePlatform platform, InstructionBlock block) {
|
||||
InstructionError conflict = block.getInstructionConflict();
|
||||
@ -292,6 +379,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
/**
|
||||
* Checks the intended locations for conflicts with existing units.
|
||||
*
|
||||
* <p>
|
||||
* This also clears locations where delay slots will be replacing non-delay slots.
|
||||
* {@code skipDelaySlots} will be populated with any existing delay slot locations which should
|
||||
* not be overwritten
|
||||
@ -400,7 +488,7 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView
|
||||
if (adder == null) {
|
||||
continue;
|
||||
}
|
||||
Instruction lastInstruction = adder.doAddInstructions(block.iterator(), false);
|
||||
Instruction lastInstruction = adder.doAddInstructions();
|
||||
block.setInstructionsAddedCount(adder.count);
|
||||
if (lastInstruction != null) {
|
||||
Address maxAddress = DBTraceCodeManager.instructionMax(lastInstruction, true);
|
||||
|
@ -15,11 +15,21 @@
|
||||
*/
|
||||
package ghidra.trace.database.listing;
|
||||
|
||||
import ghidra.trace.model.listing.TraceCodeManager;
|
||||
import ghidra.trace.model.listing.TraceUndefinedDataView;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeManager#undefinedData()}
|
||||
*/
|
||||
public class DBTraceUndefinedDataMemoryView extends
|
||||
AbstractWithUndefinedDBTraceCodeUnitsMemoryView<UndefinedDBTraceData, DBTraceUndefinedDataView>
|
||||
implements TraceUndefinedDataView {
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param manager the manager
|
||||
*/
|
||||
public DBTraceUndefinedDataMemoryView(DBTraceCodeManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -26,9 +26,13 @@ import com.google.common.collect.Range;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.listing.TraceCodeSpace;
|
||||
import ghidra.trace.model.listing.TraceUndefinedDataView;
|
||||
import ghidra.util.*;
|
||||
|
||||
/**
|
||||
* The implementation of {@link TraceCodeSpace#undefinedData()}
|
||||
*/
|
||||
public class DBTraceUndefinedDataView extends
|
||||
AbstractSingleDBTraceCodeUnitsView<UndefinedDBTraceData> implements TraceUndefinedDataView {
|
||||
|
||||
@ -42,6 +46,11 @@ public class DBTraceUndefinedDataView extends
|
||||
.build()
|
||||
.asMap();
|
||||
|
||||
/**
|
||||
* Construct the view
|
||||
*
|
||||
* @param space the space, bound to an address space
|
||||
*/
|
||||
public DBTraceUndefinedDataView(DBTraceCodeSpace space) {
|
||||
super(space);
|
||||
this.manager = space.manager;
|
||||
@ -51,6 +60,13 @@ public class DBTraceUndefinedDataView extends
|
||||
// Nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an undefined data unit at the given point
|
||||
*
|
||||
* @param snap the snap of the unit
|
||||
* @param address the address of the unit
|
||||
* @return the unit
|
||||
*/
|
||||
protected UndefinedDBTraceData doCreateUnit(long snap, Address address) {
|
||||
space.assertInSpace(address);
|
||||
return manager.doCreateUndefinedUnit(snap, address, space.getThread(),
|
||||
@ -62,6 +78,16 @@ public class DBTraceUndefinedDataView extends
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an address set view for optimizing various queries
|
||||
*
|
||||
* <p>
|
||||
* As its code may suggest, this creates the lazy address set view {@code all - definedUnits},
|
||||
* and wraps it in a cached address set view.
|
||||
*
|
||||
* @param snap the snapshot key for the address set
|
||||
* @return the address set
|
||||
*/
|
||||
protected AddressSetView doGetAddressSetView(long snap) {
|
||||
return cache.computeIfAbsent(snap,
|
||||
t -> new CachedAddressSetView(new DifferenceAddressSetView(new AddressSet(space.all),
|
||||
@ -142,6 +168,9 @@ public class DBTraceUndefinedDataView extends
|
||||
doGetAddressSetView(snap));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the cache of generated undefined units
|
||||
*/
|
||||
public void invalidateCache() {
|
||||
cache.clear();
|
||||
}
|
||||
|
@ -38,6 +38,13 @@ import ghidra.trace.model.listing.TraceData;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* The implementation for an undefined {@link TraceData} for {@link DBTrace}
|
||||
*
|
||||
* <p>
|
||||
* These are not backed by a table. They are generated ephemerally. Each is exactly one unit in size
|
||||
* in both time and space.
|
||||
*/
|
||||
public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey {
|
||||
protected final DBTrace trace;
|
||||
protected final long snap;
|
||||
@ -46,6 +53,15 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
|
||||
/**
|
||||
* Construct an undefined unit
|
||||
*
|
||||
* @param trace the trace
|
||||
* @param snap the snap
|
||||
* @param address the address
|
||||
* @param thread the thread, if in a per-thread space
|
||||
* @param frameLevel the frame, if in a per-frame space
|
||||
*/
|
||||
public UndefinedDBTraceData(DBTrace trace, long snap, Address address, TraceThread thread,
|
||||
int frameLevel) {
|
||||
this.trace = trace;
|
||||
|
@ -126,14 +126,14 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTracePropertyMapSpace(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, dataType, dataFactory);
|
||||
lock, space, null, 0, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTracePropertyMapRegisterSpace createRegisterSpace(
|
||||
protected DBTracePropertyMapSpace createRegisterSpace(
|
||||
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTracePropertyMapRegisterSpace(
|
||||
return new DBTracePropertyMapSpace(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
|
||||
}
|
||||
@ -145,9 +145,9 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracePropertyMapRegisterSpace<T> getPropertyMapRegisterSpace(TraceThread thread,
|
||||
public TracePropertyMapSpace<T> getPropertyMapRegisterSpace(TraceThread thread,
|
||||
int frameLevel, boolean createIfAbsent) {
|
||||
return (DBTracePropertyMapRegisterSpace) getForRegisterSpace(thread, frameLevel,
|
||||
return (DBTracePropertyMapSpace) getForRegisterSpace(thread, frameLevel,
|
||||
createIfAbsent);
|
||||
}
|
||||
|
||||
@ -161,96 +161,11 @@ public abstract class AbstractDBTracePropertyMap<T, DR extends AbstractDBTraceAd
|
||||
implements TracePropertyMapSpace<T> {
|
||||
|
||||
public DBTracePropertyMapSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
|
||||
ReadWriteLock lock, AddressSpace space, Class<DR> dataType,
|
||||
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
|
||||
throws VersionException, IOException {
|
||||
super(tableName, storeFactory, lock, space, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trace getTrace() {
|
||||
return trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getValueClass() {
|
||||
return AbstractDBTracePropertyMap.this.getValueClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void makeWay(Entry<TraceAddressSnapRange, T> entry, Range<Long> span) {
|
||||
// TODO: Would rather not rely on implementation knowledge here
|
||||
// The shape is the database record in AbstractDBTraceAddressSnapRangePropertyMapData
|
||||
makeWay((DR) entry.getKey(), span);
|
||||
}
|
||||
|
||||
protected void makeWay(DR data, Range<Long> span) {
|
||||
DBTraceUtils.makeWay(data, span, (d, s) -> d.doSetLifespan(s), d -> deleteData(d));
|
||||
// TODO: Any events?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Range<Long> lifespan, Address address, T value) {
|
||||
put(address, lifespan, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Range<Long> lifespan, AddressRange range, T value) {
|
||||
put(range, lifespan, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long snap, Address address) {
|
||||
return reduce(TraceAddressSnapRangeQuery.at(address, snap)).firstValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<TraceAddressSnapRange, T> getEntry(long snap, Address address) {
|
||||
return reduce(TraceAddressSnapRangeQuery.at(address, snap)).firstEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entry<TraceAddressSnapRange, T>> getEntries(Range<Long> lifespan,
|
||||
AddressRange range) {
|
||||
return reduce(TraceAddressSnapRangeQuery.intersecting(range, lifespan)).entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clear(Range<Long> span, AddressRange range) {
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
boolean result = false;
|
||||
for (Entry<TraceAddressSnapRange, T> entry : reduce(
|
||||
TraceAddressSnapRangeQuery.intersecting(range, span)).entries()) {
|
||||
makeWay(entry, span);
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T put(TraceAddressSnapRange shape, T value) {
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
for (Entry<TraceAddressSnapRange, T> entry : reduce(
|
||||
TraceAddressSnapRangeQuery.intersecting(shape)).entries()) {
|
||||
makeWay(entry, shape.getLifespan());
|
||||
}
|
||||
return super.put(shape, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DBTracePropertyMapRegisterSpace
|
||||
extends DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR>
|
||||
implements TracePropertyMapRegisterSpace<T> {
|
||||
|
||||
public DBTracePropertyMapRegisterSpace(String tableName,
|
||||
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
|
||||
TraceThread thread, int frameLevel, Class<DR> dataType,
|
||||
ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
|
||||
Class<DR> dataType,
|
||||
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
|
||||
throws VersionException, IOException {
|
||||
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,8 +48,7 @@ import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAddressSnapRangePropertyMapData<T>>
|
||||
extends
|
||||
AbstractDBTraceSpaceBasedManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>, DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR>>
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>>
|
||||
implements TraceAddressSnapRangePropertyMap<T>,
|
||||
DBTraceDelegatingManager<DBTraceAddressSnapRangePropertyMapSpace<T, DR>> {
|
||||
|
||||
@ -83,26 +82,26 @@ public class DBTraceAddressSnapRangePropertyMap<T, DR extends AbstractDBTraceAdd
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, dataType, dataFactory);
|
||||
lock, space, null, ent.getFrameLevel(), dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> createRegisterSpace(
|
||||
protected DBTraceAddressSnapRangePropertyMapSpace<T, DR> createRegisterSpace(
|
||||
AddressSpace space, TraceThread thread, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceAddressSnapRangePropertyMapRegisterSpace<>(
|
||||
return new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> getRegisterSpace(
|
||||
public DBTraceAddressSnapRangePropertyMapSpace<T, DR> getRegisterSpace(
|
||||
TraceThread thread, boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceAddressSnapRangePropertyMapRegisterSpace<T, DR> getRegisterSpace(
|
||||
public DBTraceAddressSnapRangePropertyMapSpace<T, DR> getRegisterSpace(
|
||||
TraceStackFrame frame, boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame, createIfAbsent);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -44,6 +44,8 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
|
||||
TraceAddressSnapRangePropertyMapSpace<T> {
|
||||
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTraceAddressSnapRangePropertyMapTree<T, DR> tree;
|
||||
protected final AbstractConstraintsTreeSpatialMap<TraceAddressSnapRange, DR, TraceAddressSnapRange, T, TraceAddressSnapRangeQuery> map;
|
||||
@ -51,9 +53,12 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
|
||||
|
||||
public DBTraceAddressSnapRangePropertyMapSpace(String tableName,
|
||||
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
|
||||
Class<DR> dataType, DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
|
||||
TraceThread thread, int frameLevel, Class<DR> dataType,
|
||||
DBTraceAddressSnapRangePropertyMapDataFactory<T, DR> dataFactory)
|
||||
throws VersionException, IOException {
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = frameLevel;
|
||||
this.lock = lock;
|
||||
|
||||
this.tree = new DBTraceAddressSnapRangePropertyMapTree<>(storeFactory, tableName, this,
|
||||
@ -70,12 +75,12 @@ public class DBTraceAddressSnapRangePropertyMapSpace<T, DR extends AbstractDBTra
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
return thread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
public <K> DBCachedObjectIndex<K, DR> getUserIndex(Class<K> fieldClass, DBObjectColumn column) {
|
||||
|
@ -48,8 +48,7 @@ import ghidra.util.database.DBOpenMode;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceMemoryManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace, DBTraceMemoryRegisterSpace>
|
||||
public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager<DBTraceMemorySpace>
|
||||
implements TraceMemoryManager, DBTraceDelegatingManager<DBTraceMemorySpace> {
|
||||
|
||||
protected static final String NAME = "Memory";
|
||||
@ -80,13 +79,13 @@ public class DBTraceMemoryManager
|
||||
@Override
|
||||
protected DBTraceMemorySpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceMemorySpace(this, dbh, space, ent);
|
||||
return new DBTraceMemorySpace(this, dbh, space, ent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceMemoryRegisterSpace createRegisterSpace(AddressSpace space,
|
||||
protected DBTraceMemorySpace createRegisterSpace(AddressSpace space,
|
||||
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceMemoryRegisterSpace(this, dbh, space, ent, thread);
|
||||
return new DBTraceMemorySpace(this, dbh, space, ent, thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,19 +109,19 @@ public class DBTraceMemoryManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceMemoryRegisterSpace getMemoryRegisterSpace(TraceThread thread,
|
||||
public DBTraceMemorySpace getMemoryRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceMemoryRegisterSpace getMemoryRegisterSpace(TraceThread thread, int frame,
|
||||
public DBTraceMemorySpace getMemoryRegisterSpace(TraceThread thread, int frame,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, frame, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceMemoryRegisterSpace getMemoryRegisterSpace(TraceStackFrame frame,
|
||||
public DBTraceMemorySpace getMemoryRegisterSpace(TraceStackFrame frame,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame, createIfAbsent);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -68,6 +68,8 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
||||
protected final DBTraceMemoryManager manager;
|
||||
protected final DBHandle dbh;
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTrace trace;
|
||||
|
||||
@ -96,10 +98,12 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
||||
protected final DefaultTraceTimeViewport viewport;
|
||||
|
||||
public DBTraceMemorySpace(DBTraceMemoryManager manager, DBHandle dbh, AddressSpace space,
|
||||
DBTraceSpaceEntry ent) throws IOException, VersionException {
|
||||
DBTraceSpaceEntry ent, TraceThread thread) throws IOException, VersionException {
|
||||
this.manager = manager;
|
||||
this.dbh = dbh;
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = ent.getFrameLevel();
|
||||
this.lock = manager.getLock();
|
||||
this.trace = manager.getTrace();
|
||||
|
||||
@ -108,15 +112,16 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
||||
long threadKey = ent.getThreadKey();
|
||||
int frameLevel = ent.getFrameLevel();
|
||||
this.regionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space,
|
||||
DBTraceMemoryRegion.class, (t, s, r) -> new DBTraceMemoryRegion(this, t, s, r));
|
||||
DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space, thread,
|
||||
frameLevel, DBTraceMemoryRegion.class,
|
||||
(t, s, r) -> new DBTraceMemoryRegion(this, t, s, r));
|
||||
this.regionView = Collections.unmodifiableCollection(regionMapSpace.values());
|
||||
this.regionsByPath =
|
||||
regionMapSpace.getUserIndex(String.class, DBTraceMemoryRegion.PATH_COLUMN);
|
||||
|
||||
this.stateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceMemoryStateEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
|
||||
DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new);
|
||||
thread, frameLevel, DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new);
|
||||
|
||||
this.bufferStore = factory.getOrCreateCachedStore(
|
||||
DBTraceMemoryBufferEntry.tableName(space, threadKey, frameLevel),
|
||||
@ -257,6 +262,9 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
||||
|
||||
@Override
|
||||
public DBTraceCodeSpace getCodeSpace(boolean createIfAbsent) {
|
||||
if (space.isRegisterSpace()) {
|
||||
return trace.getCodeManager().getCodeRegisterSpace(thread, frameLevel, createIfAbsent);
|
||||
}
|
||||
return trace.getCodeManager().getCodeSpace(space, createIfAbsent);
|
||||
}
|
||||
|
||||
@ -405,7 +413,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace
|
||||
@Override
|
||||
public Entry<TraceAddressSnapRange, TraceMemoryState> getViewMostRecentStateEntry(long snap,
|
||||
Address address) {
|
||||
for (Range<Long> span: viewport.getOrderedSpans(snap)) {
|
||||
for (Range<Long> span : viewport.getOrderedSpans(snap)) {
|
||||
Entry<TraceAddressSnapRange, TraceMemoryState> entry =
|
||||
stateMapSpace.reduce(TraceAddressSnapRangeQuery.mostRecent(address, span))
|
||||
.firstEntry();
|
||||
|
@ -41,8 +41,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceModuleManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceModuleSpace, DBTraceModuleSpace>
|
||||
public class DBTraceModuleManager extends AbstractDBTraceSpaceBasedManager<DBTraceModuleSpace>
|
||||
implements TraceModuleManager, DBTraceDelegatingManager<DBTraceModuleSpace> {
|
||||
public static final String NAME = "Module";
|
||||
|
||||
|
@ -58,13 +58,13 @@ public class DBTraceModuleSpace implements TraceModuleSpace, DBTraceSpaceBased {
|
||||
this.trace = manager.getTrace();
|
||||
|
||||
this.moduleMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceModule.tableName(space), trace.getStoreFactory(), lock, space,
|
||||
DBTraceModule.tableName(space), trace.getStoreFactory(), lock, space, null, 0,
|
||||
DBTraceModule.class, (t, s, r) -> new DBTraceModule(this, t, s, r));
|
||||
this.modulesByPath = moduleMapSpace.getUserIndex(String.class, DBTraceModule.PATH_COLUMN);
|
||||
this.moduleView = Collections.unmodifiableCollection(moduleMapSpace.values());
|
||||
|
||||
this.sectionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceSection.tableName(space), trace.getStoreFactory(), lock, space,
|
||||
DBTraceSection.tableName(space), trace.getStoreFactory(), lock, space, null, 0,
|
||||
DBTraceSection.class, (t, s, r) -> new DBTraceSection(this, t, s, r));
|
||||
this.sectionsByModuleKey =
|
||||
sectionMapSpace.getUserIndex(long.class, DBTraceSection.MODULE_COLUMN);
|
||||
|
@ -45,8 +45,8 @@ import ghidra.program.model.util.PropertyMapManager;
|
||||
import ghidra.program.util.ChangeManager;
|
||||
import ghidra.program.util.ProgramChangeRecord;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.listing.*;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.database.listing.DBTraceCodeSpace;
|
||||
import ghidra.trace.database.listing.DBTraceDefinedUnitsView;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.database.symbol.DBTraceFunctionSymbolView;
|
||||
import ghidra.trace.model.Trace.*;
|
||||
@ -990,12 +990,12 @@ public class DBTraceProgramView implements TraceProgramView {
|
||||
return regView;
|
||||
}
|
||||
assert trace.getThreadManager().getAllThreads().contains(thread);
|
||||
DBTraceCodeRegisterSpace codeSpace =
|
||||
DBTraceCodeSpace codeSpace =
|
||||
trace.getCodeManager().getCodeRegisterSpace(thread, createIfAbsent);
|
||||
if (codeSpace == null) {
|
||||
return null;
|
||||
}
|
||||
DBTraceMemoryRegisterSpace memorySpace =
|
||||
DBTraceMemorySpace memorySpace =
|
||||
trace.getMemoryManager().getMemoryRegisterSpace(thread, createIfAbsent);
|
||||
if (memorySpace == null) {
|
||||
return null;
|
||||
|
@ -18,7 +18,7 @@ package ghidra.trace.database.program;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
|
||||
import ghidra.trace.database.listing.DBTraceCodeSpace;
|
||||
import ghidra.trace.database.listing.UndefinedDBTraceData;
|
||||
import ghidra.trace.model.program.TraceProgramViewRegisterListing;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
@ -32,7 +32,7 @@ public class DBTraceProgramViewRegisterListing extends AbstractDBTraceProgramVie
|
||||
private Address maxAddr;
|
||||
|
||||
public DBTraceProgramViewRegisterListing(DBTraceProgramView program,
|
||||
DBTraceCodeRegisterSpace regSpace) {
|
||||
DBTraceCodeSpace regSpace) {
|
||||
super(program, regSpace);
|
||||
this.thread = regSpace.getThread();
|
||||
|
||||
|
@ -17,14 +17,14 @@ package ghidra.trace.database.program;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
|
||||
public class DBTraceProgramViewRegisterMemory extends AbstractDBTraceProgramViewMemory {
|
||||
protected final DBTraceMemoryRegisterSpace space;
|
||||
protected final DBTraceMemorySpace space;
|
||||
protected final DBTraceProgramViewRegisterMemoryBlock block;
|
||||
|
||||
public DBTraceProgramViewRegisterMemory(DBTraceProgramView program,
|
||||
DBTraceMemoryRegisterSpace space) {
|
||||
DBTraceMemorySpace space) {
|
||||
super(program);
|
||||
this.space = space;
|
||||
this.block = new DBTraceProgramViewRegisterMemoryBlock(program, space);
|
||||
|
@ -27,7 +27,7 @@ import ghidra.program.database.mem.ByteMappingScheme;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.memory.TraceMemorySpaceInputStream;
|
||||
|
||||
public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
|
||||
@ -96,14 +96,14 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
|
||||
}
|
||||
|
||||
private final DBTraceProgramView program;
|
||||
private final DBTraceMemoryRegisterSpace space;
|
||||
private final DBTraceMemorySpace space;
|
||||
private final AddressRange range;
|
||||
|
||||
private final List<MemoryBlockSourceInfo> info =
|
||||
Collections.singletonList(new DBTraceProgramViewRegisterMemoryBlockSourceInfo());
|
||||
|
||||
public DBTraceProgramViewRegisterMemoryBlock(DBTraceProgramView program,
|
||||
DBTraceMemoryRegisterSpace space) {
|
||||
DBTraceMemorySpace space) {
|
||||
this.program = program;
|
||||
this.space = space;
|
||||
this.range = new AddressRangeImpl(space.getAddressSpace().getMinAddress(),
|
||||
|
@ -34,8 +34,8 @@ import ghidra.program.model.reloc.RelocationTable;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.util.AddressSetPropertyMap;
|
||||
import ghidra.program.model.util.PropertyMapManager;
|
||||
import ghidra.trace.database.listing.DBTraceCodeRegisterSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryRegisterSpace;
|
||||
import ghidra.trace.database.listing.DBTraceCodeSpace;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.data.TraceBasedDataTypeManager;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
@ -56,8 +56,8 @@ public class DBTraceProgramViewRegisters implements TraceProgramView {
|
||||
private final DBTraceProgramViewRegisterMemory memory;
|
||||
private final DBTraceProgramViewRegistersReferenceManager referenceManager;
|
||||
|
||||
public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeRegisterSpace codeSpace,
|
||||
DBTraceMemoryRegisterSpace memorySpace) {
|
||||
public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeSpace codeSpace,
|
||||
DBTraceMemorySpace memorySpace) {
|
||||
this.view = view;
|
||||
this.thread = codeSpace.getThread(); // TODO: Bleh, should be parameter
|
||||
|
||||
|
@ -39,7 +39,7 @@ import ghidra.util.database.annot.*;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBased, R extends M>
|
||||
public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBased>
|
||||
implements DBTraceManager {
|
||||
protected static final AddressSpace NO_ADDRESS_SPACE = Address.NO_ADDRESS.getAddressSpace();
|
||||
|
||||
@ -96,10 +96,10 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
||||
// Note: use tree map so traversal is ordered by address space
|
||||
protected final Map<AddressSpace, M> memSpaces = new TreeMap<>();
|
||||
// Note: can use hash map here. I see no need to order these spaces
|
||||
protected final Map<Pair<TraceThread, Integer>, R> regSpaces = new HashMap<>();
|
||||
protected final Map<Pair<TraceThread, Integer>, M> regSpaces = new HashMap<>();
|
||||
protected final Collection<M> memSpacesView =
|
||||
Collections.unmodifiableCollection(memSpaces.values());
|
||||
protected final Collection<R> regSpacesView =
|
||||
protected final Collection<M> regSpacesView =
|
||||
Collections.unmodifiableCollection(regSpaces.values());
|
||||
protected final Collection<M> allSpacesView =
|
||||
new CatenatedCollection<>(memSpacesView, regSpacesView);
|
||||
@ -145,12 +145,12 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
||||
continue;
|
||||
}
|
||||
TraceThread thread = threadManager.getThread(ent.threadKey);
|
||||
R regSpace;
|
||||
M regSpace;
|
||||
if (ent.space == null) {
|
||||
regSpace = createRegisterSpace(space, thread, ent);
|
||||
}
|
||||
else {
|
||||
regSpace = (R) ent.space;
|
||||
regSpace = (M) ent.space;
|
||||
}
|
||||
regSpaces.put(ImmutablePair.of(thread, ent.getFrameLevel()), regSpace);
|
||||
}
|
||||
@ -199,7 +199,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
||||
}
|
||||
}
|
||||
|
||||
protected R getForRegisterSpace(TraceThread thread, int frameLevel, boolean createIfAbsent) {
|
||||
protected M getForRegisterSpace(TraceThread thread, int frameLevel, boolean createIfAbsent) {
|
||||
trace.getThreadManager().assertIsMine(thread);
|
||||
// TODO: What if registers are memory mapped?
|
||||
Pair<TraceThread, Integer> frame = ImmutablePair.of(thread, frameLevel);
|
||||
@ -227,7 +227,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
||||
}
|
||||
}
|
||||
|
||||
protected R getForRegisterSpace(TraceStackFrame frame, boolean createIfAbsent) {
|
||||
protected M getForRegisterSpace(TraceStackFrame frame, boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame.getStack().getThread(), frame.getLevel(), createIfAbsent);
|
||||
}
|
||||
|
||||
@ -259,14 +259,14 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
||||
return memSpacesView;
|
||||
}
|
||||
|
||||
public Collection<R> getActiveRegisterSpaces() {
|
||||
public Collection<M> getActiveRegisterSpaces() {
|
||||
return regSpacesView;
|
||||
}
|
||||
|
||||
protected abstract M createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException;
|
||||
|
||||
protected abstract R createRegisterSpace(AddressSpace space, TraceThread thread,
|
||||
protected abstract M createRegisterSpace(AddressSpace space, TraceThread thread,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException;
|
||||
|
||||
@Override
|
||||
@ -286,7 +286,7 @@ public abstract class AbstractDBTraceSpaceBasedManager<M extends DBTraceSpaceBas
|
||||
for (M m : memSpaces.values()) {
|
||||
m.invalidateCache();
|
||||
}
|
||||
for (R r : regSpaces.values()) {
|
||||
for (M r : regSpaces.values()) {
|
||||
r.invalidateCache();
|
||||
}
|
||||
}
|
||||
|
@ -40,8 +40,7 @@ import ghidra.util.database.*;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceEquateManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceEquateSpace, DBTraceEquateRegisterSpace>
|
||||
public class DBTraceEquateManager extends AbstractDBTraceSpaceBasedManager<DBTraceEquateSpace>
|
||||
implements TraceEquateManager, DBTraceDelegatingManager<DBTraceEquateSpace> {
|
||||
public static final String NAME = "Equate";
|
||||
|
||||
@ -96,13 +95,13 @@ public class DBTraceEquateManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceEquateRegisterSpace getEquateRegisterSpace(TraceThread thread,
|
||||
public DBTraceEquateSpace getEquateRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceEquateRegisterSpace getEquateRegisterSpace(TraceStackFrame frame,
|
||||
public DBTraceEquateSpace getEquateRegisterSpace(TraceStackFrame frame,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame, createIfAbsent);
|
||||
}
|
||||
@ -110,13 +109,13 @@ public class DBTraceEquateManager
|
||||
@Override
|
||||
protected DBTraceEquateSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceEquateSpace(this, dbh, space, ent);
|
||||
return new DBTraceEquateSpace(this, dbh, space, ent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceEquateRegisterSpace createRegisterSpace(AddressSpace space,
|
||||
protected DBTraceEquateSpace createRegisterSpace(AddressSpace space,
|
||||
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceEquateRegisterSpace(this, dbh, space, ent, thread);
|
||||
return new DBTraceEquateSpace(this, dbh, space, ent, thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -101,6 +101,8 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
|
||||
protected final DBTraceEquateManager manager;
|
||||
protected final DBHandle dbh;
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final Language baseLanguage;
|
||||
protected final DBTrace trace;
|
||||
@ -110,10 +112,12 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
|
||||
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceEquateReference, DBTraceEquateReference> equateMapSpace;
|
||||
|
||||
public DBTraceEquateSpace(DBTraceEquateManager manager, DBHandle dbh, AddressSpace space,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
|
||||
this.manager = manager;
|
||||
this.dbh = dbh;
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = ent.getFrameLevel();
|
||||
this.lock = manager.getLock();
|
||||
this.baseLanguage = manager.getBaseLanguage();
|
||||
this.trace = manager.getTrace();
|
||||
@ -126,7 +130,8 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
|
||||
int frameLevel = ent.getFrameLevel();
|
||||
this.equateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceEquateReference.tableName(space, threadKey, frameLevel), factory, lock, space,
|
||||
DBTraceEquateReference.class, (t, s, r) -> new DBTraceEquateReference(this, t, s, r));
|
||||
thread, ent.getFrameLevel(), DBTraceEquateReference.class,
|
||||
(t, s, r) -> new DBTraceEquateReference(this, t, s, r));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -136,12 +141,12 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace {
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
return thread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,8 +44,7 @@ import ghidra.util.database.DBOpenMode;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceReferenceManager extends
|
||||
AbstractDBTraceSpaceBasedManager<DBTraceReferenceSpace, DBTraceReferenceRegisterSpace>
|
||||
public class DBTraceReferenceManager extends AbstractDBTraceSpaceBasedManager<DBTraceReferenceSpace>
|
||||
implements TraceReferenceManager, DBTraceDelegatingManager<DBTraceReferenceSpace> {
|
||||
public static final String NAME = "Reference";
|
||||
|
||||
@ -64,13 +63,13 @@ public class DBTraceReferenceManager extends
|
||||
@Override
|
||||
protected DBTraceReferenceSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceReferenceSpace(this, dbh, space, ent);
|
||||
return new DBTraceReferenceSpace(this, dbh, space, ent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceReferenceRegisterSpace createRegisterSpace(AddressSpace space,
|
||||
protected DBTraceReferenceSpace createRegisterSpace(AddressSpace space,
|
||||
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceReferenceRegisterSpace(this, dbh, space, ent, thread);
|
||||
return new DBTraceReferenceSpace(this, dbh, space, ent, thread);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,13 +146,13 @@ public class DBTraceReferenceManager extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceReferenceRegisterSpace getReferenceRegisterSpace(TraceThread thread,
|
||||
public DBTraceReferenceSpace getReferenceRegisterSpace(TraceThread thread,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(thread, 0, createIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceReferenceRegisterSpace getReferenceRegisterSpace(TraceStackFrame frame,
|
||||
public DBTraceReferenceSpace getReferenceRegisterSpace(TraceStackFrame frame,
|
||||
boolean createIfAbsent) {
|
||||
return getForRegisterSpace(frame, createIfAbsent);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -334,6 +334,8 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||
protected final DBTraceReferenceManager manager;
|
||||
protected final DBHandle dbh;
|
||||
protected final AddressSpace space;
|
||||
protected final TraceThread thread;
|
||||
protected final int frameLevel;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final Language baseLanguage;
|
||||
protected final DBTrace trace;
|
||||
@ -347,10 +349,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||
protected final DBCachedObjectIndex<Long, DBTraceXRefEntry> xrefsByRefKey;
|
||||
|
||||
public DBTraceReferenceSpace(DBTraceReferenceManager manager, DBHandle dbh, AddressSpace space,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException {
|
||||
this.manager = manager;
|
||||
this.dbh = dbh;
|
||||
this.space = space;
|
||||
this.thread = thread;
|
||||
this.frameLevel = ent.getFrameLevel();
|
||||
this.lock = manager.getLock();
|
||||
this.baseLanguage = manager.getBaseLanguage();
|
||||
this.trace = manager.getTrace();
|
||||
@ -363,13 +367,14 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||
int frameLevel = ent.getFrameLevel();
|
||||
this.referenceMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceReferenceEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
|
||||
DBTraceReferenceEntry.class, (t, s, r) -> new DBTraceReferenceEntry(this, t, s, r));
|
||||
thread, frameLevel, DBTraceReferenceEntry.class,
|
||||
(t, s, r) -> new DBTraceReferenceEntry(this, t, s, r));
|
||||
this.refsBySymbolId =
|
||||
referenceMapSpace.getUserIndex(long.class, DBTraceReferenceEntry.SYMBOL_ID_COLUMN);
|
||||
|
||||
this.xrefMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>(
|
||||
DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space,
|
||||
DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r));
|
||||
DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space, thread,
|
||||
frameLevel, DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r));
|
||||
this.xrefsByRefKey = xrefMapSpace.getUserIndex(long.class, DBTraceXRefEntry.REF_KEY_COLUMN);
|
||||
}
|
||||
|
||||
@ -409,12 +414,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return null;
|
||||
return thread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,9 +27,9 @@ import ghidra.trace.model.thread.TraceThread;
|
||||
public interface TraceBookmarkManager extends TraceBookmarkOperations {
|
||||
TraceBookmarkSpace getBookmarkSpace(AddressSpace space, boolean createIfAbsent);
|
||||
|
||||
TraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceThread thread, boolean createIfAbsent);
|
||||
TraceBookmarkSpace getBookmarkRegisterSpace(TraceThread thread, boolean createIfAbsent);
|
||||
|
||||
TraceBookmarkRegisterSpace getBookmarkRegisterSpace(TraceStackFrame frame,
|
||||
TraceBookmarkSpace getBookmarkRegisterSpace(TraceStackFrame frame,
|
||||
boolean createIfAbsent);
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -15,11 +15,30 @@
|
||||
*/
|
||||
package ghidra.trace.model.bookmark;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceRegisterUtils;
|
||||
|
||||
public interface TraceBookmarkSpace extends TraceBookmarkOperations {
|
||||
AddressSpace getAddressSpace();
|
||||
|
||||
TraceThread getThread();
|
||||
|
||||
default TraceBookmark addBookmark(Range<Long> lifespan, Register register,
|
||||
TraceBookmarkType type, String category, String comment) {
|
||||
return addBookmark(lifespan, register.getAddress(), type, category, comment);
|
||||
}
|
||||
|
||||
default Iterable<? extends TraceBookmark> getBookmarksEnclosed(Range<Long> lifespan,
|
||||
Register register) {
|
||||
return getBookmarksEnclosed(lifespan, TraceRegisterUtils.rangeForRegister(register));
|
||||
}
|
||||
|
||||
default Iterable<? extends TraceBookmark> getBookmarksIntersecting(Range<Long> lifespan,
|
||||
Register register) {
|
||||
return getBookmarksIntersecting(lifespan, TraceRegisterUtils.rangeForRegister(register));
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -15,17 +15,23 @@
|
||||
*/
|
||||
package ghidra.trace.model.listing;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceRegisterUtils;
|
||||
import ghidra.util.IntersectionAddressSetView;
|
||||
import ghidra.util.UnionAddressSetView;
|
||||
|
||||
/**
|
||||
* A view of code units stored in a trace, possibly restricted to a particular subset by type,
|
||||
* address space, and/or thread.
|
||||
* address space, or thread and frame.
|
||||
*
|
||||
* @param <T> the type of units in the view
|
||||
*/
|
||||
@ -38,6 +44,20 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
*/
|
||||
Trace getTrace();
|
||||
|
||||
/**
|
||||
* Get the associated thread, if applicable
|
||||
*
|
||||
* @return the thread, or null
|
||||
*/
|
||||
TraceThread getThread();
|
||||
|
||||
/**
|
||||
* Get the associated frame level, if applicable
|
||||
*
|
||||
* @return the frame level, or 0
|
||||
*/
|
||||
int getFrameLevel();
|
||||
|
||||
/**
|
||||
* Get the total number of <em>defined</em> units in this view
|
||||
*
|
||||
@ -162,6 +182,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
/**
|
||||
* Get all addresses contained by live units at the given snap
|
||||
*
|
||||
* <p>
|
||||
* Note that the ranges in this set may not be coalesced. If a coalesced set is required, wrap
|
||||
* it with {@link UnionAddressSetView}.
|
||||
*
|
||||
@ -173,10 +194,11 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
/**
|
||||
* Get all addresses contained by live units at the given snap, within a restricted range
|
||||
*
|
||||
* <p>
|
||||
* Note that the ranges in this set may not be coalesced. If a coalesced set is required, wrap
|
||||
* it with {@link UnionAddressSetView}. The returned ranges are not necessarily enclosed by
|
||||
* -within-, but they will intersect it. If strict enclosure is required, wrap the set with
|
||||
* {@link IntersectionAddressSetView}.
|
||||
* {@code within}, but they will intersect it. If strict enclosure is required, wrap the set
|
||||
* with {@link IntersectionAddressSetView}.
|
||||
*
|
||||
* @param snap the snap during which the units must be alive
|
||||
* @param within the range to restrict the view
|
||||
@ -196,6 +218,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
/**
|
||||
* Check if the given span of snaps and range of addresses is covered by the units
|
||||
*
|
||||
* <p>
|
||||
* This checks if every (snap, address) point within the given box is contained within some code
|
||||
* unit in this view.
|
||||
*
|
||||
@ -208,6 +231,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
/**
|
||||
* Check if the given address-snap range is covered by the units
|
||||
*
|
||||
* <p>
|
||||
* This checks if every (snap, address) point within the given box is contained within some code
|
||||
* unit in this view.
|
||||
*
|
||||
@ -219,6 +243,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
/**
|
||||
* Check if the given span of snaps and range of addresses intersects any unit
|
||||
*
|
||||
* <p>
|
||||
* This checks if any (snap, address) point within the given box is contained within some code
|
||||
* unit in this view.
|
||||
*
|
||||
@ -231,6 +256,7 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
/**
|
||||
* Check if the given span of snaps and range of addresses intersects any unit
|
||||
*
|
||||
* <p>
|
||||
* This checks if any (snap, address) point within the given box is contained within some code
|
||||
* unit in this view.
|
||||
*
|
||||
@ -239,4 +265,77 @@ public interface TraceBaseCodeUnitsView<T extends TraceCodeUnit> {
|
||||
* @return true if intersecting, false otherwise
|
||||
*/
|
||||
boolean intersectsRange(TraceAddressSnapRange range);
|
||||
|
||||
/**
|
||||
* Get the set of registers for the trace's base language
|
||||
*
|
||||
* @return the register set
|
||||
*/
|
||||
default Set<Register> getRegisters() {
|
||||
return new HashSet<>(getTrace().getBaseLanguage().getRegisters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit (or component of a structure) which spans exactly the addresses of the given
|
||||
* register
|
||||
*
|
||||
* @param register the register
|
||||
* @return the unit or {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default T getForRegister(long snap, Register register) {
|
||||
// Find a code unit which contains the register completely
|
||||
T candidate = getContaining(snap, register.getAddress());
|
||||
if (candidate == null) {
|
||||
return null;
|
||||
}
|
||||
AddressRange range = TraceRegisterUtils.rangeForRegister(register);
|
||||
int cmpMax = range.getMaxAddress().compareTo(candidate.getMaxAddress());
|
||||
if (cmpMax > 0) {
|
||||
return null;
|
||||
}
|
||||
if (cmpMax == 0 && candidate.getMinAddress().equals(register.getAddress())) {
|
||||
return candidate;
|
||||
}
|
||||
if (!(candidate instanceof TraceData)) {
|
||||
return null;
|
||||
}
|
||||
TraceData data = (TraceData) candidate;
|
||||
// Cast because if candidate is TraceData, T is, too
|
||||
// NOTE: It may not be a primitive
|
||||
return (T) TraceRegisterUtils.seekComponent(data, range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit which completely contains the given register
|
||||
*
|
||||
* <p>
|
||||
* This does not descend into structures.
|
||||
*
|
||||
* @param register the register
|
||||
* @return the unit or {@code unit}
|
||||
*/
|
||||
default T getContaining(long snap, Register register) {
|
||||
T candidate = getContaining(snap, register.getAddress());
|
||||
if (candidate == null) {
|
||||
return null;
|
||||
}
|
||||
AddressRange range = TraceRegisterUtils.rangeForRegister(register);
|
||||
int cmpMax = range.getMaxAddress().compareTo(candidate.getMaxAddress());
|
||||
if (cmpMax > 0) {
|
||||
return null;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the live units whose start addresses are within the given register
|
||||
*
|
||||
* @param register the register
|
||||
* @param forward true to order the units by increasing address, false for descending
|
||||
* @return the iterable of units
|
||||
*/
|
||||
default Iterable<? extends T> get(long snap, Register register, boolean forward) {
|
||||
return get(snap, TraceRegisterUtils.rangeForRegister(register), forward);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user