mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-5194: Remove Deprecated 'Legacy mode' for DBTrace.
This commit is contained in:
parent
8367ac7354
commit
7e7c8a5e86
312 changed files with 5925 additions and 9830 deletions
|
@ -21,16 +21,16 @@ import java.util.function.BiFunction;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpoint;
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener;
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpoint.State;
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.CodeUnitLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
|
||||
@ServiceInfo(
|
||||
|
@ -99,10 +99,10 @@ public interface DebuggerLogicalBreakpointService {
|
|||
* If the given trace breakpoint is not part of any logical breakpoint, e.g., because the trace
|
||||
* is not opened in the tool or events are still being processed, then null is returned.
|
||||
*
|
||||
* @param bpt the trace breakpoint
|
||||
* @param loc the trace breakpoint location
|
||||
* @return the logical breakpoint, or null
|
||||
*/
|
||||
LogicalBreakpoint getBreakpoint(TraceBreakpoint bpt);
|
||||
LogicalBreakpoint getBreakpoint(TraceBreakpointLocation loc);
|
||||
|
||||
/**
|
||||
* Get the collected logical breakpoints (at present) at the given location.
|
||||
|
@ -297,10 +297,10 @@ public interface DebuggerLogicalBreakpointService {
|
|||
*
|
||||
* <p>
|
||||
* If the given location refers to a static image, this behaves as in
|
||||
* {@link #placeBreakpointAt(Program, Address, TraceBreakpointKind)}. If it refers to a trace
|
||||
* view, this behaves as in {@link #placeBreakpointAt(Trace, Address, TraceBreakpointKind)},
|
||||
* ignoring the view's current snapshot in favor of the present. The name is only saved for a
|
||||
* program breakpoint.
|
||||
* {@link #placeBreakpointAt(Program, Address, long, Collection, String)}. If it refers to a
|
||||
* trace view, this behaves as in *
|
||||
* {@link #placeBreakpointAt(Trace, Address, long, Collection, String)}, ignoring the view's
|
||||
* current snapshot in favor of the present. The name is only saved for a program breakpoint.
|
||||
*
|
||||
* @param loc the location
|
||||
* @param length size of the breakpoint, may be ignored by debugger
|
||||
|
@ -348,7 +348,7 @@ public interface DebuggerLogicalBreakpointService {
|
|||
/**
|
||||
* Disable a collection of logical breakpoints on target, if applicable
|
||||
*
|
||||
* @see #enableAll(Collection)
|
||||
* @see #enableAll(Collection, Trace)
|
||||
* @param col the collection
|
||||
* @param trace a trace, if the command should be limited to the given trace
|
||||
* @return a future which completes when all associated specifications have been disabled
|
||||
|
@ -358,7 +358,7 @@ public interface DebuggerLogicalBreakpointService {
|
|||
/**
|
||||
* Delete, if possible, a collection of logical breakpoints on target, if applicable
|
||||
*
|
||||
* @see #enableAll(Collection)
|
||||
* @see #enableAll(Collection, Trace)
|
||||
* @param col the collection
|
||||
* @param trace a trace, if the command should be limited to the given trace
|
||||
* @return a future which completes when all associated specifications have been deleted
|
||||
|
@ -371,7 +371,7 @@ public interface DebuggerLogicalBreakpointService {
|
|||
* @param col the trace breakpoints
|
||||
* @return a future which completes when the command has been processed
|
||||
*/
|
||||
CompletableFuture<Void> enableLocs(Collection<TraceBreakpoint> col);
|
||||
CompletableFuture<Void> enableLocs(Collection<TraceBreakpointLocation> col);
|
||||
|
||||
/**
|
||||
* Disable the given locations
|
||||
|
@ -379,7 +379,7 @@ public interface DebuggerLogicalBreakpointService {
|
|||
* @param col the trace breakpoints
|
||||
* @return a future which completes when the command has been processed
|
||||
*/
|
||||
CompletableFuture<Void> disableLocs(Collection<TraceBreakpoint> col);
|
||||
CompletableFuture<Void> disableLocs(Collection<TraceBreakpointLocation> col);
|
||||
|
||||
/**
|
||||
* Delete the given locations
|
||||
|
@ -387,7 +387,7 @@ public interface DebuggerLogicalBreakpointService {
|
|||
* @param col the trace breakpoints
|
||||
* @return a future which completes when the command has been processed
|
||||
*/
|
||||
CompletableFuture<Void> deleteLocs(Collection<TraceBreakpoint> col);
|
||||
CompletableFuture<Void> deleteLocs(Collection<TraceBreakpointLocation> col);
|
||||
|
||||
/**
|
||||
* Generate an informational message when toggling the breakpoints
|
||||
|
@ -397,7 +397,8 @@ public interface DebuggerLogicalBreakpointService {
|
|||
* is for toggling breakpoints. If the breakpoint set is empty, this should return null, since
|
||||
* the usual behavior in that case is to prompt to place a new breakpoint.
|
||||
*
|
||||
* @see #generateStatusEnable(Collection, Trace))
|
||||
* @see #generateStatusEnable(Collection, Trace)
|
||||
* @param bs the set of logical breakpoints
|
||||
* @param loc a representative location
|
||||
* @return the status message, or null
|
||||
*/
|
||||
|
@ -407,12 +408,12 @@ public interface DebuggerLogicalBreakpointService {
|
|||
* Generate an informational message when toggling the breakpoints at the given location
|
||||
*
|
||||
* <p>
|
||||
* This works in the same manner as {@link #generateStatusEnable(Collection, Trace))}, except it
|
||||
* This works in the same manner as {@link #generateStatusEnable(Collection, Trace)}, except it
|
||||
* is for toggling breakpoints at a given location. If there are no breakpoints at the location,
|
||||
* this should return null, since the usual behavior in that case is to prompt to place a new
|
||||
* breakpoint.
|
||||
*
|
||||
* @see #generateStatusEnable(Collection)
|
||||
* @see #generateStatusEnable(Collection, Trace)
|
||||
* @param loc the location
|
||||
* @return the status message, or null
|
||||
*/
|
||||
|
|
|
@ -18,11 +18,11 @@ package ghidra.debug.api.action;
|
|||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* The actual tracking logic for a location tracking spec
|
||||
|
@ -73,8 +73,8 @@ public interface LocationTracker {
|
|||
* @param coordinates the provider's current coordinates
|
||||
* @return true if re-computation and "goto" is warranted
|
||||
*/
|
||||
boolean affectedByBytesChange(TraceAddressSpace space,
|
||||
TraceAddressSnapRange range, DebuggerCoordinates coordinates);
|
||||
boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates);
|
||||
|
||||
/**
|
||||
* Check if the address should be recomputed given the indicated stack change
|
||||
|
|
|
@ -20,9 +20,8 @@ import javax.swing.Icon;
|
|||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* A specification for automatic navigation of the dynamic listing
|
||||
|
@ -67,21 +66,13 @@ public interface LocationTrackingSpec {
|
|||
* @param current the current coordinates
|
||||
* @return true if the change affects the tracked address for the given coordinates
|
||||
*/
|
||||
static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
static boolean changeIsCurrent(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates current) {
|
||||
if (space == null) {
|
||||
return false;
|
||||
}
|
||||
if (!space.getAddressSpace().isMemorySpace()) {
|
||||
if (current.getThread() == null) {
|
||||
return false;
|
||||
}
|
||||
TraceMemorySpace memSpace = current.getTrace()
|
||||
.getMemoryManager()
|
||||
.getMemoryRegisterSpace(current.getThread(), current.getFrame(), false);
|
||||
if (memSpace == null || memSpace.getAddressSpace() != space.getAddressSpace()) {
|
||||
return false;
|
||||
}
|
||||
if (!space.isMemorySpace() && !current.isRegisterSpace(space)) {
|
||||
return false;
|
||||
}
|
||||
if (!range.getLifespan().contains(current.getSnap())) {
|
||||
return false;
|
||||
|
|
|
@ -28,8 +28,8 @@ import ghidra.program.model.listing.Bookmark;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import resources.MultiIcon;
|
||||
|
||||
/**
|
||||
|
@ -471,6 +471,8 @@ public interface LogicalBreakpoint {
|
|||
*/
|
||||
INCONSISTENT_MIXED(Mode.MIXED, Consistency.INCONSISTENT, NAME_MARKER_INCON_MIX, ICON_MARKER_INCON_MIX);
|
||||
|
||||
public static final List<State> VALUES = List.of(values());
|
||||
|
||||
public final Mode mode;
|
||||
public final Consistency consistency;
|
||||
public final String display;
|
||||
|
@ -658,7 +660,7 @@ public interface LogicalBreakpoint {
|
|||
* Get the sleigh injection when emulating this breakpoint
|
||||
*
|
||||
* @return the sleigh injection
|
||||
* @see TraceBreakpoint#getEmuSleigh()
|
||||
* @see TraceBreakpointLocation#getEmuSleigh(long)
|
||||
*/
|
||||
String getEmuSleigh();
|
||||
|
||||
|
@ -666,7 +668,7 @@ public interface LogicalBreakpoint {
|
|||
* Set the sleigh injection when emulating this breakpoint
|
||||
*
|
||||
* @param sleigh the sleigh injection
|
||||
* @see TraceBreakpoint#setEmuSleigh(String)
|
||||
* @see TraceBreakpointLocation#setEmuSleigh(long,String)
|
||||
*/
|
||||
void setEmuSleigh(String sleigh);
|
||||
|
||||
|
@ -699,7 +701,7 @@ public interface LogicalBreakpoint {
|
|||
*
|
||||
* @return the set of trace breakpoints
|
||||
*/
|
||||
Set<TraceBreakpoint> getTraceBreakpoints();
|
||||
Set<TraceBreakpointLocation> getTraceBreakpoints();
|
||||
|
||||
/**
|
||||
* Get all trace breakpoints for the given trace which map to this logical breakpoint.
|
||||
|
@ -707,15 +709,15 @@ public interface LogicalBreakpoint {
|
|||
* @param trace the trace
|
||||
* @return the set of trace breakpoints
|
||||
*/
|
||||
Set<TraceBreakpoint> getTraceBreakpoints(Trace trace);
|
||||
Set<TraceBreakpointLocation> getTraceBreakpoints(Trace trace);
|
||||
|
||||
/**
|
||||
* Get the traces for which this logical breakpoint has an address.
|
||||
*
|
||||
* <p>
|
||||
* Note, this does not necessarily indicate that a {@link TraceBreakpoint} is present for each
|
||||
* trace, but rather that for each returned trace, the logical breakpoint can be mapped to an
|
||||
* address in that trace. See {@link #getParticipatingTraces()}.
|
||||
* Note, this does not necessarily indicate that a {@link TraceBreakpointLocation} is present
|
||||
* for each trace, but rather that for each returned trace, the logical breakpoint can be mapped
|
||||
* to an address in that trace. See {@link #getParticipatingTraces()}.
|
||||
*
|
||||
* @return a copy of the set of traces
|
||||
*/
|
||||
|
@ -725,8 +727,8 @@ public interface LogicalBreakpoint {
|
|||
* Get the traces for which this logical breakpoint has a trace breakpoint.
|
||||
*
|
||||
* <p>
|
||||
* Note, unlike {@link #getMappedTraces()}, this does indicate that a {@link TraceBreakpoint} is
|
||||
* present for each trace.
|
||||
* Note, unlike {@link #getMappedTraces()}, this does indicate that a
|
||||
* {@link TraceBreakpointLocation} is present for each trace.
|
||||
*
|
||||
* @return the set of traces
|
||||
*/
|
||||
|
@ -779,7 +781,7 @@ public interface LogicalBreakpoint {
|
|||
* @param loc the location
|
||||
* @return the state
|
||||
*/
|
||||
State computeStateForLocation(TraceBreakpoint loc);
|
||||
State computeStateForLocation(TraceBreakpointLocation loc);
|
||||
|
||||
/**
|
||||
* Compute the state for all involved traces and program.
|
||||
|
|
|
@ -17,7 +17,7 @@ package ghidra.debug.api.breakpoint;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public interface LogicalBreakpointsChangeListener {
|
||||
default void breakpointAdded(LogicalBreakpoint added) {
|
||||
|
@ -47,12 +47,12 @@ public interface LogicalBreakpointsChangeListener {
|
|||
}
|
||||
}
|
||||
|
||||
default void locationAdded(TraceBreakpoint added) {
|
||||
default void locationAdded(TraceBreakpointLocation added) {
|
||||
}
|
||||
|
||||
default void locationUpdated(TraceBreakpoint updated) {
|
||||
default void locationUpdated(TraceBreakpointLocation updated) {
|
||||
}
|
||||
|
||||
default void locationRemoved(TraceBreakpoint removed) {
|
||||
default void locationRemoved(TraceBreakpointLocation removed) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,7 @@ import ghidra.program.model.lang.Register;
|
|||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceExecutionState;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
|
@ -617,12 +616,12 @@ public interface Target {
|
|||
* @param breakpoint the breakpoint
|
||||
* @return true if valid
|
||||
*/
|
||||
boolean isBreakpointValid(TraceBreakpoint breakpoint);
|
||||
boolean isBreakpointValid(TraceBreakpointLocation breakpoint);
|
||||
|
||||
/**
|
||||
* @see #deleteBreakpoint(TraceBreakpoint)
|
||||
* @see #deleteBreakpoint(TraceBreakpointCommon)
|
||||
*/
|
||||
CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpoint breakpoint);
|
||||
CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint);
|
||||
|
||||
/**
|
||||
* Delete the given breakpoint from the target
|
||||
|
@ -633,12 +632,13 @@ public interface Target {
|
|||
*
|
||||
* @param breakpoint the breakpoint to delete
|
||||
*/
|
||||
void deleteBreakpoint(TraceBreakpoint breakpoint);
|
||||
void deleteBreakpoint(TraceBreakpointCommon breakpoint);
|
||||
|
||||
/**
|
||||
* @see #toggleBreakpoint(TraceBreakpoint, boolean)
|
||||
* @see #toggleBreakpoint(TraceBreakpointLocation, boolean)
|
||||
*/
|
||||
CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpoint breakpoint, boolean enabled);
|
||||
CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint,
|
||||
boolean enabled);
|
||||
|
||||
/**
|
||||
* Toggle the given breakpoint on the target
|
||||
|
@ -651,7 +651,7 @@ public interface Target {
|
|||
* @param breakpoint the breakpoint to toggle
|
||||
* @param enabled true to enable, false to disable
|
||||
*/
|
||||
void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled);
|
||||
void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled);
|
||||
|
||||
/**
|
||||
* @see #forceTerminate()
|
||||
|
|
|
@ -27,15 +27,16 @@ import ghidra.framework.model.*;
|
|||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.trace.database.DBTraceContentHandler;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.stack.*;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
|
@ -315,36 +316,34 @@ public class DebuggerCoordinates {
|
|||
return thread(trace.getThreadManager().getThread(thread.getKey()));
|
||||
}
|
||||
|
||||
private static KeyPath resolvePath(TraceThread thread, Integer frameLevel,
|
||||
TraceSchedule time) {
|
||||
if (thread instanceof TraceObjectThread tot) {
|
||||
TraceObject objThread = tot.getObject();
|
||||
if (frameLevel == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStack stack;
|
||||
long snap = time.getSnap();
|
||||
try {
|
||||
stack = thread.getTrace().getStackManager().getStack(thread, snap, false);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
// Schema does not specify a stack
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
if (stack == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStackFrame frame = stack.getFrame(snap, frameLevel, false);
|
||||
if (frame == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
return ((TraceObjectStackFrame) frame).getObject().getCanonicalPath();
|
||||
private static KeyPath resolvePath(TraceThread thread, Integer frameLevel, TraceSchedule time) {
|
||||
if (thread == null) {
|
||||
return KeyPath.of();
|
||||
}
|
||||
return null;
|
||||
TraceObject objThread = thread.getObject();
|
||||
if (frameLevel == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStack stack;
|
||||
long snap = time.getSnap();
|
||||
try {
|
||||
stack = thread.getTrace().getStackManager().getStack(thread, snap, false);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
// Schema does not specify a stack
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
if (stack == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStackFrame frame = stack.getFrame(snap, frameLevel, false);
|
||||
if (frame == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
return frame.getObject().getCanonicalPath();
|
||||
}
|
||||
|
||||
private static KeyPath choose(KeyPath curPath,
|
||||
KeyPath newPath) {
|
||||
private static KeyPath choose(KeyPath curPath, KeyPath newPath) {
|
||||
if (curPath == null) {
|
||||
return newPath;
|
||||
}
|
||||
|
@ -525,9 +524,7 @@ public class DebuggerCoordinates {
|
|||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
return object.queryCanonicalAncestorsInterface(TraceObjectThread.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return object.queryCanonicalAncestorsInterface(TraceThread.class).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private static Integer resolveFrame(Trace trace, KeyPath path) {
|
||||
|
@ -535,10 +532,9 @@ public class DebuggerCoordinates {
|
|||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
TraceObjectStackFrame frame =
|
||||
object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
TraceStackFrame frame = object.queryCanonicalAncestorsInterface(TraceStackFrame.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return frame == null ? null : frame.getLevel();
|
||||
}
|
||||
|
||||
|
@ -669,6 +665,11 @@ public class DebuggerCoordinates {
|
|||
return registerContainer = object.findRegisterContainer(getFrame());
|
||||
}
|
||||
|
||||
public boolean isRegisterSpace(AddressSpace space) {
|
||||
TraceObject container = getRegisterContainer();
|
||||
return container != null && container.getCanonicalPath().toString().equals(space.getName());
|
||||
}
|
||||
|
||||
public synchronized long getViewSnap() {
|
||||
if (viewSnap != null) {
|
||||
return viewSnap;
|
||||
|
|
|
@ -53,7 +53,6 @@ import ghidra.trace.model.program.TraceProgramView;
|
|||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import ghidra.util.MathUtilities;
|
||||
|
@ -1452,11 +1451,7 @@ public interface FlatDebuggerAPI {
|
|||
}
|
||||
|
||||
default ActionContext createContext(TraceThread thread) {
|
||||
if (thread instanceof TraceObjectThread objThread) {
|
||||
return createContext(objThread.getObject());
|
||||
}
|
||||
return new DebuggerSingleObjectPathActionContext(
|
||||
KeyPath.parse(thread.getPath()));
|
||||
return createContext(thread.getObject());
|
||||
}
|
||||
|
||||
default ActionContext createContext(Trace trace) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.Map;
|
|||
import com.sun.jdi.*;
|
||||
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.*;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceRmiMethod;
|
||||
import ghidra.dbg.jdi.manager.impl.DebugStatus;
|
||||
import ghidra.dbg.jdi.manager.impl.JdiManagerImpl;
|
||||
import ghidra.program.model.address.*;
|
||||
|
@ -144,7 +144,7 @@ public class JdiConnector {
|
|||
}
|
||||
|
||||
public void registerRemoteMethod(JdiMethods methods, java.lang.reflect.Method m, String name) {
|
||||
TraceMethod annot = m.getAnnotation(TraceMethod.class);
|
||||
TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class);
|
||||
if (annot == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@ import com.sun.jdi.*;
|
|||
import com.sun.jdi.request.*;
|
||||
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.*;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceRmiMethod;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.rmi.trace.TraceRmi.MemoryState;
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.Param;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.Param;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public class JdiMethods implements RmiMethods {
|
||||
|
@ -45,14 +45,14 @@ public class JdiMethods implements RmiMethods {
|
|||
public void registerMethods() {
|
||||
Class<?> cls = this.getClass();
|
||||
for (java.lang.reflect.Method m : cls.getMethods()) {
|
||||
TraceMethod annot = m.getAnnotation(TraceMethod.class);
|
||||
TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class);
|
||||
if (annot != null) {
|
||||
connector.registerRemoteMethod(this, m, m.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh VM")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh VM")
|
||||
public void refresh_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVM")) {
|
||||
String path = obj.getPath();
|
||||
|
@ -61,7 +61,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh process")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh process")
|
||||
public void refresh_process(
|
||||
@Param(schema = "ProcessRef", name = "process") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshProcess")) {
|
||||
|
@ -71,7 +71,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread groups")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread groups")
|
||||
public void refresh_thread_groups(
|
||||
@Param(
|
||||
schema = "ThreadGroupReferenceContainer",
|
||||
|
@ -89,7 +89,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread group")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread group")
|
||||
public void refresh_thread_group_proxy(
|
||||
@Param(schema = "ThreadGroupReferenceProxy", name = "proxy") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) {
|
||||
|
@ -105,7 +105,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread group")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread group")
|
||||
public void refresh_thread_group(
|
||||
@Param(schema = "ThreadGroupReference", name = "group") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) {
|
||||
|
@ -115,7 +115,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh threads")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh threads")
|
||||
public void refresh_threads(
|
||||
@Param(schema = "ThreadContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) {
|
||||
|
@ -126,7 +126,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh threads")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh threads")
|
||||
public void refresh_threadrefs(
|
||||
@Param(schema = "ThreadReferenceContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) {
|
||||
|
@ -147,7 +147,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread")
|
||||
public void refresh_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThread")) {
|
||||
String path = obj.getPath();
|
||||
|
@ -156,14 +156,14 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh stack")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh stack")
|
||||
public void refresh_stack(@Param(schema = "Stack", name = "stack") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshStack")) {
|
||||
cmds.ghidraTracePutFrames();
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh registers")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh registers")
|
||||
public void refresh_registers(
|
||||
@Param(schema = "RegisterContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshRegisters")) {
|
||||
|
@ -171,7 +171,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh modules")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh modules")
|
||||
public void refresh_modules(
|
||||
@Param(schema = "ModuleReferenceContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModules")) {
|
||||
|
@ -179,7 +179,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh module")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh module")
|
||||
public void refresh_module(
|
||||
@Param(schema = "ModuleReference", name = "module") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModule")) {
|
||||
|
@ -189,7 +189,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh monitor info")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh monitor info")
|
||||
public void refresh_monitors(
|
||||
@Param(schema = "MonitorInfoContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) {
|
||||
|
@ -203,7 +203,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh monitor info")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh monitor info")
|
||||
public void refresh_monitor_info(
|
||||
@Param(schema = "MonitorInfo", name = "monitor_info") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) {
|
||||
|
@ -213,13 +213,13 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh fields")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh fields")
|
||||
public void refresh_canonical_fields(
|
||||
@Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) {
|
||||
refresh_fields(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh fields")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh fields")
|
||||
public void refresh_fields(
|
||||
@Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshFields")) {
|
||||
|
@ -235,7 +235,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh objects")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh objects")
|
||||
public void refresh_objects(
|
||||
@Param(schema = "ObjectReferenceContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObjects")) {
|
||||
|
@ -261,7 +261,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh object")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh object")
|
||||
public void refresh_object_proxy(
|
||||
@Param(schema = "ObjectReferenceProxy", name = "proxy") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObject")) {
|
||||
|
@ -283,7 +283,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh object")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh object")
|
||||
public void refresh_object(
|
||||
@Param(schema = "ObjectReference", name = "object") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshInstance")) {
|
||||
|
@ -293,13 +293,13 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh methods")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh methods")
|
||||
public void refresh_canonical_methods(
|
||||
@Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) {
|
||||
refresh_methods(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh methods")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh methods")
|
||||
public void refresh_methods(
|
||||
@Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethods")) {
|
||||
|
@ -310,7 +310,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh method")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh method")
|
||||
public void refresh_method(@Param(schema = "Method", name = "method") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethod")) {
|
||||
String path = obj.getPath();
|
||||
|
@ -319,7 +319,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh arguments")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh arguments")
|
||||
public void refresh_arguments(
|
||||
@Param(schema = "ArgumentContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshArguments")) {
|
||||
|
@ -330,7 +330,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Load class")
|
||||
@TraceRmiMethod(display = "Load class")
|
||||
public boolean find_canonical_class(
|
||||
@Param(
|
||||
schema = "CanonicalReferenceTypeContainer",
|
||||
|
@ -344,7 +344,7 @@ public class JdiMethods implements RmiMethods {
|
|||
return find_class(obj, targetClass);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Load class")
|
||||
@TraceRmiMethod(display = "Load class")
|
||||
public boolean find_class(
|
||||
@Param(
|
||||
schema = "ReferenceTypeContainer",
|
||||
|
@ -370,12 +370,12 @@ public class JdiMethods implements RmiMethods {
|
|||
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action
|
||||
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
|
||||
*/
|
||||
@TraceMethod(display = "Refresh memory")
|
||||
@TraceRmiMethod(display = "Refresh memory")
|
||||
public void refresh_memory(@Param(schema = "Memory", name = "memory") RmiTraceObject obj) {
|
||||
refresh_reference_types(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Refresh reference types")
|
||||
@TraceRmiMethod(display = "Refresh reference types")
|
||||
public void refresh_canonical_reference_types(
|
||||
@Param(
|
||||
schema = "CanonicalReferenceTypeContainer",
|
||||
|
@ -387,7 +387,7 @@ public class JdiMethods implements RmiMethods {
|
|||
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action
|
||||
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
|
||||
*/
|
||||
@TraceMethod(display = "Refresh reference types")
|
||||
@TraceRmiMethod(display = "Refresh reference types")
|
||||
public void refresh_reference_types(
|
||||
@Param(schema = "ReferenceTypeContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceTypes")) {
|
||||
|
@ -430,7 +430,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh reference type")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh reference type")
|
||||
public void refresh_reference_type_proxy(
|
||||
@Param(schema = "ReferenceTypeProxy", name = "proxy") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
|
||||
|
@ -452,13 +452,13 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh reference type")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh reference type")
|
||||
public void refresh_canonical_reference_type(
|
||||
@Param(schema = "CanonicalReferenceType", name = "container") RmiTraceObject obj) {
|
||||
refresh_reference_type(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh reference type")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh reference type")
|
||||
public void refresh_reference_type(
|
||||
@Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
|
||||
|
@ -468,7 +468,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Load reference type")
|
||||
@TraceRmiMethod(display = "Load reference type")
|
||||
public void load_reftype(
|
||||
@Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
|
||||
|
@ -480,13 +480,13 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh variables")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh variables")
|
||||
public void refresh_canonical_variables(
|
||||
@Param(schema = "CanonicalVariableContainer", name = "container") RmiTraceObject obj) {
|
||||
refresh_variables(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh variables")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh variables")
|
||||
public void refresh_variables(
|
||||
@Param(schema = "VariableContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariables")) {
|
||||
|
@ -513,7 +513,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh variable")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh variable")
|
||||
public void refresh_variable(
|
||||
@Param(schema = "Variable", name = "variable") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariable")) {
|
||||
|
@ -525,7 +525,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh locations")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh locations")
|
||||
public void refresh_locations(
|
||||
@Param(schema = "LocationContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocations")) {
|
||||
|
@ -543,7 +543,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh location")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh location")
|
||||
public void refresh_location(
|
||||
@Param(schema = "Location", name = "location") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) {
|
||||
|
@ -553,7 +553,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh breakpoints")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh breakpoints")
|
||||
public void refresh_breakpoints(
|
||||
@Param(schema = "BreakpointContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshBreakpoints")) {
|
||||
|
@ -561,7 +561,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh events")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh events")
|
||||
public void refresh_events(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshEvents")) {
|
||||
|
@ -569,7 +569,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh values")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh values")
|
||||
public void refresh_values(
|
||||
@Param(schema = "ValueContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshValues")) {
|
||||
|
@ -582,7 +582,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh value")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh value")
|
||||
public void refresh_value(@Param(schema = "Value", name = "value") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) {
|
||||
String path = obj.getPath();
|
||||
|
@ -591,7 +591,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set value")
|
||||
@TraceRmiMethod(display = "Set value")
|
||||
public void set_value_lvar(
|
||||
@Param(
|
||||
schema = "Variable",
|
||||
|
@ -609,7 +609,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set value")
|
||||
@TraceRmiMethod(display = "Set value")
|
||||
public void set_value_field(
|
||||
@Param(
|
||||
schema = "Field",
|
||||
|
@ -627,7 +627,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "activate", display = "Activate")
|
||||
@TraceRmiMethod(action = "activate", display = "Activate")
|
||||
public void activate(@Param(schema = "OBJECT", name = "object") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("Activate")) {
|
||||
String path = obj.getPath();
|
||||
|
@ -635,7 +635,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "kill", display = "Terminate")
|
||||
@TraceRmiMethod(action = "kill", display = "Terminate")
|
||||
public void kill(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
|
||||
vm.exit(143);
|
||||
|
@ -647,28 +647,28 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "resume", display = "Resume")
|
||||
@TraceRmiMethod(action = "resume", display = "Resume")
|
||||
public void resume_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
|
||||
vm.resume();
|
||||
connector.getHooks().setState(vm);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "resume", display = "Resume")
|
||||
@TraceRmiMethod(action = "resume", display = "Resume")
|
||||
public void resume_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
thread.resume();
|
||||
connector.getHooks().setState(thread.virtualMachine());
|
||||
}
|
||||
|
||||
@TraceMethod(action = "interrupt", display = "Suspend")
|
||||
@TraceRmiMethod(action = "interrupt", display = "Suspend")
|
||||
public void suspend_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
|
||||
vm.suspend();
|
||||
connector.getHooks().setState(vm);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "interrupt", display = "Suspend")
|
||||
@TraceRmiMethod(action = "interrupt", display = "Suspend")
|
||||
public void suspend_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
thread.suspend();
|
||||
|
@ -679,7 +679,7 @@ public class JdiMethods implements RmiMethods {
|
|||
* NB: For the VirtualMachine, the step methods add requests for break-on-step for all threads.
|
||||
* These requests will remain pending until the VM is resumed.
|
||||
*/
|
||||
@TraceMethod(action = "step_into", display = "Step into")
|
||||
@TraceRmiMethod(action = "step_into", display = "Step into")
|
||||
public void step_vm_into(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
List<ThreadReference> threads = getThreadsFromValue(obj);
|
||||
|
@ -697,7 +697,7 @@ public class JdiMethods implements RmiMethods {
|
|||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_over", display = "Step over")
|
||||
@TraceRmiMethod(action = "step_over", display = "Step over")
|
||||
public void step_vm_over(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
List<ThreadReference> threads = getThreadsFromValue(obj);
|
||||
|
@ -715,7 +715,7 @@ public class JdiMethods implements RmiMethods {
|
|||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_out", display = "Step out")
|
||||
@TraceRmiMethod(action = "step_out", display = "Step out")
|
||||
public void step_vm_out(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
List<ThreadReference> threads = getThreadsFromValue(obj);
|
||||
|
@ -733,7 +733,7 @@ public class JdiMethods implements RmiMethods {
|
|||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_into", display = "Step into")
|
||||
@TraceRmiMethod(action = "step_into", display = "Step into")
|
||||
public void step_into(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
|
@ -744,7 +744,7 @@ public class JdiMethods implements RmiMethods {
|
|||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_over", display = "Step over")
|
||||
@TraceRmiMethod(action = "step_over", display = "Step over")
|
||||
public void step_over(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
|
@ -755,7 +755,7 @@ public class JdiMethods implements RmiMethods {
|
|||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_out", display = "Step out")
|
||||
@TraceRmiMethod(action = "step_out", display = "Step out")
|
||||
public void step_out(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
|
@ -766,7 +766,7 @@ public class JdiMethods implements RmiMethods {
|
|||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Thread Interrupt")
|
||||
@TraceRmiMethod(display = "Thread Interrupt")
|
||||
public void thread_interrupt(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
Object object = getObjectFromPath(obj.getPath());
|
||||
if (object instanceof ThreadReference thread) {
|
||||
|
@ -775,7 +775,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_ext", display = "Pop stack")
|
||||
@TraceRmiMethod(action = "step_ext", display = "Pop stack")
|
||||
public void pop_stack(@Param(schema = "StackFrame", name = "frame") RmiTraceObject obj) {
|
||||
StackFrame frame = (StackFrame) getObjectFromPath(obj.getPath());
|
||||
ThreadReference thread = frame.thread();
|
||||
|
@ -787,7 +787,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on execute")
|
||||
@TraceRmiMethod(display = "Break on execute")
|
||||
public void break_location(@Param(schema = "Location", name = "location") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
|
@ -799,7 +799,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on access")
|
||||
@TraceRmiMethod(display = "Break on access")
|
||||
public void break_access(@Param(schema = "Field", name = "field") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
|
@ -811,7 +811,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on modify")
|
||||
@TraceRmiMethod(display = "Break on modify")
|
||||
public void break_modify(@Param(schema = "Field", name = "field") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
|
@ -823,7 +823,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on exception")
|
||||
@TraceRmiMethod(display = "Break on exception")
|
||||
public void break_exception(
|
||||
@Param(
|
||||
schema = "ReferenceType",
|
||||
|
@ -861,13 +861,13 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread start")
|
||||
@TraceRmiMethod(display = "Break on thread start")
|
||||
public void break_started_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_started(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread start")
|
||||
@TraceRmiMethod(display = "Break on thread start")
|
||||
public void break_started_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_started(obj);
|
||||
|
@ -886,18 +886,18 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread exit")
|
||||
@TraceRmiMethod(display = "Break on thread exit")
|
||||
public void break_death_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_death(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread exit")
|
||||
@TraceRmiMethod(display = "Break on thread exit")
|
||||
public void break_death_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_death(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on VM death")
|
||||
@TraceRmiMethod(display = "Break on VM death")
|
||||
public void break_vm_death(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
VMDeathRequest brkReq = vm.eventRequestManager()
|
||||
|
@ -927,25 +927,25 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
@ -971,25 +971,25 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
@ -1007,13 +1007,13 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on class load")
|
||||
@TraceRmiMethod(display = "Break on class load")
|
||||
public void break_load_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_load(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on class load")
|
||||
@TraceRmiMethod(display = "Break on class load")
|
||||
public void break_load_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_load(obj);
|
||||
|
@ -1027,7 +1027,7 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on class unload")
|
||||
@TraceRmiMethod(display = "Break on class unload")
|
||||
public void break_unload_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_unload(obj);
|
||||
|
@ -1054,25 +1054,25 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
|
@ -1099,25 +1099,25 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
|
@ -1144,25 +1144,25 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
|
@ -1189,31 +1189,31 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Add count filter")
|
||||
@TraceRmiMethod(display = "Add count filter")
|
||||
public void add_count_filter(
|
||||
@Param(
|
||||
schema = "Event",
|
||||
|
@ -1234,7 +1234,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set class filter")
|
||||
@TraceRmiMethod(display = "Set class filter")
|
||||
public void set_class_filter(
|
||||
@Param(
|
||||
schema = "Event",
|
||||
|
@ -1349,7 +1349,7 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set source filter")
|
||||
@TraceRmiMethod(display = "Set source filter")
|
||||
public void set_source_filter(
|
||||
@Param(
|
||||
schema = "Event",
|
||||
|
@ -1370,7 +1370,7 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set platform filter")
|
||||
@TraceRmiMethod(display = "Set platform filter")
|
||||
public void set_platform_filter(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
if (ctxt instanceof ThreadStartRequest req) {
|
||||
|
@ -1388,7 +1388,7 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle breakpoint")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle breakpoint")
|
||||
public void toggle_breakpoint(
|
||||
@Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
|
@ -1409,7 +1409,7 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putBreakpoints();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "delete", display = "Delete breakpoint")
|
||||
@TraceRmiMethod(action = "delete", display = "Delete breakpoint")
|
||||
public void delete_breakpoint(
|
||||
@Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
|
@ -1420,7 +1420,7 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putBreakpoints();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle event")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle event")
|
||||
public void toggle_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
if (ctxt instanceof EventRequest req) {
|
||||
|
@ -1434,7 +1434,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "delete", display = "Delete Event")
|
||||
@TraceRmiMethod(action = "delete", display = "Delete Event")
|
||||
public void delete_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
|
@ -1444,13 +1444,13 @@ public class JdiMethods implements RmiMethods {
|
|||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_canonical_methods(
|
||||
@Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) {
|
||||
toggle_scope_methods(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_methods(
|
||||
@Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) {
|
||||
String ppath = cmds.getParentPath(obj.getPath());
|
||||
|
@ -1459,13 +1459,13 @@ public class JdiMethods implements RmiMethods {
|
|||
refresh_methods(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_canonical_fields(
|
||||
@Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) {
|
||||
toggle_scope_fields(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_fields(
|
||||
@Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) {
|
||||
String ppath = cmds.getParentPath(obj.getPath());
|
||||
|
@ -1479,7 +1479,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "read_mem", display = "Read Memory")
|
||||
@TraceRmiMethod(action = "read_mem", display = "Read Memory")
|
||||
public long read_mem(
|
||||
@Param(
|
||||
schema = "VirtualMachine",
|
||||
|
@ -1503,7 +1503,7 @@ public class JdiMethods implements RmiMethods {
|
|||
return range.getLength();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke method (no args)")
|
||||
public void execute_on_instance(
|
||||
@Param(
|
||||
schema = "ObjectReference",
|
||||
|
@ -1531,7 +1531,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke static method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke static method (no args)")
|
||||
public void execute_on_class(
|
||||
@Param(
|
||||
schema = "ReferenceType",
|
||||
|
@ -1565,7 +1565,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke method (no args)")
|
||||
public void execute_method(
|
||||
@Param(
|
||||
schema = "Method",
|
||||
|
@ -1596,7 +1596,7 @@ public class JdiMethods implements RmiMethods {
|
|||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke static method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke static method (no args)")
|
||||
public void execute_static_method(
|
||||
@Param(
|
||||
schema = "Method",
|
||||
|
|
|
@ -26,7 +26,7 @@ public class RmiMethodRegistry {
|
|||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface TraceMethod {
|
||||
public static @interface TraceRmiMethod {
|
||||
String action() default "";
|
||||
|
||||
String display() default "";
|
||||
|
|
|
@ -18,7 +18,7 @@ package ghidra.app.plugin.core.debug.client.tracermi;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.schema.*;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ import ghidra.trace.model.breakpoint.*;
|
|||
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.stack.*;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.*;
|
||||
import ghidra.trace.model.target.iface.*;
|
||||
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
|
||||
|
@ -60,7 +61,8 @@ import ghidra.trace.model.target.path.PathFilter.Align;
|
|||
import ghidra.trace.model.target.schema.*;
|
||||
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.thread.*;
|
||||
import ghidra.trace.model.thread.TraceProcess;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule.ScheduleForm;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -186,12 +188,12 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
protected ScheduleForm getSupportedTimeFormByAttribute(TraceObject obj, long snap) {
|
||||
TraceObject eventScope = obj.findSuitableInterface(TraceObjectEventScope.class);
|
||||
TraceObject eventScope = obj.findSuitableInterface(TraceEventScope.class);
|
||||
if (eventScope == null) {
|
||||
return null;
|
||||
}
|
||||
TraceObjectValue timeSupportStr =
|
||||
eventScope.getAttribute(snap, TraceObjectEventScope.KEY_TIME_SUPPORT);
|
||||
eventScope.getAttribute(snap, TraceEventScope.KEY_TIME_SUPPORT);
|
||||
if (timeSupportStr == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -213,11 +215,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
|
||||
@Override
|
||||
public TraceExecutionState getThreadExecutionState(TraceThread thread) {
|
||||
if (!(thread instanceof TraceObjectThread tot)) {
|
||||
Msg.error(this, "Non-object thread with Trace RMI!");
|
||||
return TraceExecutionState.ALIVE;
|
||||
}
|
||||
return tot.getObject().getExecutionState(getSnap());
|
||||
return thread.getObject().getExecutionState(getSnap());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -226,7 +224,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
return object.queryCanonicalAncestorsInterface(TraceObjectThread.class)
|
||||
return object.queryCanonicalAncestorsInterface(TraceThread.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
@ -237,7 +235,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
return object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class)
|
||||
return object.queryCanonicalAncestorsInterface(TraceStackFrame.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
@ -303,7 +301,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
return null;
|
||||
}
|
||||
TraceObjectValue attrEnabled =
|
||||
object.getAttribute(getSnap(), TraceObjectTogglable.KEY_ENABLED);
|
||||
object.getAttribute(getSnap(), TraceTogglable.KEY_ENABLED);
|
||||
boolean enabled = attrEnabled != null && attrEnabled.getValue() instanceof Boolean b && b;
|
||||
return !enabled;
|
||||
}
|
||||
|
@ -549,7 +547,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
return schema
|
||||
.getInterfaces()
|
||||
.contains(TraceObjectFocusScope.class) &&
|
||||
.contains(TraceFocusScope.class) &&
|
||||
!connection.getMethods().getByAction(ActionName.ACTIVATE).isEmpty();
|
||||
}
|
||||
|
||||
|
@ -557,7 +555,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
public KeyPath getFocus() {
|
||||
TraceObjectValue focusVal = trace.getObjectManager()
|
||||
.getRootObject()
|
||||
.getAttribute(getSnap(), TraceObjectFocusScope.KEY_FOCUS);
|
||||
.getAttribute(getSnap(), TraceFocusScope.KEY_FOCUS);
|
||||
if (focusVal == null || !focusVal.isObject()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -740,7 +738,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
|
||||
record ReadMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final ReadMemMatcher HAS_PROC_RANGE = new ReadMemMatcher(2, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("range", AddressRange.class)));
|
||||
static final ReadMemMatcher HAS_RANGE = new ReadMemMatcher(1, List.of(
|
||||
new TypeParamSpec("range", AddressRange.class)));
|
||||
|
@ -749,7 +747,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
|
||||
record WriteMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final WriteMemMatcher HAS_PROC_START_DATA = new WriteMemMatcher(2, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("start", Address.class),
|
||||
new TypeParamSpec("data", byte[].class)));
|
||||
static final WriteMemMatcher HAS_START_DATA = new WriteMemMatcher(1, List.of(
|
||||
|
@ -760,43 +758,43 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
|
||||
record ReadRegsMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final ReadRegsMatcher HAS_CONTAINER = new ReadRegsMatcher(3, List.of(
|
||||
new TypeParamSpec("container", TraceObjectRegisterContainer.class)));
|
||||
new TypeParamSpec("container", TraceRegisterContainer.class)));
|
||||
static final ReadRegsMatcher HAS_REGISTER = new ReadRegsMatcher(1, List.of(
|
||||
new TypeParamSpec("register", TraceObjectRegister.class)));
|
||||
new TypeParamSpec("register", TraceRegister.class)));
|
||||
static final List<ReadRegsMatcher> ALL = matchers(HAS_CONTAINER, HAS_REGISTER);
|
||||
}
|
||||
|
||||
record WriteRegMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final WriteRegMatcher HAS_FRAME_NAME_VALUE = new WriteRegMatcher(3, List.of(
|
||||
new TypeParamSpec("frame", TraceObjectStackFrame.class),
|
||||
new TypeParamSpec("frame", TraceStackFrame.class),
|
||||
new TypeParamSpec("name", String.class),
|
||||
new TypeParamSpec("value", byte[].class)));
|
||||
static final WriteRegMatcher HAS_THREAD_NAME_VALUE = new WriteRegMatcher(2, List.of(
|
||||
new TypeParamSpec("thread", TraceObjectThread.class),
|
||||
new TypeParamSpec("thread", TraceThread.class),
|
||||
new TypeParamSpec("name", String.class),
|
||||
new TypeParamSpec("value", byte[].class)));
|
||||
static final WriteRegMatcher HAS_REG_VALUE = new WriteRegMatcher(1, List.of(
|
||||
new TypeParamSpec("register", TraceObjectRegister.class),
|
||||
new TypeParamSpec("register", TraceRegister.class),
|
||||
new TypeParamSpec("value", byte[].class)));
|
||||
static final List<WriteRegMatcher> ALL = matchers(HAS_FRAME_NAME_VALUE, HAS_REG_VALUE);
|
||||
}
|
||||
|
||||
record BreakExecMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final BreakExecMatcher HAS_PROC_ADDR_COND_CMDS = new BreakExecMatcher(8, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("address", Address.class),
|
||||
new NameParamSpec("condition", String.class),
|
||||
new NameParamSpec("commands", String.class)));
|
||||
static final BreakExecMatcher HAS_PROC_ADDR_COND = new BreakExecMatcher(7, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("address", Address.class),
|
||||
new NameParamSpec("condition", String.class)));
|
||||
static final BreakExecMatcher HAS_PROC_ADDR_CMDS = new BreakExecMatcher(6, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("address", Address.class),
|
||||
new NameParamSpec("commands", String.class)));
|
||||
static final BreakExecMatcher HAS_PROC_ADDR = new BreakExecMatcher(5, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("address", Address.class)));
|
||||
static final BreakExecMatcher HAS_ADDR_COND_CMDS = new BreakExecMatcher(4, List.of(
|
||||
new TypeParamSpec("address", Address.class),
|
||||
|
@ -818,20 +816,20 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
// TODO: Probably need a better way to deal with optional requirements
|
||||
record BreakAccMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final BreakAccMatcher HAS_PROC_RNG_COND_CMDS = new BreakAccMatcher(8, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("range", AddressRange.class),
|
||||
new NameParamSpec("condition", String.class),
|
||||
new NameParamSpec("commands", String.class)));
|
||||
static final BreakAccMatcher HAS_PROC_RNG_COND = new BreakAccMatcher(7, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("range", AddressRange.class),
|
||||
new NameParamSpec("condition", String.class)));
|
||||
static final BreakAccMatcher HAS_PROC_RNG_CMDS = new BreakAccMatcher(6, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("range", AddressRange.class),
|
||||
new NameParamSpec("commands", String.class)));
|
||||
static final BreakAccMatcher HAS_PROC_RNG = new BreakAccMatcher(5, List.of(
|
||||
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||
new TypeParamSpec("process", TraceProcess.class),
|
||||
new TypeParamSpec("range", AddressRange.class)));
|
||||
static final BreakAccMatcher HAS_RNG_COND_CMDS = new BreakAccMatcher(4, List.of(
|
||||
new TypeParamSpec("range", AddressRange.class),
|
||||
|
@ -852,19 +850,19 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
|
||||
record DelBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final DelBreakMatcher HAS_LOC = new DelBreakMatcher(2, List.of(
|
||||
new TypeParamSpec("location", TraceObjectBreakpointLocation.class)));
|
||||
new TypeParamSpec("location", TraceBreakpointLocation.class)));
|
||||
static final DelBreakMatcher HAS_SPEC = new DelBreakMatcher(1, List.of(
|
||||
new TypeParamSpec("specification", TraceObjectBreakpointSpec.class)));
|
||||
new TypeParamSpec("specification", TraceBreakpointSpec.class)));
|
||||
static final List<DelBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
|
||||
static final List<DelBreakMatcher> SPEC = matchers(HAS_SPEC);
|
||||
}
|
||||
|
||||
record ToggleBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final ToggleBreakMatcher HAS_LOC = new ToggleBreakMatcher(2, List.of(
|
||||
new TypeParamSpec("location", TraceObjectBreakpointLocation.class),
|
||||
new TypeParamSpec("location", TraceBreakpointLocation.class),
|
||||
new TypeParamSpec("enabled", Boolean.class)));
|
||||
static final ToggleBreakMatcher HAS_SPEC = new ToggleBreakMatcher(1, List.of(
|
||||
new TypeParamSpec("specification", TraceObjectBreakpointSpec.class),
|
||||
new TypeParamSpec("specification", TraceBreakpointSpec.class),
|
||||
new TypeParamSpec("enabled", Boolean.class)));
|
||||
static final List<ToggleBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
|
||||
static final List<ToggleBreakMatcher> SPEC = matchers(HAS_SPEC);
|
||||
|
@ -1079,8 +1077,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
protected TraceObject getProcessForSpace(AddressSpace space) {
|
||||
List<TraceObjectProcess> processes = trace.getObjectManager()
|
||||
.queryAllInterface(Lifespan.at(getSnap()), TraceObjectProcess.class)
|
||||
List<TraceProcess> processes = trace.getObjectManager()
|
||||
.queryAllInterface(Lifespan.at(getSnap()), TraceProcess.class)
|
||||
.toList();
|
||||
if (processes.size() == 1) {
|
||||
return processes.get(0).getObject();
|
||||
|
@ -1089,11 +1087,10 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
return null;
|
||||
}
|
||||
for (TraceMemoryRegion region : trace.getMemoryManager()
|
||||
.getRegionsIntersecting(
|
||||
Lifespan.at(getSnap()),
|
||||
.getRegionsIntersecting(Lifespan.at(getSnap()),
|
||||
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) {
|
||||
TraceObject obj = ((TraceObjectMemoryRegion) region).getObject();
|
||||
return obj.findCanonicalAncestorsInterface(TraceObjectProcess.class)
|
||||
TraceObject obj = region.getObject();
|
||||
return obj.findCanonicalAncestorsInterface(TraceProcess.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
@ -1207,11 +1204,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
if (readRegs == null) {
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
if (!(thread instanceof TraceObjectThread tot)) {
|
||||
Msg.error(this, "Non-object trace with TraceRmi!");
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
TraceObject container = tot.getObject().findRegisterContainer(frame);
|
||||
TraceObject container = thread.getObject().findRegisterContainer(frame);
|
||||
if (container == null) {
|
||||
Msg.error(this,
|
||||
"Cannot find register container for thread,frame: " + thread + "," + frame);
|
||||
|
@ -1229,8 +1222,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
keys.add("[" + lower + "]");
|
||||
}
|
||||
Set<TraceObject> regs = container
|
||||
.findSuccessorsInterface(Lifespan.at(getSnap()), TraceObjectRegister.class,
|
||||
true)
|
||||
.findSuccessorsInterface(Lifespan.at(getSnap()), TraceRegister.class, true)
|
||||
.filter(p -> keys.contains(p.getLastEntry().getEntryKey().toLowerCase()))
|
||||
.map(r -> r.getDestination(null))
|
||||
.collect(Collectors.toSet());
|
||||
|
@ -1303,14 +1295,13 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
return findRegister(container, filter, parent);
|
||||
}
|
||||
|
||||
protected FoundRegister findRegister(TraceObjectThread thread, int frame,
|
||||
Register register) {
|
||||
protected FoundRegister findRegister(TraceThread thread, int frame, Register register) {
|
||||
TraceObject container = thread.getObject().findRegisterContainer(frame);
|
||||
if (container == null) {
|
||||
Msg.error(this, "No register container for thread=" + thread + ",frame=" + frame);
|
||||
return null;
|
||||
}
|
||||
PathFilter filter = container.getSchema().searchFor(TraceObjectRegister.class, true);
|
||||
PathFilter filter = container.getSchema().searchFor(TraceRegister.class, true);
|
||||
return findRegister(container, filter, register);
|
||||
}
|
||||
|
||||
|
@ -1337,11 +1328,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
if (writeReg == null) {
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
if (!(thread instanceof TraceObjectThread tot)) {
|
||||
Msg.error(this, "Non-object trace with TraceRmi!");
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
FoundRegister found = findRegister(tot, frameLevel, value.getRegister());
|
||||
FoundRegister found = findRegister(thread, frameLevel, value.getRegister());
|
||||
if (found == null) {
|
||||
Msg.warn(this, "Could not find register " + value.getRegister() + " in object model.");
|
||||
}
|
||||
|
@ -1352,7 +1339,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
RemoteParameter paramThread = writeReg.params.get("thread");
|
||||
if (paramThread != null) {
|
||||
return writeReg.method.invokeAsync(Map.ofEntries(
|
||||
Map.entry(paramThread.name(), tot.getObject()),
|
||||
Map.entry(paramThread.name(), thread.getObject()),
|
||||
Map.entry(writeReg.params.get("name").name(), found.name()),
|
||||
Map.entry(writeReg.params.get("value").name(), getBytes(value))))
|
||||
.toCompletableFuture()
|
||||
|
@ -1363,12 +1350,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
if (paramFrame != null) {
|
||||
TraceStack stack = trace.getStackManager().getLatestStack(thread, getSnap());
|
||||
TraceStackFrame frame = stack.getFrame(getSnap(), frameLevel, false);
|
||||
if (!(frame instanceof TraceObjectStackFrame tof)) {
|
||||
Msg.error(this, "Non-object trace with TraceRmi!");
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
return writeReg.method.invokeAsync(Map.ofEntries(
|
||||
Map.entry(paramFrame.name(), tof.getObject()),
|
||||
Map.entry(paramFrame.name(), frame.getObject()),
|
||||
Map.entry(writeReg.params.get("name").name(), found.name()),
|
||||
Map.entry(writeReg.params.get("value").name(), getBytes(value))))
|
||||
.toCompletableFuture()
|
||||
|
@ -1398,11 +1381,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
if (register == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(thread instanceof TraceObjectThread tot)) {
|
||||
return false;
|
||||
}
|
||||
// May be primitive or object
|
||||
FoundRegister found = findRegister(tot, frame, register);
|
||||
FoundRegister found = findRegister(thread, frame, register);
|
||||
if (found == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1596,7 +1576,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakpointValid(TraceBreakpoint breakpoint) {
|
||||
public boolean isBreakpointValid(TraceBreakpointLocation breakpoint) {
|
||||
long snap = getSnap();
|
||||
if (breakpoint.getName(snap).endsWith("emu-" + breakpoint.getMinAddress(snap))) {
|
||||
return false;
|
||||
|
@ -1607,7 +1587,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected CompletableFuture<Void> deleteBreakpointSpecAsync(TraceObjectBreakpointSpec spec) {
|
||||
protected CompletableFuture<Void> deleteBreakpointSpecAsync(TraceBreakpointSpec spec) {
|
||||
KeyPath path = spec.getObject().getCanonicalPath();
|
||||
MatchedMethod delBreak =
|
||||
matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.SPEC);
|
||||
|
@ -1621,7 +1601,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
// TODO: Would this make sense for any debugger? To delete individual locations?
|
||||
protected CompletableFuture<Void> deleteBreakpointLocAsync(TraceObjectBreakpointLocation loc) {
|
||||
protected CompletableFuture<Void> deleteBreakpointLocAsync(TraceBreakpointLocation loc) {
|
||||
KeyPath path = loc.getObject().getCanonicalPath();
|
||||
MatchedMethod delBreak =
|
||||
matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.ALL);
|
||||
|
@ -1639,18 +1619,18 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpoint breakpoint) {
|
||||
if (breakpoint instanceof TraceObjectBreakpointLocation loc) {
|
||||
public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint) {
|
||||
if (breakpoint instanceof TraceBreakpointLocation loc) {
|
||||
return deleteBreakpointLocAsync(loc);
|
||||
}
|
||||
if (breakpoint instanceof TraceObjectBreakpointSpec spec) {
|
||||
if (breakpoint instanceof TraceBreakpointSpec spec) {
|
||||
return deleteBreakpointSpecAsync(spec);
|
||||
}
|
||||
Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint);
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
|
||||
protected CompletableFuture<Void> toggleBreakpointSpecAsync(TraceObjectBreakpointSpec spec,
|
||||
protected CompletableFuture<Void> toggleBreakpointSpecAsync(TraceBreakpointSpec spec,
|
||||
boolean enabled) {
|
||||
KeyPath path = spec.getObject().getCanonicalPath();
|
||||
MatchedMethod toggleBreak =
|
||||
|
@ -1667,7 +1647,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
.thenApply(__ -> null);
|
||||
}
|
||||
|
||||
protected CompletableFuture<Void> toggleBreakpointLocAsync(TraceObjectBreakpointLocation loc,
|
||||
protected CompletableFuture<Void> toggleBreakpointLocAsync(TraceBreakpointLocation loc,
|
||||
boolean enabled) {
|
||||
KeyPath path = loc.getObject().getCanonicalPath();
|
||||
MatchedMethod toggleBreak =
|
||||
|
@ -1690,12 +1670,12 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpoint breakpoint,
|
||||
public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint,
|
||||
boolean enabled) {
|
||||
if (breakpoint instanceof TraceObjectBreakpointLocation loc) {
|
||||
if (breakpoint instanceof TraceBreakpointLocation loc) {
|
||||
return toggleBreakpointLocAsync(loc, enabled);
|
||||
}
|
||||
if (breakpoint instanceof TraceObjectBreakpointSpec spec) {
|
||||
if (breakpoint instanceof TraceBreakpointSpec spec) {
|
||||
return toggleBreakpointSpecAsync(spec, enabled);
|
||||
}
|
||||
Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint);
|
||||
|
|
|
@ -37,8 +37,8 @@ import ghidra.debug.api.target.ActionName;
|
|||
import ghidra.debug.api.tracermi.RemoteMethod;
|
||||
import ghidra.debug.api.tracermi.RemoteParameter;
|
||||
import ghidra.framework.options.PropertyBoolean;
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.Param;
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.Param;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.schema.*;
|
||||
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
|
|
|
@ -343,16 +343,16 @@ public class PopulateDemoTrace extends GhidraScript {
|
|||
*/
|
||||
mainLabel = trace.getSymbolManager()
|
||||
.labels()
|
||||
.create(snap, null, addr(0x00400000), "main", global, SourceType.USER_DEFINED);
|
||||
.create(snap, addr(0x00400000), "main", global, SourceType.USER_DEFINED);
|
||||
cloneLabel = trace.getSymbolManager()
|
||||
.labels()
|
||||
.create(snap, null, addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
|
||||
.create(snap, addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
|
||||
childLabel = trace.getSymbolManager()
|
||||
.labels()
|
||||
.create(snap, null, addr(0x00400034), "child", global, SourceType.USER_DEFINED);
|
||||
.create(snap, addr(0x00400034), "child", global, SourceType.USER_DEFINED);
|
||||
exitLabel = trace.getSymbolManager()
|
||||
.labels()
|
||||
.create(snap, null, addr(0x00400061), "exit", global, SourceType.USER_DEFINED);
|
||||
.create(snap, addr(0x00400061), "exit", global, SourceType.USER_DEFINED);
|
||||
|
||||
/**
|
||||
* Note the use of getProgramView as a means of using components intended for Program
|
||||
|
|
|
@ -29,8 +29,8 @@ import ghidra.debug.api.modules.ModuleMapProposal;
|
|||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.modules.TraceObjectModule;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.util.TraceEvent;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
|
@ -76,8 +76,8 @@ public class ByModuleAutoMapSpec implements AutoMapSpec {
|
|||
|
||||
@Override
|
||||
public boolean objectHasType(TraceObjectValue value) {
|
||||
return value.getParent().queryInterface(TraceObjectModule.class) != null ||
|
||||
value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null;
|
||||
return value.getParent().queryInterface(TraceModule.class) != null ||
|
||||
value.getParent().queryInterface(TraceMemoryRegion.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,7 +29,7 @@ import ghidra.debug.api.modules.RegionMapProposal;
|
|||
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.util.TraceEvent;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
|
@ -61,7 +61,7 @@ public class ByRegionAutoMapSpec implements AutoMapSpec {
|
|||
|
||||
@Override
|
||||
public boolean objectHasType(TraceObjectValue value) {
|
||||
return value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null;
|
||||
return value.getParent().queryInterface(TraceMemoryRegion.class) != null;
|
||||
}
|
||||
|
||||
static String getInfoForRegions(Trace trace, long snap) {
|
||||
|
|
|
@ -28,8 +28,8 @@ import ghidra.debug.api.modules.MapProposal;
|
|||
import ghidra.debug.api.modules.SectionMapProposal;
|
||||
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.database.module.TraceObjectSection;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.modules.TraceSection;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.util.TraceEvent;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
|
@ -61,7 +61,7 @@ public class BySectionAutoMapSpec implements AutoMapSpec {
|
|||
|
||||
@Override
|
||||
public boolean objectHasType(TraceObjectValue value) {
|
||||
return value.getParent().queryInterface(TraceObjectSection.class) != null;
|
||||
return value.getParent().queryInterface(TraceSection.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,11 +40,13 @@ import ghidra.framework.options.SaveState;
|
|||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.annotation.AutoConfigStateField;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
|
@ -60,10 +62,12 @@ public class DebuggerTrackLocationTrait {
|
|||
|
||||
public ForTrackingListener() {
|
||||
listenFor(TraceEvents.BYTES_CHANGED, this::registersChanged);
|
||||
listenFor(TraceEvents.STACK_CHANGED, this::stackChanged);
|
||||
//listenFor(TraceEvents.STACK_CHANGED, this::stackChanged);
|
||||
listenFor(TraceEvents.VALUE_CREATED, this::valueCreated);
|
||||
listenFor(TraceEvents.VALUE_LIFESPAN_CHANGED, this::valueLifespanChanged);
|
||||
}
|
||||
|
||||
private void registersChanged(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
private void registersChanged(AddressSpace space, TraceAddressSnapRange range,
|
||||
byte[] oldValue, byte[] newValue) {
|
||||
if (current.getView() == null || spec == null) {
|
||||
// Should only happen during transitional times, if at all.
|
||||
|
@ -85,6 +89,42 @@ public class DebuggerTrackLocationTrait {
|
|||
}
|
||||
doTrack(TrackCause.DB_CHANGE);
|
||||
}
|
||||
|
||||
private void valueCreated(TraceObjectValue value) {
|
||||
if (!value.getLifespan().contains(current.getSnap())) {
|
||||
return;
|
||||
}
|
||||
if (!value.getEntryKey().equals(TraceStackFrame.KEY_PC)) {
|
||||
return;
|
||||
}
|
||||
TraceStackFrame frame = value.getParent().queryInterface(TraceStackFrame.class);
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
if (!tracker.affectedByStackChange(frame.getStack(), current)) {
|
||||
return;
|
||||
}
|
||||
doTrack(TrackCause.DB_CHANGE);
|
||||
}
|
||||
|
||||
private void valueLifespanChanged(TraceObjectValue value, Lifespan oldLife,
|
||||
Lifespan newLife) {
|
||||
long snap = current.getSnap();
|
||||
if (oldLife.contains(snap) == newLife.contains(snap)) {
|
||||
return;
|
||||
}
|
||||
if (!value.getEntryKey().equals(TraceStackFrame.KEY_PC)) {
|
||||
return;
|
||||
}
|
||||
TraceStackFrame frame = value.getParent().queryInterface(TraceStackFrame.class);
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
if (!tracker.affectedByStackChange(frame.getStack(), current)) {
|
||||
return;
|
||||
}
|
||||
doTrack(TrackCause.DB_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This may already be deprecated....
|
||||
|
@ -297,6 +337,9 @@ public class DebuggerTrackLocationTrait {
|
|||
trackedLocation = newLocation;
|
||||
locationTracked();
|
||||
}
|
||||
catch (TraceClosedException ex) {
|
||||
// Silently continue
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
Msg.error(this, "Error while computing location: " + ex);
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@ import ghidra.debug.api.action.*;
|
|||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTracker {
|
||||
INSTANCE;
|
||||
|
@ -77,8 +77,8 @@ public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTr
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean affectedByBytesChange(TraceAddressSpace space,
|
||||
TraceAddressSnapRange range, DebuggerCoordinates coordinates) {
|
||||
public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ import ghidra.debug.api.action.*;
|
|||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, LocationTracker {
|
||||
INSTANCE;
|
||||
|
@ -124,7 +124,7 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@ import ghidra.debug.api.action.*;
|
|||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTracker {
|
||||
INSTANCE;
|
||||
|
@ -91,7 +91,7 @@ public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTrac
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates) {
|
||||
return BY_REG.affectedByBytesChange(space, range, coordinates);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import ghidra.trace.model.memory.TraceMemorySpace;
|
|||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, LocationTracker {
|
||||
Register computeRegister(DebuggerCoordinates coordinates);
|
||||
|
@ -102,18 +101,17 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, Loca
|
|||
}
|
||||
|
||||
@Override
|
||||
default boolean affectedByBytesChange(TraceAddressSpace space,
|
||||
TraceAddressSnapRange range, DebuggerCoordinates coordinates) {
|
||||
default boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates) {
|
||||
if (!LocationTrackingSpec.changeIsCurrent(space, range, coordinates)) {
|
||||
return false;
|
||||
}
|
||||
Register register = computeRegister(coordinates);
|
||||
AddressSpace as = space.getAddressSpace();
|
||||
if (register == null || register.getAddressSpace() != as) {
|
||||
if (register == null) {
|
||||
return false;
|
||||
}
|
||||
AddressRange regRng = coordinates.getPlatform()
|
||||
.getConventionalRegisterRange(as.isRegisterSpace() ? as : null, register);
|
||||
.getConventionalRegisterRange(space.isRegisterSpace() ? space : null, register);
|
||||
return range.getRange().intersects(regRng);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,13 +28,11 @@ import ghidra.framework.plugintool.ServiceProvider;
|
|||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
|
||||
import ghidra.pcode.exec.SleighUtils.AddressOf;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* A tracking specification for the address of a given Sleigh expression
|
||||
|
@ -151,7 +149,7 @@ public class WatchLocationTrackingSpec implements LocationTrackingSpec {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates) {
|
||||
return LocationTrackingSpec.changeIsCurrent(space, range, coordinates) &&
|
||||
(reads == null || reads.intersects(range.getX1(), range.getX2()));
|
||||
|
|
|
@ -24,13 +24,14 @@ import ghidra.debug.api.breakpoint.LogicalBreakpoint.State;
|
|||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public class BreakpointLocationRow {
|
||||
private final DebuggerBreakpointsProvider provider;
|
||||
private final TraceBreakpoint loc;
|
||||
private final TraceBreakpointLocation loc;
|
||||
|
||||
public BreakpointLocationRow(DebuggerBreakpointsProvider provider, TraceBreakpoint loc) {
|
||||
public BreakpointLocationRow(DebuggerBreakpointsProvider provider,
|
||||
TraceBreakpointLocation loc) {
|
||||
this.provider = provider;
|
||||
this.loc = loc;
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ public class BreakpointLocationRow {
|
|||
return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh(getSnap()));
|
||||
}
|
||||
|
||||
public TraceBreakpoint getTraceBreakpoint() {
|
||||
public TraceBreakpointLocation getTraceBreakpoint() {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import java.util.Collection;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import docking.DefaultActionContext;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public class DebuggerBreakpointLocationsActionContext extends DefaultActionContext {
|
||||
private final Collection<BreakpointLocationRow> selection;
|
||||
|
@ -32,7 +32,7 @@ public class DebuggerBreakpointLocationsActionContext extends DefaultActionConte
|
|||
return selection;
|
||||
}
|
||||
|
||||
public Collection<TraceBreakpoint> getLocations() {
|
||||
public Collection<TraceBreakpointLocation> getLocations() {
|
||||
return selection.stream().map(row -> row.getTraceBreakpoint()).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ import ghidra.program.model.address.AddressRange;
|
|||
import ghidra.program.util.MarkerLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.database.ObjectKey;
|
||||
|
@ -230,11 +230,13 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
|
||||
protected static class BreakpointLocationTableModel
|
||||
extends RowWrappedEnumeratedColumnTableModel< //
|
||||
BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, TraceBreakpoint> {
|
||||
BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, //
|
||||
TraceBreakpointLocation> {
|
||||
|
||||
public BreakpointLocationTableModel(DebuggerBreakpointsProvider provider) {
|
||||
super(provider.getTool(), "Locations", BreakpointLocationTableColumns.class,
|
||||
TraceBreakpoint::getObjectKey, loc -> new BreakpointLocationRow(provider, loc),
|
||||
TraceBreakpointLocation::getObjectKey,
|
||||
loc -> new BreakpointLocationRow(provider, loc),
|
||||
BreakpointLocationRow::getTraceBreakpoint);
|
||||
}
|
||||
|
||||
|
@ -376,7 +378,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
if (context instanceof DebuggerBreakpointLocationsActionContext) {
|
||||
DebuggerBreakpointLocationsActionContext ctx =
|
||||
(DebuggerBreakpointLocationsActionContext) context;
|
||||
Collection<TraceBreakpoint> sel = ctx.getLocations();
|
||||
Collection<TraceBreakpointLocation> sel = ctx.getLocations();
|
||||
breakpointService.enableLocs(sel).exceptionally(ex -> {
|
||||
breakpointError("Enable Breakpoints", "Could not enable breakpoints", ex);
|
||||
return null;
|
||||
|
@ -455,7 +457,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
if (context instanceof DebuggerBreakpointLocationsActionContext) {
|
||||
DebuggerBreakpointLocationsActionContext ctx =
|
||||
(DebuggerBreakpointLocationsActionContext) context;
|
||||
Collection<TraceBreakpoint> sel = ctx.getLocations();
|
||||
Collection<TraceBreakpointLocation> sel = ctx.getLocations();
|
||||
breakpointService.disableLocs(sel).exceptionally(ex -> {
|
||||
breakpointError("Disable Breakpoints", "Could not disable breakpoints", ex);
|
||||
return null;
|
||||
|
@ -526,7 +528,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
if (context instanceof DebuggerBreakpointLocationsActionContext) {
|
||||
DebuggerBreakpointLocationsActionContext ctx =
|
||||
(DebuggerBreakpointLocationsActionContext) context;
|
||||
Collection<TraceBreakpoint> sel = ctx.getLocations();
|
||||
Collection<TraceBreakpointLocation> sel = ctx.getLocations();
|
||||
breakpointService.deleteLocs(sel).exceptionally(ex -> {
|
||||
breakpointError("Clear Breakpoints", "Could not clear breakpoints", ex);
|
||||
return null;
|
||||
|
@ -700,26 +702,26 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
reloadBreakpointLocations(trace);
|
||||
}
|
||||
|
||||
private boolean isVisible(TraceBreakpoint location) {
|
||||
private boolean isVisible(TraceBreakpointLocation location) {
|
||||
long snap = traceManager.getCurrentFor(trace).getSnap();
|
||||
return location.isValid(snap);
|
||||
}
|
||||
|
||||
private void locationAdded(TraceBreakpoint location) {
|
||||
private void locationAdded(TraceBreakpointLocation location) {
|
||||
if (!isVisible(location)) {
|
||||
return;
|
||||
}
|
||||
breakpointLocationAdded(location);
|
||||
}
|
||||
|
||||
private void locationChanged(TraceBreakpoint location) {
|
||||
private void locationChanged(TraceBreakpointLocation location) {
|
||||
if (!isVisible(location)) {
|
||||
return;
|
||||
}
|
||||
breakpointLocationUpdated(location);
|
||||
}
|
||||
|
||||
private void locationLifespanChanged(TraceBreakpoint location, Lifespan oldSpan,
|
||||
private void locationLifespanChanged(TraceBreakpointLocation location, Lifespan oldSpan,
|
||||
Lifespan newSpan) {
|
||||
long snap = traceManager.getCurrentFor(trace).getSnap();
|
||||
boolean isLiveOld = oldSpan.contains(snap);
|
||||
|
@ -735,7 +737,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
}
|
||||
}
|
||||
|
||||
private void locationDeleted(TraceBreakpoint location) {
|
||||
private void locationDeleted(TraceBreakpointLocation location) {
|
||||
if (!isVisible(location)) {
|
||||
return;
|
||||
}
|
||||
|
@ -955,15 +957,15 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
return;
|
||||
}
|
||||
Lifespan span = Lifespan.at(currentFor.getSnap());
|
||||
Collection<TraceBreakpoint> visible = new ArrayList<>();
|
||||
Collection<TraceBreakpointLocation> visible = new ArrayList<>();
|
||||
for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) {
|
||||
Collection<? extends TraceBreakpoint> breaks =
|
||||
Collection<? extends TraceBreakpointLocation> breaks =
|
||||
trace.getBreakpointManager().getBreakpointsIntersecting(span, range);
|
||||
if (mode.useEmulatedBreakpoints()) {
|
||||
visible.addAll(breaks);
|
||||
}
|
||||
else {
|
||||
for (TraceBreakpoint l : breaks) {
|
||||
for (TraceBreakpointLocation l : breaks) {
|
||||
if (target.isBreakpointValid(l)) {
|
||||
visible.add(l);
|
||||
}
|
||||
|
@ -982,19 +984,19 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
loadBreakpointLocations(trace);
|
||||
}
|
||||
|
||||
private void breakpointLocationAdded(TraceBreakpoint location) {
|
||||
private void breakpointLocationAdded(TraceBreakpointLocation location) {
|
||||
locationTableModel.addItem(location);
|
||||
}
|
||||
|
||||
private void breakpointLocationUpdated(TraceBreakpoint location) {
|
||||
private void breakpointLocationUpdated(TraceBreakpointLocation location) {
|
||||
locationTableModel.updateItem(location);
|
||||
}
|
||||
|
||||
private void breakpointLocationsUpdated(Collection<TraceBreakpoint> locations) {
|
||||
private void breakpointLocationsUpdated(Collection<TraceBreakpointLocation> locations) {
|
||||
locationTableModel.updateAllItems(locations);
|
||||
}
|
||||
|
||||
private void breakpointLocationRemoved(TraceBreakpoint location) {
|
||||
private void breakpointLocationRemoved(TraceBreakpointLocation location) {
|
||||
locationTableModel.deleteItem(location);
|
||||
}
|
||||
|
||||
|
@ -1304,12 +1306,12 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
}
|
||||
}
|
||||
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
|
||||
Collection<TraceBreakpoint> locations = locCtx.getLocations();
|
||||
Collection<TraceBreakpointLocation> locations = locCtx.getLocations();
|
||||
if (locations.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (TraceBreakpoint tb : locations) {
|
||||
traces.add(tb.getTrace());
|
||||
for (TraceBreakpointLocation loc : locations) {
|
||||
traces.add(loc.getTrace());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1338,9 +1340,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
return true;
|
||||
}
|
||||
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
|
||||
for (TraceBreakpoint tb : locCtx.getLocations()) {
|
||||
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap();
|
||||
if (!EXECUTE_KINDS.containsAll(tb.getKinds(snap))) {
|
||||
for (TraceBreakpointLocation loc : locCtx.getLocations()) {
|
||||
long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap();
|
||||
if (!EXECUTE_KINDS.containsAll(loc.getKinds(snap))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1371,9 +1373,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
return sleigh;
|
||||
}
|
||||
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
|
||||
for (TraceBreakpoint tb : locCtx.getLocations()) {
|
||||
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap();
|
||||
String s = tb.getEmuSleigh(snap);
|
||||
for (TraceBreakpointLocation loc : locCtx.getLocations()) {
|
||||
long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap();
|
||||
String s = loc.getEmuSleigh(snap);
|
||||
if (sleigh != null && !sleigh.equals(s)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1397,9 +1399,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
}
|
||||
}
|
||||
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
|
||||
for (TraceBreakpoint tb : locCtx.getLocations()) {
|
||||
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap();
|
||||
tb.setEmuSleigh(snap, sleigh);
|
||||
for (TraceBreakpointLocation loc : locCtx.getLocations()) {
|
||||
long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap();
|
||||
loc.setEmuSleigh(snap, sleigh);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1466,7 +1468,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
breakpointTableModel, breakpointFilterPanel);
|
||||
}
|
||||
|
||||
public void setSelectedLocations(Set<TraceBreakpoint> sel) {
|
||||
public void setSelectedLocations(Set<TraceBreakpointLocation> sel) {
|
||||
DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable,
|
||||
locationTableModel, locationFilterPanel);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import ghidra.program.model.data.*;
|
|||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
|
@ -220,7 +220,7 @@ public class DebuggerCopyPlan {
|
|||
public void copy(TraceProgramView from, AddressRange fromRange, Program into,
|
||||
Address intoAddress, TaskMonitor monitor) throws Exception {
|
||||
long snap = from.getSnap();
|
||||
for (TraceBreakpoint bpt : from.getTrace()
|
||||
for (TraceBreakpointLocation bpt : from.getTrace()
|
||||
.getBreakpointManager()
|
||||
.getBreakpointsIntersecting(Lifespan.at(from.getSnap()), fromRange)) {
|
||||
monitor.checkCancelled();
|
||||
|
|
|
@ -32,7 +32,7 @@ import ghidra.program.model.address.*;
|
|||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.util.layout.PairLayout;
|
||||
|
@ -161,8 +161,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
|||
if (rootSchema == null) {
|
||||
return "";
|
||||
}
|
||||
KeyPath suitable = rootSchema.searchForSuitableContainer(TraceObjectMemoryRegion.class,
|
||||
current.getPath());
|
||||
KeyPath suitable =
|
||||
rootSchema.searchForSuitableContainer(TraceMemoryRegion.class, current.getPath());
|
||||
if (suitable == null) {
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -55,8 +55,7 @@ import ghidra.framework.options.SaveState;
|
|||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.annotation.AutoConfigStateField;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
|
@ -65,7 +64,6 @@ import ghidra.program.util.ProgramSelection;
|
|||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceDomainObjectListener;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.Swing;
|
||||
|
||||
|
@ -99,8 +97,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged);
|
||||
}
|
||||
|
||||
private void bytesChanged(TraceAddressSpace space) {
|
||||
if (space.getAddressSpace().isMemorySpace()) {
|
||||
private void bytesChanged(AddressSpace space) {
|
||||
if (space.isMemorySpace()) {
|
||||
currCache.invalidate();
|
||||
prevCache.invalidate();
|
||||
}
|
||||
|
|
|
@ -29,13 +29,14 @@ import ghidra.framework.plugintool.ServiceProvider;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemory;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||
import ghidra.trace.model.thread.TraceProcess;
|
||||
|
||||
public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceObjectMemoryRegion> {
|
||||
public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceMemoryRegion> {
|
||||
|
||||
private static class RegionKeyColumn extends TraceValueKeyColumn {
|
||||
@Override
|
||||
|
@ -66,7 +67,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
private static class RegionStartColumn extends AbstractTraceValueObjectAddressColumn {
|
||||
public RegionStartColumn() {
|
||||
super(TraceObjectMemoryRegion.KEY_RANGE);
|
||||
super(TraceMemoryRegion.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,7 +83,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
private static class RegionEndColumn extends AbstractTraceValueObjectAddressColumn {
|
||||
public RegionEndColumn() {
|
||||
super(TraceObjectMemoryRegion.KEY_RANGE);
|
||||
super(TraceMemoryRegion.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +99,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
private static class RegionLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
||||
public RegionLengthColumn() {
|
||||
super(TraceObjectMemoryRegion.KEY_RANGE);
|
||||
super(TraceMemoryRegion.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,7 +121,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
public static class RegionReadColumn extends RegionFlagColumn {
|
||||
public RegionReadColumn() {
|
||||
super(TraceObjectMemoryRegion.KEY_READABLE);
|
||||
super(TraceMemoryRegion.KEY_READABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,7 +132,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
public static class RegionWriteColumn extends RegionFlagColumn {
|
||||
public RegionWriteColumn() {
|
||||
super(TraceObjectMemoryRegion.KEY_WRITABLE);
|
||||
super(TraceMemoryRegion.KEY_WRITABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -142,7 +143,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
public static class RegionExecuteColumn extends RegionFlagColumn {
|
||||
public RegionExecuteColumn() {
|
||||
super(TraceObjectMemoryRegion.KEY_EXECUTABLE);
|
||||
super(TraceMemoryRegion.KEY_EXECUTABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -174,7 +175,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
protected static ModelQuery successorRegions(TraceObjectSchema rootSchema, KeyPath path) {
|
||||
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||
return new ModelQuery(schema.searchFor(TraceObjectMemoryRegion.class, path, true));
|
||||
return new ModelQuery(schema.searchFor(TraceMemoryRegion.class, path, true));
|
||||
}
|
||||
|
||||
protected Set<TraceMemoryRegion> getSelectedRegions(DebuggerObjectActionContext ctx) {
|
||||
|
@ -182,7 +183,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
}
|
||||
|
||||
public DebuggerRegionsPanel(DebuggerRegionsProvider provider) {
|
||||
super(provider.plugin, provider, TraceObjectMemoryRegion.class);
|
||||
super(provider.plugin, provider, TraceMemoryRegion.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -194,14 +195,14 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
protected ModelQuery computeQuery(TraceObject object) {
|
||||
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||
KeyPath seedPath = object.getCanonicalPath();
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
|
||||
if (processPath != null) {
|
||||
ModelQuery result = successorRegions(rootSchema, processPath);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
KeyPath memoryPath = rootSchema.searchForSuitable(TraceObjectMemory.class, seedPath);
|
||||
KeyPath memoryPath = rootSchema.searchForSuitable(TraceMemory.class, seedPath);
|
||||
if (memoryPath != null) {
|
||||
ModelQuery result = successorRegions(rootSchema, memoryPath);
|
||||
if (!result.isEmpty()) {
|
||||
|
|
|
@ -23,15 +23,17 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
|||
import ghidra.framework.model.DomainObjectChangeRecord;
|
||||
import ghidra.framework.model.DomainObjectEvent;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.module.TraceObjectSection;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.modules.*;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.thread.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.thread.TraceThreadManager;
|
||||
import ghidra.trace.model.time.TraceTimeManager;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.Swing;
|
||||
|
@ -100,7 +102,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
}
|
||||
|
||||
private void threadChanged(TraceThread thread) {
|
||||
if (!trackThreads || !trackTrace || !(thread instanceof TraceObjectThread objThread)) {
|
||||
if (!trackThreads || !trackTrace) {
|
||||
return;
|
||||
}
|
||||
AddressFactory factory = thread.getTrace().getBaseAddressFactory();
|
||||
|
@ -108,7 +110,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
Long threadId = thread.getKey();
|
||||
|
||||
AddressRange rng = rng(defaultSpace, threadId, threadId);
|
||||
TraceObject obj = objThread.getObject();
|
||||
TraceObject obj = thread.getObject();
|
||||
obj.getCanonicalParents(Lifespan.ALL).forEach(p -> {
|
||||
MemoryBox box = new MemoryBox(currentTrace, "Thread " + thread.getName(p.getMinSnap()),
|
||||
MemviewBoxType.THREAD, rng, p.getLifespan());
|
||||
|
@ -118,13 +120,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
}
|
||||
|
||||
private void regionChanged(TraceMemoryRegion region) {
|
||||
if (!trackRegions || !trackTrace ||
|
||||
!(region instanceof TraceObjectMemoryRegion objRegion)) {
|
||||
if (!trackRegions || !trackTrace) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objRegion.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectMemoryRegion.KEY_RANGE, true).forEach(v -> {
|
||||
TraceObject obj = region.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceMemoryRegion.KEY_RANGE, true).forEach(v -> {
|
||||
if (region.getName(v.getMinSnap()).equals("full memory")) {
|
||||
return;
|
||||
}
|
||||
|
@ -136,12 +137,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
}
|
||||
|
||||
private void moduleChanged(TraceModule module) {
|
||||
if (!trackModules || !trackTrace || !(module instanceof TraceObjectModule objModule)) {
|
||||
if (!trackModules || !trackTrace) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objModule.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectModule.KEY_RANGE, true).forEach(v -> {
|
||||
TraceObject obj = module.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceModule.KEY_RANGE, true).forEach(v -> {
|
||||
MemoryBox box = new MemoryBox(currentTrace, "Module " + module.getName(v.getMinSnap()),
|
||||
MemviewBoxType.MODULE, v.castValue(), v.getLifespan());
|
||||
updateList.add(box);
|
||||
|
@ -150,12 +151,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
}
|
||||
|
||||
private void sectionChanged(TraceSection section) {
|
||||
if (!trackSections || !trackTrace || !(section instanceof TraceObjectSection objSection)) {
|
||||
if (!trackSections || !trackTrace) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objSection.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectSection.KEY_RANGE, true).forEach(v -> {
|
||||
TraceObject obj = section.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceSection.KEY_RANGE, true).forEach(v -> {
|
||||
MemoryBox box = new MemoryBox(currentTrace, "Module " + section.getName(v.getMinSnap()),
|
||||
MemviewBoxType.IMAGE, v.castValue(), v.getLifespan());
|
||||
updateList.add(box);
|
||||
|
@ -163,14 +164,13 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
updateLabelDebouncer.contact(null);
|
||||
}
|
||||
|
||||
private void breakpointChanged(TraceBreakpoint bpt) {
|
||||
if (!trackBreakpoints || !trackTrace ||
|
||||
!(bpt instanceof TraceObjectBreakpointLocation objBpt)) {
|
||||
private void breakpointChanged(TraceBreakpointLocation bpt) {
|
||||
if (!trackBreakpoints || !trackTrace) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objBpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
TraceObject obj = bpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
MemoryBox box =
|
||||
new MemoryBox(currentTrace, "Module " + bpt.getName(v.getMinSnap()),
|
||||
|
@ -301,7 +301,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
|
|||
regionChanged(region);
|
||||
}
|
||||
TraceBreakpointManager breakpointManager = trace.getBreakpointManager();
|
||||
for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) {
|
||||
for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) {
|
||||
breakpointChanged(bpt);
|
||||
}
|
||||
updateLabelDebouncer.contact(null);
|
||||
|
|
|
@ -130,7 +130,7 @@ public interface ObjectDefaultActionsMixin {
|
|||
default boolean performDefaultAction(TraceObject object) {
|
||||
Set<Class<? extends TraceObjectInterface>> interfaces =
|
||||
object.getSchema().getInterfaces();
|
||||
if (interfaces.contains(TraceObjectActivatable.class)) {
|
||||
if (interfaces.contains(TraceActivatable.class)) {
|
||||
activatePath(object.getCanonicalPath());
|
||||
return true;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public interface ObjectDefaultActionsMixin {
|
|||
* Should I check aliveAndPresent() here? If I do, behavior changes when target is dead,
|
||||
* which might be unexpected.
|
||||
*/
|
||||
if (interfaces.contains(TraceObjectTogglable.class)) {
|
||||
if (interfaces.contains(TraceTogglable.class)) {
|
||||
toggleObject(object);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ import generic.theme.GIcon;
|
|||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceObjectBreakpointSpec;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointSpec;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.iface.*;
|
||||
|
@ -65,10 +65,10 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||
if (!value.getParent()
|
||||
.getSchema()
|
||||
.getInterfaces()
|
||||
.contains(TraceObjectEventScope.class)) {
|
||||
.contains(TraceEventScope.class)) {
|
||||
return false;
|
||||
}
|
||||
if (!TraceObjectEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) {
|
||||
if (!TraceEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -77,12 +77,12 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||
protected boolean isEnabledValue(TraceObjectValue value) {
|
||||
Set<Class<? extends TraceObjectInterface>> interfaces =
|
||||
value.getParent().getSchema().getInterfaces();
|
||||
if (!interfaces.contains(TraceObjectBreakpointSpec.class) &&
|
||||
!interfaces.contains(TraceObjectBreakpointLocation.class) &&
|
||||
!interfaces.contains(TraceObjectTogglable.class)) {
|
||||
if (!interfaces.contains(TraceBreakpointSpec.class) &&
|
||||
!interfaces.contains(TraceBreakpointLocation.class) &&
|
||||
!interfaces.contains(TraceTogglable.class)) {
|
||||
return false;
|
||||
}
|
||||
if (!TraceObjectTogglable.KEY_ENABLED.equals(value.getEntryKey())) {
|
||||
if (!TraceTogglable.KEY_ENABLED.equals(value.getEntryKey())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -675,7 +675,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||
|
||||
protected TraceObject getEventObject(TraceObject object) {
|
||||
TraceObject scope = object
|
||||
.findCanonicalAncestorsInterface(TraceObjectEventScope.class)
|
||||
.findCanonicalAncestorsInterface(TraceEventScope.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (scope == null) {
|
||||
|
@ -685,7 +685,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||
return null;
|
||||
}
|
||||
TraceObjectValue eventValue =
|
||||
scope.getAttribute(snap, TraceObjectEventScope.KEY_EVENT_THREAD);
|
||||
scope.getAttribute(snap, TraceEventScope.KEY_EVENT_THREAD);
|
||||
if (eventValue == null || !eventValue.isObject()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -712,7 +712,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||
if (type.contains("Breakpoint") || type.contains("Watchpoint")) {
|
||||
TraceObject object = edge.getChild();
|
||||
TraceObjectValue en =
|
||||
object.getAttribute(snap, TraceObjectTogglable.KEY_ENABLED);
|
||||
object.getAttribute(snap, TraceTogglable.KEY_ENABLED);
|
||||
// includes true or non-boolean values
|
||||
if (en == null || !Objects.equals(false, en.getValue())) {
|
||||
return DebuggerResources.ICON_SET_BREAKPOINT;
|
||||
|
|
|
@ -31,20 +31,20 @@ import ghidra.docking.settings.Settings;
|
|||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.module.TraceObjectSection;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.modules.*;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.modules.TraceSection;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||
import ghidra.trace.model.thread.TraceProcess;
|
||||
|
||||
public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceObjectModule> {
|
||||
public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceModule> {
|
||||
|
||||
private static class ModuleBaseColumn extends AbstractTraceValueObjectAddressColumn {
|
||||
public ModuleBaseColumn() {
|
||||
super(TraceObjectModule.KEY_RANGE);
|
||||
super(TraceModule.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +60,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
private static class ModuleMaxColumn extends AbstractTraceValueObjectAddressColumn {
|
||||
public ModuleMaxColumn() {
|
||||
super(TraceObjectModule.KEY_RANGE);
|
||||
super(TraceModule.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,7 +76,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
private static class ModuleNameColumn extends TraceValueObjectAttributeColumn<String> {
|
||||
public ModuleNameColumn() {
|
||||
super(TraceObjectModule.KEY_MODULE_NAME, String.class);
|
||||
super(TraceModule.KEY_MODULE_NAME, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +98,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
return "";
|
||||
}
|
||||
ValueAttribute<AddressRange> attr =
|
||||
rowObject.getAttribute(TraceObjectModule.KEY_RANGE, AddressRange.class);
|
||||
rowObject.getAttribute(TraceModule.KEY_RANGE, AddressRange.class);
|
||||
if (attr == null) {
|
||||
return "";
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
private static class ModuleLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
||||
public ModuleLengthColumn() {
|
||||
super(TraceObjectModule.KEY_RANGE);
|
||||
super(TraceModule.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -166,12 +166,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
continue;
|
||||
}
|
||||
TraceObject child = value.getChild();
|
||||
TraceObjectModule module = child.queryInterface(TraceObjectModule.class);
|
||||
TraceModule module = child.queryInterface(TraceModule.class);
|
||||
if (module != null) {
|
||||
result.add(module);
|
||||
continue;
|
||||
}
|
||||
TraceObjectSection section = child.queryInterface(TraceObjectSection.class);
|
||||
TraceSection section = child.queryInterface(TraceSection.class);
|
||||
if (section != null) {
|
||||
result.add(section.getModule());
|
||||
continue;
|
||||
|
@ -188,12 +188,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
continue;
|
||||
}
|
||||
TraceObject child = value.getChild();
|
||||
TraceObjectModule module = child.queryInterface(TraceObjectModule.class);
|
||||
TraceModule module = child.queryInterface(TraceModule.class);
|
||||
if (module != null) {
|
||||
result.addAll(module.getSections(ctx.getSnap()));
|
||||
continue;
|
||||
}
|
||||
TraceObjectSection section = child.queryInterface(TraceObjectSection.class);
|
||||
TraceSection section = child.queryInterface(TraceSection.class);
|
||||
if (section != null) {
|
||||
result.add(section);
|
||||
continue;
|
||||
|
@ -206,12 +206,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
AddressSet result = new AddressSet();
|
||||
for (TraceObjectValue value : ctx.getObjectValues()) {
|
||||
TraceObject child = value.getChild();
|
||||
TraceObjectModule module = child.queryInterface(TraceObjectModule.class);
|
||||
TraceModule module = child.queryInterface(TraceModule.class);
|
||||
if (module != null) {
|
||||
result.add(module.getRange(ctx.getSnap()));
|
||||
continue;
|
||||
}
|
||||
TraceObjectSection section = child.queryInterface(TraceObjectSection.class);
|
||||
TraceSection section = child.queryInterface(TraceSection.class);
|
||||
if (section != null) {
|
||||
result.add(section.getRange(ctx.getSnap()));
|
||||
continue;
|
||||
|
@ -222,13 +222,13 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
|
||||
protected static ModelQuery successorModules(TraceObjectSchema rootSchema, KeyPath path) {
|
||||
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||
return new ModelQuery(schema.searchFor(TraceObjectModule.class, path, true));
|
||||
return new ModelQuery(schema.searchFor(TraceModule.class, path, true));
|
||||
}
|
||||
|
||||
private final DebuggerModulesProvider provider;
|
||||
|
||||
public DebuggerModulesPanel(DebuggerModulesProvider provider) {
|
||||
super(provider.plugin, provider, TraceObjectModule.class);
|
||||
super(provider.plugin, provider, TraceModule.class);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
|
@ -241,15 +241,14 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
protected ModelQuery computeQuery(TraceObject object) {
|
||||
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||
KeyPath seedPath = object.getCanonicalPath();
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
|
||||
if (processPath != null) {
|
||||
ModelQuery result = successorModules(rootSchema, processPath);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
KeyPath containerPath =
|
||||
rootSchema.searchForSuitableContainer(TraceObjectModule.class, seedPath);
|
||||
KeyPath containerPath = rootSchema.searchForSuitableContainer(TraceModule.class, seedPath);
|
||||
if (containerPath != null) {
|
||||
ModelQuery result = successorModules(rootSchema, containerPath);
|
||||
if (!result.isEmpty()) {
|
||||
|
|
|
@ -547,7 +547,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
|
|||
DebuggerModulesPanel modulesPanel;
|
||||
DebuggerSectionsPanel sectionsPanel;
|
||||
|
||||
// TODO: Lazy construction of these dialogs?
|
||||
// LATER?: Lazy construction of these dialogs?
|
||||
private final DebuggerBlockChooserDialog blockChooserDialog;
|
||||
private final DebuggerModuleMapProposalDialog moduleProposalDialog;
|
||||
private final DebuggerSectionMapProposalDialog sectionProposalDialog;
|
||||
|
|
|
@ -30,22 +30,21 @@ import ghidra.framework.plugintool.Plugin;
|
|||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.database.module.TraceObjectSection;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.modules.TraceObjectModule;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.modules.TraceSection;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||
import ghidra.trace.model.thread.TraceProcess;
|
||||
|
||||
public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceObjectSection> {
|
||||
public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceSection> {
|
||||
|
||||
private static class SectionStartColumn extends AbstractTraceValueObjectAddressColumn {
|
||||
|
||||
public SectionStartColumn() {
|
||||
super(TraceObjectSection.KEY_RANGE);
|
||||
super(TraceSection.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,7 +60,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
|
||||
private static class SectionEndColumn extends AbstractTraceValueObjectAddressColumn {
|
||||
public SectionEndColumn() {
|
||||
super(TraceObjectSection.KEY_RANGE);
|
||||
super(TraceSection.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,8 +119,8 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
if (module == null) {
|
||||
return "";
|
||||
}
|
||||
TraceObjectValue nameEntry = module.getAttribute(row.currentSnap(),
|
||||
TraceObjectModule.KEY_MODULE_NAME);
|
||||
TraceObjectValue nameEntry =
|
||||
module.getAttribute(row.currentSnap(), TraceModule.KEY_MODULE_NAME);
|
||||
if (nameEntry == null) {
|
||||
return "";
|
||||
}
|
||||
|
@ -133,7 +132,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
|
||||
private static class SectionLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
||||
public SectionLengthColumn() {
|
||||
super(TraceObjectSection.KEY_RANGE);
|
||||
super(TraceSection.KEY_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -161,21 +160,20 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
}
|
||||
|
||||
private static TraceObject getModule(ValueRow row) {
|
||||
TraceObjectValue moduleEntry =
|
||||
row.getAttributeEntry(TraceObjectSection.KEY_MODULE);
|
||||
TraceObjectValue moduleEntry = row.getAttributeEntry(TraceSection.KEY_MODULE);
|
||||
if (moduleEntry != null && moduleEntry.isObject()) {
|
||||
return moduleEntry.getChild();
|
||||
}
|
||||
return row.getValue()
|
||||
.getChild()
|
||||
.findCanonicalAncestorsInterface(TraceObjectModule.class)
|
||||
.findCanonicalAncestorsInterface(TraceModule.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
protected static ModelQuery successorSections(TraceObjectSchema rootSchema, KeyPath path) {
|
||||
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||
return new ModelQuery(schema.searchFor(TraceObjectSection.class, path, true));
|
||||
return new ModelQuery(schema.searchFor(TraceSection.class, path, true));
|
||||
}
|
||||
|
||||
private class SectionsBySelectedModulesTableFilter implements TableFilter<ValueRow> {
|
||||
|
@ -201,7 +199,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
new SectionsBySelectedModulesTableFilter();
|
||||
|
||||
public DebuggerSectionsPanel(DebuggerModulesProvider provider) {
|
||||
super(provider.plugin, provider, TraceObjectSection.class);
|
||||
super(provider.plugin, provider, TraceSection.class);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
|
@ -214,19 +212,18 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
protected ModelQuery computeQuery(TraceObject object) {
|
||||
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||
KeyPath seedPath = object.getCanonicalPath();
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
|
||||
if (processPath != null) {
|
||||
ModelQuery result = successorSections(rootSchema, processPath);
|
||||
ModelQuery result = successorSections(rootSchema, processPath);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Yes, anchor on the *module* container when searching for sections
|
||||
KeyPath containerPath =
|
||||
rootSchema.searchForSuitableContainer(TraceObjectModule.class, seedPath);
|
||||
KeyPath containerPath = rootSchema.searchForSuitableContainer(TraceModule.class, seedPath);
|
||||
|
||||
if (containerPath != null) {
|
||||
ModelQuery result = successorSections(rootSchema, containerPath);
|
||||
ModelQuery result = successorSections(rootSchema, containerPath);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import ghidra.debug.api.ValStr;
|
|||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod;
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.iface.TraceMethod;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription;
|
||||
|
||||
@Deprecated(forRemoval = true, since = "11.3")
|
||||
public class DebuggerMethodInvocationDialog
|
||||
|
@ -71,7 +71,7 @@ public class DebuggerMethodInvocationDialog
|
|||
protected Map<String, ValStr<?>> validateArguments(
|
||||
Map<String, ParameterDescription<?>> parameters, Map<String, ValStr<?>> arguments) {
|
||||
Map<String, ?> args = ValStr.toPlainMap(arguments);
|
||||
return ValStr.fromPlainMap(TraceObjectMethod.validateArguments(parameters, args, false));
|
||||
return ValStr.fromPlainMap(TraceMethod.validateArguments(parameters, args, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -69,9 +69,9 @@ import ghidra.trace.model.guest.TracePlatform;
|
|||
import ghidra.trace.model.listing.*;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.*;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.trace.util.TraceRegisterUtils;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
@ -283,37 +283,28 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
listenFor(TraceEvents.THREAD_LIFESPAN_CHANGED, this::threadDestroyed);
|
||||
}
|
||||
|
||||
private boolean isVisibleObjectsMode(AddressSpace space) {
|
||||
TraceObject container = current.getRegisterContainer();
|
||||
return container != null &&
|
||||
container.getCanonicalPath().toString().equals(space.getName());
|
||||
}
|
||||
|
||||
private boolean isVisible(TraceAddressSpace space) {
|
||||
private boolean isVisible(AddressSpace space) {
|
||||
if (!space.isRegisterSpace()) {
|
||||
return true; // Memory-mapped, visible no matter the active thread
|
||||
}
|
||||
TraceThread curThread = current.getThread();
|
||||
if (curThread == null) {
|
||||
return false;
|
||||
}
|
||||
if (space.getAddressSpace().isOverlaySpace()) {
|
||||
return isVisibleObjectsMode(space.getAddressSpace());
|
||||
if (space.isOverlaySpace()) {
|
||||
return current.isRegisterSpace(space);
|
||||
}
|
||||
if (!space.getAddressSpace().isRegisterSpace()) {
|
||||
return true; // Memory-mapped, visible no matter the active thread
|
||||
if (space.isRegisterSpace()) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
if (space.getThread() != curThread) {
|
||||
return false;
|
||||
}
|
||||
if (space.getFrameLevel() != current.getFrame()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isVisible(TraceAddressSpace space, TraceAddressSnapRange range) {
|
||||
private boolean isVisible(AddressSpace space, TraceAddressSnapRange range) {
|
||||
if (!isVisible(space)) {
|
||||
return false;
|
||||
}
|
||||
if (space.getAddressSpace().isMemorySpace()) {
|
||||
if (space.isMemorySpace()) {
|
||||
return current.getPlatform()
|
||||
.getLanguage()
|
||||
.getRegisterAddresses()
|
||||
|
@ -351,7 +342,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
}
|
||||
}
|
||||
|
||||
private void registerValueChanged(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
private void registerValueChanged(AddressSpace space, TraceAddressSnapRange range,
|
||||
byte[] oldIsNull, byte[] newVal) {
|
||||
if (!isVisible(space, range)) {
|
||||
return;
|
||||
|
@ -359,7 +350,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
refreshRange(range.getRange());
|
||||
}
|
||||
|
||||
private void registerStateChanged(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
private void registerStateChanged(AddressSpace space, TraceAddressSnapRange range,
|
||||
TraceMemoryState oldState, TraceMemoryState newState) {
|
||||
if (!isVisible(space, range)) {
|
||||
return;
|
||||
|
@ -368,7 +359,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
refreshRange(range.getRange());
|
||||
}
|
||||
|
||||
private void registerTypeAdded(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
private void registerTypeAdded(AddressSpace space, TraceAddressSnapRange range,
|
||||
TraceCodeUnit oldIsNull, TraceCodeUnit newUnit) {
|
||||
if (!isVisible(space, range)) {
|
||||
return;
|
||||
|
@ -376,7 +367,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
refreshRange(range.getRange());
|
||||
}
|
||||
|
||||
private void registerTypeReplaced(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
private void registerTypeReplaced(AddressSpace space, TraceAddressSnapRange range,
|
||||
long oldTypeID, long newTypeID) {
|
||||
if (!isVisible(space, range)) {
|
||||
return;
|
||||
|
@ -384,7 +375,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
refreshRange(range.getRange());
|
||||
}
|
||||
|
||||
private void registerTypeLifespanChanged(TraceAddressSpace space, TraceCodeUnit unit,
|
||||
private void registerTypeLifespanChanged(AddressSpace space, TraceCodeUnit unit,
|
||||
Lifespan oldSpan, Lifespan newSpan) {
|
||||
if (!isVisible(space)) {
|
||||
return;
|
||||
|
@ -402,7 +393,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
refreshRange(range); // Slightly wasteful, as we already have the data unit
|
||||
}
|
||||
|
||||
private void registerTypeRemoved(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
private void registerTypeRemoved(AddressSpace space, TraceAddressSnapRange range,
|
||||
TraceCodeUnit oldUnit, TraceCodeUnit newIsNull) {
|
||||
if (!isVisible(space)) {
|
||||
return;
|
||||
|
|
|
@ -34,15 +34,15 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.stack.TraceObjectStack;
|
||||
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.path.PathFilter;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
|
||||
public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObjectStackFrame>
|
||||
public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceStackFrame>
|
||||
implements ListSelectionListener {
|
||||
|
||||
private static class FrameLevelColumn extends TraceValueKeyColumn {
|
||||
|
@ -59,7 +59,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||
|
||||
private static class FramePcColumn extends TraceValueObjectAttributeColumn<Address> {
|
||||
public FramePcColumn() {
|
||||
super(TraceObjectStackFrame.KEY_PC, Address.class);
|
||||
super(TraceStackFrame.KEY_PC, Address.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,7 +72,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||
if (!(row.getValue().getValue() instanceof TraceObject object)) {
|
||||
return null;
|
||||
}
|
||||
TraceObjectValue attrPc = object.getAttribute(snap, TraceObjectStackFrame.KEY_PC);
|
||||
TraceObjectValue attrPc = object.getAttribute(snap, TraceStackFrame.KEY_PC);
|
||||
if (attrPc == null || !(attrPc.getValue() instanceof Address pc)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||
protected DebuggerTraceManagerService traceManager;
|
||||
|
||||
public DebuggerStackPanel(DebuggerStackProvider provider) {
|
||||
super(provider.plugin, provider, TraceObjectStackFrame.class);
|
||||
super(provider.plugin, provider, TraceStackFrame.class);
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
|
@ -190,12 +190,12 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||
protected ModelQuery computeQuery(TraceObject object) {
|
||||
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||
KeyPath stackPath =
|
||||
rootSchema.searchForSuitable(TraceObjectStack.class, object.getCanonicalPath());
|
||||
rootSchema.searchForSuitable(TraceStack.class, object.getCanonicalPath());
|
||||
if (stackPath == null) {
|
||||
return ModelQuery.EMPTY;
|
||||
}
|
||||
TraceObjectSchema stackSchema = rootSchema.getSuccessorSchema(stackPath);
|
||||
PathFilter filter = stackSchema.searchFor(TraceObjectStackFrame.class, stackPath, true);
|
||||
PathFilter filter = stackSchema.searchFor(TraceStackFrame.class, stackPath, true);
|
||||
return new ModelQuery(filter);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import ghidra.pcode.exec.DebuggerPcodeUtils.PrettyBytes;
|
|||
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
|
||||
import ghidra.pcode.exec.ValueLocation;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.*;
|
||||
|
@ -35,8 +36,7 @@ import ghidra.program.model.pcode.Varnode;
|
|||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.listing.TraceCodeUnit;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
@ -366,17 +366,9 @@ public interface VariableValueRow {
|
|||
* @param snap the snapshot key
|
||||
* @return the composite state
|
||||
*/
|
||||
static TraceMemoryState computeState(Trace trace, TraceAddressSpace space, AddressRange range,
|
||||
static TraceMemoryState computeState(Trace trace, AddressSpace space, AddressRange range,
|
||||
long snap) {
|
||||
TraceMemoryManager mem = trace.getMemoryManager();
|
||||
TraceMemoryOperations ops;
|
||||
if (space != null && space.getAddressSpace().isRegisterSpace()) {
|
||||
ops = mem.getMemoryRegisterSpace(space.getThread(), space.getFrameLevel(), false);
|
||||
}
|
||||
else {
|
||||
ops = mem;
|
||||
}
|
||||
return ops != null && ops.isKnown(snap, range)
|
||||
return trace.getMemoryManager().isKnown(snap, range)
|
||||
? TraceMemoryState.KNOWN
|
||||
: TraceMemoryState.UNKNOWN;
|
||||
}
|
||||
|
@ -387,10 +379,11 @@ public interface VariableValueRow {
|
|||
* @param unit the code unit
|
||||
* @param snap the snapshot key
|
||||
* @return the composite state.
|
||||
* @see #computeState(Trace, TraceAddressSpace, AddressRange, long)
|
||||
* @see #computeState(Trace, AddressSpace, AddressRange, long)
|
||||
*/
|
||||
static TraceMemoryState computeState(TraceCodeUnit unit, long snap) {
|
||||
return computeState(unit.getTrace(), unit.getTraceSpace(), unit.getRange(), snap);
|
||||
return computeState(unit.getTrace(), unit.getAddress().getAddressSpace(), unit.getRange(),
|
||||
snap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,7 +46,6 @@ import ghidra.trace.model.memory.*;
|
|||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.MathUtilities;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -672,10 +671,9 @@ public enum VariableValueUtils {
|
|||
listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged);
|
||||
}
|
||||
|
||||
private void bytesChanged(TraceAddressSpace space, TraceAddressSnapRange range) {
|
||||
TraceThread thread = space.getThread();
|
||||
private void bytesChanged(AddressSpace space, TraceAddressSnapRange range) {
|
||||
// TODO: Consider the lifespan, too? Would have to use viewport....
|
||||
if (thread == null || thread == coordinates.getThread()) {
|
||||
if (space.isMemorySpace() || coordinates.isRegisterSpace(space)) {
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,17 +38,17 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.iface.TraceObjectExecutionStateful;
|
||||
import ghidra.trace.model.target.iface.TraceExecutionStateful;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceProcess;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
||||
public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceObjectThread> {
|
||||
public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceThread> {
|
||||
|
||||
protected static ModelQuery successorThreads(TraceObjectSchema rootSchema, KeyPath path) {
|
||||
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||
return new ModelQuery(schema.searchFor(TraceObjectThread.class, path, true));
|
||||
return new ModelQuery(schema.searchFor(TraceThread.class, path, true));
|
||||
}
|
||||
|
||||
private static class ThreadPathColumn extends TraceValueKeyColumn {
|
||||
|
@ -246,7 +246,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
private static class ThreadStateColumn extends TraceValueObjectAttributeColumn<String> {
|
||||
public ThreadStateColumn() {
|
||||
// NB. The recorder converts enums to strings
|
||||
super(TraceObjectExecutionStateful.KEY_STATE, String.class);
|
||||
super(TraceExecutionStateful.KEY_STATE, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -258,7 +258,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
private static class ThreadCommentColumn
|
||||
extends TraceValueObjectEditableAttributeColumn<String> {
|
||||
public ThreadCommentColumn() {
|
||||
super(TraceObjectThread.KEY_COMMENT, String.class);
|
||||
super(TraceThread.KEY_COMMENT, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -315,7 +315,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
};
|
||||
|
||||
public DebuggerThreadsPanel(DebuggerThreadsProvider provider) {
|
||||
super(provider.plugin, provider, TraceObjectThread.class);
|
||||
super(provider.plugin, provider, TraceThread.class);
|
||||
this.provider = provider;
|
||||
setLimitToSnap(false); // TODO: Toggle for this?
|
||||
|
||||
|
@ -346,18 +346,18 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
protected ModelQuery computeQuery(TraceObject object) {
|
||||
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||
KeyPath seedPath = object.getCanonicalPath();
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||
KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
|
||||
if (processPath != null) {
|
||||
ModelQuery result = successorThreads(rootSchema, processPath);
|
||||
ModelQuery result = successorThreads(rootSchema, processPath);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
KeyPath containerPath =
|
||||
rootSchema.searchForSuitableContainer(TraceObjectThread.class, seedPath);
|
||||
rootSchema.searchForSuitableContainer(TraceThread.class, seedPath);
|
||||
|
||||
if (containerPath != null) {
|
||||
ModelQuery result = successorThreads(rootSchema, containerPath);
|
||||
ModelQuery result = successorThreads(rootSchema, containerPath);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -42,11 +42,15 @@ import ghidra.trace.model.Lifespan;
|
|||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.bookmark.TraceBookmark;
|
||||
import ghidra.trace.model.bookmark.TraceBookmarkManager;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.modules.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.modules.TraceModuleManager;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.thread.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.thread.TraceThreadManager;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
@ -82,7 +86,6 @@ public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin {
|
|||
@SuppressWarnings("unused")
|
||||
private final AutoService.Wiring autoServiceWiring;
|
||||
|
||||
|
||||
public static final String HELP_TOPIC = "OverviewPlugin";
|
||||
private static final String ACTIVE_SERVICES = "ActiveServices";
|
||||
private List<TimeOverviewColorService> allServices;
|
||||
|
@ -270,27 +273,19 @@ public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin {
|
|||
Trace trace = traceManager.getCurrentTrace();
|
||||
TraceThreadManager threadManager = trace.getThreadManager();
|
||||
for (TraceThread thread : threadManager.getAllThreads()) {
|
||||
if (thread instanceof TraceObjectThread objThread) {
|
||||
addObject(set, objThread.getObject());
|
||||
}
|
||||
addObject(set, thread.getObject());
|
||||
}
|
||||
TraceModuleManager moduleManager = trace.getModuleManager();
|
||||
for (TraceModule module : moduleManager.getAllModules()) {
|
||||
if (module instanceof TraceObjectModule objModule) {
|
||||
addObject(set, objModule.getObject());
|
||||
}
|
||||
addObject(set, module.getObject());
|
||||
}
|
||||
TraceMemoryManager memoryManager = trace.getMemoryManager();
|
||||
for (TraceMemoryRegion region : memoryManager.getAllRegions()) {
|
||||
if (region instanceof TraceObjectMemoryRegion objRegion) {
|
||||
addObject(set, objRegion.getObject());
|
||||
}
|
||||
addObject(set, region.getObject());
|
||||
}
|
||||
TraceBreakpointManager breakpointManager = trace.getBreakpointManager();
|
||||
for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) {
|
||||
if (bpt instanceof TraceObjectBreakpointLocation objBreakpoint) {
|
||||
addObject(set, objBreakpoint.getObject());
|
||||
}
|
||||
for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) {
|
||||
addObject(set, bpt.getObject());
|
||||
}
|
||||
TraceBookmarkManager bookmarkManager = trace.getBookmarkManager();
|
||||
for (TraceBookmark mark : bookmarkManager.getAllBookmarks()) {
|
||||
|
|
|
@ -23,11 +23,15 @@ import ghidra.framework.model.DomainObjectChangeRecord;
|
|||
import ghidra.framework.model.DomainObjectEvent;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.bookmark.TraceBookmark;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.trace.model.modules.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.modules.TraceModuleManager;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.thread.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.thread.TraceThreadManager;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.Swing;
|
||||
|
||||
|
@ -118,193 +122,150 @@ public class TimeOverviewEventListener extends TraceDomainObjectListener {
|
|||
regionChanged(region);
|
||||
}
|
||||
TraceBreakpointManager breakpointManager = trace.getBreakpointManager();
|
||||
for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) {
|
||||
for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) {
|
||||
bptChanged(bpt);
|
||||
}
|
||||
}
|
||||
|
||||
private void threadAdded(TraceThread thread) {
|
||||
if (!(thread instanceof TraceObjectThread objThread)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objThread.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.BPT_ADDED, thread.getName(snap), true);
|
||||
});
|
||||
TraceObject obj = thread.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.BPT_ADDED, thread.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void threadChanged(TraceThread thread) {
|
||||
if (!(thread instanceof TraceObjectThread objThread)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objThread.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectThread.KEY_TID, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.THREAD_CHANGED, thread.getName(snapMin), true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.THREAD_ADDED, thread.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.THREAD_REMOVED, thread.getName(snapMax), true);
|
||||
}
|
||||
});
|
||||
TraceObject obj = thread.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceThread.KEY_TID, true).forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.THREAD_CHANGED, thread.getName(snapMin),
|
||||
true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.THREAD_ADDED, thread.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.THREAD_REMOVED, thread.getName(snapMax),
|
||||
true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void threadDeleted(TraceThread thread) {
|
||||
if (!(thread instanceof TraceObjectThread objThread)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objThread.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.THREAD_REMOVED, thread.getName(snap), true);
|
||||
});
|
||||
TraceObject obj = thread.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.THREAD_REMOVED, thread.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void moduleAdded(TraceModule module) {
|
||||
if (!(module instanceof TraceObjectModule objMod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objMod.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.MODULE_ADDED, module.getName(snap), true);
|
||||
});
|
||||
TraceObject obj = module.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.MODULE_ADDED, module.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void moduleChanged(TraceModule module) {
|
||||
if (!(module instanceof TraceObjectModule objMod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objMod.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.MODULE_CHANGED, module.getName(snapMin), true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.MODULE_ADDED, module.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.MODULE_REMOVED, module.getName(snapMax), true);
|
||||
}
|
||||
});
|
||||
TraceObject obj = module.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.MODULE_CHANGED, module.getName(snapMin),
|
||||
true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.MODULE_ADDED, module.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.MODULE_REMOVED, module.getName(snapMax),
|
||||
true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void moduleDeleted(TraceModule module) {
|
||||
if (!(module instanceof TraceObjectModule objMod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objMod.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.MODULE_REMOVED, module.getName(snap), true);
|
||||
});
|
||||
TraceObject obj = module.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.MODULE_REMOVED, module.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void regionAdded(TraceMemoryRegion region) {
|
||||
if (!(region instanceof TraceObjectMemoryRegion objReg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objReg.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.REGION_ADDED, region.getName(snap), true);
|
||||
});
|
||||
TraceObject obj = region.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.REGION_ADDED, region.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void regionChanged(TraceMemoryRegion region) {
|
||||
if (!(region instanceof TraceObjectMemoryRegion objReg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objReg.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.REGION_CHANGED, region.getName(snapMin), true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.REGION_ADDED, region.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.REGION_REMOVED, region.getName(snapMax), true);
|
||||
}
|
||||
});
|
||||
TraceObject obj = region.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.REGION_CHANGED, region.getName(snapMin),
|
||||
true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.REGION_ADDED, region.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.REGION_REMOVED, region.getName(snapMax),
|
||||
true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void regionDeleted(TraceMemoryRegion region) {
|
||||
if (!(region instanceof TraceObjectMemoryRegion objReg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objReg.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.REGION_REMOVED, region.getName(snap), true);
|
||||
});
|
||||
TraceObject obj = region.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.REGION_REMOVED, region.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void bptAdded(TraceBreakpoint bpt) {
|
||||
if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objBpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.BPT_ADDED, bpt.getName(snap), true);
|
||||
});
|
||||
private void bptAdded(TraceBreakpointLocation bpt) {
|
||||
TraceObject obj = bpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMinSnap();
|
||||
p.updateMap(snap, TimeType.BPT_ADDED, bpt.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void bptChanged(TraceBreakpoint bpt) {
|
||||
if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objBpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.BPT_CHANGED, bpt.getName(snapMin), true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.BPT_ADDED, bpt.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.BPT_REMOVED, bpt.getName(snapMax), true);
|
||||
}
|
||||
});
|
||||
private void bptChanged(TraceBreakpointLocation bpt) {
|
||||
TraceObject obj = bpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snapMin = v.getMinSnap();
|
||||
long snapMax = v.getMaxSnap();
|
||||
if (snapMin == snapMax) {
|
||||
p.updateMap(snapMin, TimeType.BPT_CHANGED, bpt.getName(snapMin), true);
|
||||
}
|
||||
else {
|
||||
p.updateMap(snapMin, TimeType.BPT_ADDED, bpt.getName(snapMin), true);
|
||||
p.updateMap(snapMax, TimeType.BPT_REMOVED, bpt.getName(snapMax), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void bptDeleted(TraceBreakpoint bpt) {
|
||||
if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TraceObject obj = objBpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.BPT_REMOVED, bpt.getName(snap), true);
|
||||
});
|
||||
private void bptDeleted(TraceBreakpointLocation bpt) {
|
||||
TraceObject obj = bpt.getObject();
|
||||
obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
|
||||
.forEach(v -> {
|
||||
long snap = v.getMaxSnap();
|
||||
p.updateMap(snap, TimeType.BPT_REMOVED, bpt.getName(snap), true);
|
||||
});
|
||||
}
|
||||
|
||||
private void bookmarkAdded(TraceBookmark bookmark) {
|
||||
|
|
|
@ -78,7 +78,6 @@ import ghidra.trace.model.*;
|
|||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -260,14 +259,14 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter
|
|||
}
|
||||
}
|
||||
|
||||
private void bytesChanged(TraceAddressSpace space, TraceAddressSnapRange range) {
|
||||
if (space.getThread() == current.getThread() || space.getThread() == null) {
|
||||
private void bytesChanged(AddressSpace space, TraceAddressSnapRange range) {
|
||||
if (space.isMemorySpace() || current.isRegisterSpace(space)) {
|
||||
addChanged(range.getRange());
|
||||
}
|
||||
}
|
||||
|
||||
private void stateChanged(TraceAddressSpace space, TraceAddressSnapRange range) {
|
||||
if (space.getThread() == current.getThread() || space.getThread() == null) {
|
||||
private void stateChanged(AddressSpace space, TraceAddressSnapRange range) {
|
||||
if (space.isMemorySpace() || current.isRegisterSpace(space)) {
|
||||
addChanged(range.getRange());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -529,7 +529,7 @@ public class DefaultWatchRow implements WatchRow {
|
|||
DebuggerCoordinates current = provider.current;
|
||||
Trace trace = current.getTrace();
|
||||
Collection<? extends TraceLabelSymbol> labels =
|
||||
trace.getSymbolManager().labels().getAt(current.getSnap(), null, address, false);
|
||||
trace.getSymbolManager().labels().getAt(current.getSnap(), address, false);
|
||||
if (!labels.isEmpty()) {
|
||||
return labels.iterator().next();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import ghidra.trace.model.Lifespan;
|
|||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.iface.TraceObjectEnvironment;
|
||||
import ghidra.trace.model.target.iface.TraceEnvironment;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.path.PathFilter;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -67,7 +67,7 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
|
|||
}
|
||||
TraceObject root = object.getRoot();
|
||||
KeyPath pathToEnv = root.getSchema()
|
||||
.searchForSuitable(TraceObjectEnvironment.class, object.getCanonicalPath());
|
||||
.searchForSuitable(TraceEnvironment.class, object.getCanonicalPath());
|
||||
if (pathToEnv == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -86,15 +86,15 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
|
|||
}
|
||||
|
||||
static String getDebugggerFromEnv(TraceObject env, long snap) {
|
||||
return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_DEBUGGER);
|
||||
return getStringAttribute(env, snap, TraceEnvironment.KEY_DEBUGGER);
|
||||
}
|
||||
|
||||
static String getArchitectureFromEnv(TraceObject env, long snap) {
|
||||
return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_ARCH);
|
||||
return getStringAttribute(env, snap, TraceEnvironment.KEY_ARCH);
|
||||
}
|
||||
|
||||
static String getOperatingSystemFromEnv(TraceObject env, long snap) {
|
||||
return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_OS);
|
||||
return getStringAttribute(env, snap, TraceEnvironment.KEY_OS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,7 +105,7 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
|
|||
* @return the endianness, or null
|
||||
*/
|
||||
static Endian getEndianFromEnv(TraceObject env, long snap) {
|
||||
String strEndian = getStringAttribute(env, snap, TraceObjectEnvironment.KEY_ENDIAN);
|
||||
String strEndian = getStringAttribute(env, snap, TraceEnvironment.KEY_ENDIAN);
|
||||
if (strEndian == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import ghidra.async.AsyncFence;
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
/**
|
||||
* A de-duplicated collection of breakpoint action items necessary to implement a logical breakpoint
|
||||
|
@ -37,11 +37,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
|
|||
* Add an item to enable a target breakpoint
|
||||
*
|
||||
* @param target the target
|
||||
* @param bpt the target breakpoint
|
||||
* @param loc the target breakpoint
|
||||
* @return the added item
|
||||
*/
|
||||
public EnableTargetBreakpointActionItem planEnableTarget(Target target, TraceBreakpoint bpt) {
|
||||
EnableTargetBreakpointActionItem action = new EnableTargetBreakpointActionItem(target, bpt);
|
||||
public EnableTargetBreakpointActionItem planEnableTarget(Target target,
|
||||
TraceBreakpointLocation loc) {
|
||||
EnableTargetBreakpointActionItem action = new EnableTargetBreakpointActionItem(target, loc);
|
||||
add(action);
|
||||
return action;
|
||||
}
|
||||
|
@ -49,12 +50,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
|
|||
/**
|
||||
* Add an item to enable an emulated breakpoint
|
||||
*
|
||||
* @param bpt the trace breakpoint
|
||||
* @param loc the trace breakpoint
|
||||
* @param snap the snap
|
||||
* @return the added item
|
||||
*/
|
||||
public EnableEmuBreakpointActionItem planEnableEmu(TraceBreakpoint bpt, long snap) {
|
||||
EnableEmuBreakpointActionItem action = new EnableEmuBreakpointActionItem(bpt, snap);
|
||||
public EnableEmuBreakpointActionItem planEnableEmu(TraceBreakpointLocation loc, long snap) {
|
||||
EnableEmuBreakpointActionItem action = new EnableEmuBreakpointActionItem(loc, snap);
|
||||
add(action);
|
||||
return action;
|
||||
}
|
||||
|
@ -63,12 +64,13 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
|
|||
* Add an item to disable a target breakpoint
|
||||
*
|
||||
* @param target the target
|
||||
* @param bpt the target breakpoint
|
||||
* @param loc the target breakpoint
|
||||
* @return the added item
|
||||
*/
|
||||
public DisableTargetBreakpointActionItem planDisableTarget(Target target, TraceBreakpoint bpt) {
|
||||
public DisableTargetBreakpointActionItem planDisableTarget(Target target,
|
||||
TraceBreakpointLocation loc) {
|
||||
DisableTargetBreakpointActionItem action =
|
||||
new DisableTargetBreakpointActionItem(target, bpt);
|
||||
new DisableTargetBreakpointActionItem(target, loc);
|
||||
add(action);
|
||||
return action;
|
||||
}
|
||||
|
@ -76,12 +78,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
|
|||
/**
|
||||
* Add an item to disable an emulated breakpoint
|
||||
*
|
||||
* @param bpt the trace breakpoint
|
||||
* @param loc the trace breakpoint
|
||||
* @param snap the snap
|
||||
* @return the added item
|
||||
*/
|
||||
public DisableEmuBreakpointActionItem planDisableEmu(TraceBreakpoint bpt, long snap) {
|
||||
DisableEmuBreakpointActionItem action = new DisableEmuBreakpointActionItem(bpt, snap);
|
||||
public DisableEmuBreakpointActionItem planDisableEmu(TraceBreakpointLocation loc, long snap) {
|
||||
DisableEmuBreakpointActionItem action = new DisableEmuBreakpointActionItem(loc, snap);
|
||||
add(action);
|
||||
return action;
|
||||
}
|
||||
|
@ -90,11 +92,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
|
|||
* Add an item to delete a target breakpoint
|
||||
*
|
||||
* @param target the target
|
||||
* @param bpt the target breakpoint
|
||||
* @param loc the target breakpoint
|
||||
* @return the added item
|
||||
*/
|
||||
public DeleteTargetBreakpointActionItem planDeleteTarget(Target target, TraceBreakpoint bpt) {
|
||||
DeleteTargetBreakpointActionItem action = new DeleteTargetBreakpointActionItem(target, bpt);
|
||||
public DeleteTargetBreakpointActionItem planDeleteTarget(Target target,
|
||||
TraceBreakpointLocation loc) {
|
||||
DeleteTargetBreakpointActionItem action = new DeleteTargetBreakpointActionItem(target, loc);
|
||||
add(action);
|
||||
return action;
|
||||
}
|
||||
|
@ -102,12 +105,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
|
|||
/**
|
||||
* Add an item to delete an emulated breakpoint
|
||||
*
|
||||
* @param bpt the trace breakpoint
|
||||
* @param loc the trace breakpoint
|
||||
* @param snap the snap
|
||||
* @return the added item
|
||||
*/
|
||||
public DeleteEmuBreakpointActionItem planDeleteEmu(TraceBreakpoint bpt, long snap) {
|
||||
DeleteEmuBreakpointActionItem action = new DeleteEmuBreakpointActionItem(bpt, snap);
|
||||
public DeleteEmuBreakpointActionItem planDeleteEmu(TraceBreakpointLocation loc, long snap) {
|
||||
DeleteEmuBreakpointActionItem action = new DeleteEmuBreakpointActionItem(loc, snap);
|
||||
add(action);
|
||||
return action;
|
||||
}
|
||||
|
|
|
@ -45,15 +45,13 @@ import ghidra.framework.model.*;
|
|||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
@ -228,7 +226,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
info.reloadBreakpoints(c);
|
||||
}
|
||||
|
||||
private void breakpointAdded(TraceBreakpoint tb) {
|
||||
private void breakpointAdded(TraceBreakpointLocation tb) {
|
||||
if (!tb.isValid(info.snap)) {
|
||||
return;
|
||||
}
|
||||
|
@ -241,7 +239,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
}
|
||||
|
||||
private void breakpointChanged(TraceBreakpoint tb) {
|
||||
private void breakpointChanged(TraceBreakpointLocation tb) {
|
||||
if (!tb.isValid(info.snap)) {
|
||||
return;
|
||||
}
|
||||
|
@ -258,8 +256,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
}
|
||||
|
||||
private void breakpointLifespanChanged(TraceAddressSpace spaceIsNull, TraceBreakpoint tb,
|
||||
Lifespan oldSpan, Lifespan newSpan) {
|
||||
private void breakpointLifespanChanged(AddressSpace spaceIsNull,
|
||||
TraceBreakpointLocation tb, Lifespan oldSpan, Lifespan newSpan) {
|
||||
// NOTE: User/script probably modified historical breakpoint
|
||||
boolean isInOld = oldSpan.contains(info.snap);
|
||||
boolean isInNew = newSpan.contains(info.snap);
|
||||
|
@ -280,7 +278,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
}
|
||||
|
||||
private void breakpointDeleted(TraceBreakpoint tb) {
|
||||
private void breakpointDeleted(TraceBreakpointLocation tb) {
|
||||
// Could check snap, but might as well just be sure it's gone
|
||||
info.forgetTraceBreakpoint(c.r, tb);
|
||||
}
|
||||
|
@ -360,7 +358,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
long length, Collection<TraceBreakpointKind> kinds);
|
||||
|
||||
protected LogicalBreakpointInternal getOrCreateLogicalBreakpointFor(AddCollector a,
|
||||
Address address, TraceBreakpoint tb, long snap) throws TrackedTooSoonException {
|
||||
Address address, TraceBreakpointLocation tb, long snap)
|
||||
throws TrackedTooSoonException {
|
||||
Set<LogicalBreakpointInternal> set =
|
||||
logicalByAddress.computeIfAbsent(address, __ -> new HashSet<>());
|
||||
for (LogicalBreakpointInternal lb : set) {
|
||||
|
@ -377,7 +376,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
protected boolean removeLogicalBreakpoint(Address address, LogicalBreakpoint lb) {
|
||||
for (TraceBreakpoint tb : lb.getTraceBreakpoints()) {
|
||||
for (TraceBreakpointLocation tb : lb.getTraceBreakpoints()) {
|
||||
InfoPerTrace info = traceInfos.get(tb.getTrace());
|
||||
if (info != null) {
|
||||
info.logicalByBreakpoint.remove(tb);
|
||||
|
@ -435,7 +434,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
protected class InfoPerTrace extends AbstractInfo {
|
||||
final Map<TraceBreakpoint, LogicalBreakpointInternal> logicalByBreakpoint = new HashMap<>();
|
||||
final Map<TraceBreakpointLocation, LogicalBreakpointInternal> logicalByBreakpoint =
|
||||
new HashMap<>();
|
||||
|
||||
final Trace trace;
|
||||
final TraceBreakpointsListener breakpointListener;
|
||||
|
@ -486,12 +486,12 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
protected void forgetAllBreakpoints(RemoveCollector r) {
|
||||
Collection<TraceBreakpoint> toForget = new ArrayList<>();
|
||||
Collection<TraceBreakpointLocation> toForget = new ArrayList<>();
|
||||
for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) {
|
||||
toForget.addAll(
|
||||
trace.getBreakpointManager().getBreakpointsIntersecting(Lifespan.ALL, range));
|
||||
}
|
||||
for (TraceBreakpoint tb : toForget) {
|
||||
for (TraceBreakpointLocation tb : toForget) {
|
||||
forgetTraceBreakpoint(r, tb);
|
||||
}
|
||||
}
|
||||
|
@ -504,16 +504,16 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
*/
|
||||
ControlMode mode = getMode(trace);
|
||||
|
||||
for (Entry<TraceBreakpoint, LogicalBreakpointInternal> ent : Set
|
||||
for (Entry<TraceBreakpointLocation, LogicalBreakpointInternal> ent : Set
|
||||
.copyOf(logicalByBreakpoint.entrySet())) {
|
||||
TraceBreakpoint tb = ent.getKey();
|
||||
TraceBreakpointLocation tb = ent.getKey();
|
||||
LogicalBreakpoint lb = ent.getValue();
|
||||
if (!mode.useEmulatedBreakpoints() &&
|
||||
(target == null || !target.isBreakpointValid(tb))) {
|
||||
forgetTraceBreakpoint(r, tb);
|
||||
continue;
|
||||
}
|
||||
if (!trace.getBreakpointManager().getAllBreakpoints().contains(tb)) {
|
||||
if (!trace.getBreakpointManager().getAllBreakpointLocations().contains(tb)) {
|
||||
forgetTraceBreakpoint(r, tb);
|
||||
continue;
|
||||
}
|
||||
|
@ -536,7 +536,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
if (!mode.useEmulatedBreakpoints() && target == null) {
|
||||
return;
|
||||
}
|
||||
Collection<TraceBreakpoint> visible = new ArrayList<>();
|
||||
Collection<TraceBreakpointLocation> visible = new ArrayList<>();
|
||||
for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) {
|
||||
visible.addAll(trace.getBreakpointManager()
|
||||
.getBreakpointsIntersecting(Lifespan.at(snap), range));
|
||||
|
@ -545,8 +545,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
protected void trackTraceBreakpoints(AddCollector a,
|
||||
Collection<TraceBreakpoint> breakpoints, ControlMode mode) {
|
||||
for (TraceBreakpoint tb : breakpoints) {
|
||||
Collection<TraceBreakpointLocation> breakpoints, ControlMode mode) {
|
||||
for (TraceBreakpointLocation tb : breakpoints) {
|
||||
try {
|
||||
/**
|
||||
* Sadly, even something as simple as toggling a breakpoint can cause so many
|
||||
|
@ -562,7 +562,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
}
|
||||
|
||||
protected ProgramLocation computeStaticLocation(TraceBreakpoint tb) {
|
||||
protected ProgramLocation computeStaticLocation(TraceBreakpointLocation tb) {
|
||||
if (traceManager == null || !traceManager.getOpenTraces().contains(tb.getTrace())) {
|
||||
/**
|
||||
* Mapping service will throw an exception otherwise. NB: When trace is opened,
|
||||
|
@ -579,7 +579,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
new DefaultTraceLocation(trace, null, Lifespan.at(snap), minAddress));
|
||||
}
|
||||
|
||||
protected void trackTraceBreakpoint(AddCollector a, TraceBreakpoint tb, ControlMode mode,
|
||||
protected void trackTraceBreakpoint(AddCollector a, TraceBreakpointLocation tb,
|
||||
ControlMode mode,
|
||||
boolean forceUpdate) throws TrackedTooSoonException {
|
||||
if (!mode.useEmulatedBreakpoints() &&
|
||||
(target == null || !target.isBreakpointValid(tb))) {
|
||||
|
@ -607,7 +608,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
protected LogicalBreakpointInternal removeFromLogicalBreakpoint(RemoveCollector r,
|
||||
TraceBreakpoint tb) {
|
||||
TraceBreakpointLocation tb) {
|
||||
LogicalBreakpointInternal lb = logicalByBreakpoint.remove(tb);
|
||||
if (lb == null || !lb.untrackBreakpoint(tb)) {
|
||||
return null;
|
||||
|
@ -624,7 +625,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
return lb;
|
||||
}
|
||||
|
||||
protected void forgetTraceBreakpoint(RemoveCollector r, TraceBreakpoint tb) {
|
||||
protected void forgetTraceBreakpoint(RemoveCollector r, TraceBreakpointLocation tb) {
|
||||
LogicalBreakpointInternal lb = removeFromLogicalBreakpoint(r, tb);
|
||||
if (lb == null) {
|
||||
return; // Warnings already logged
|
||||
|
@ -1114,7 +1115,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
@Override
|
||||
public LogicalBreakpoint getBreakpoint(TraceBreakpoint bpt) {
|
||||
public LogicalBreakpoint getBreakpoint(TraceBreakpointLocation bpt) {
|
||||
Trace trace = bpt.getTrace();
|
||||
synchronized (lock) {
|
||||
InfoPerTrace info = traceInfos.get(trace);
|
||||
|
@ -1271,18 +1272,18 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
interface TargetBreakpointConsumer {
|
||||
void accept(BreakpointActionSet actions, Target target, TraceBreakpoint tb);
|
||||
void accept(BreakpointActionSet actions, Target target, TraceBreakpointLocation tb);
|
||||
}
|
||||
|
||||
interface EmuBreakpointConsumer {
|
||||
void accept(BreakpointActionSet actions, TraceBreakpoint tb, long snap);
|
||||
void accept(BreakpointActionSet actions, TraceBreakpointLocation tb, long snap);
|
||||
}
|
||||
|
||||
interface ProgramBreakpointConsumer {
|
||||
void accept(LogicalBreakpoint lb);
|
||||
}
|
||||
|
||||
private void planActOnLoc(BreakpointActionSet actions, TraceBreakpoint tb,
|
||||
private void planActOnLoc(BreakpointActionSet actions, TraceBreakpointLocation tb,
|
||||
TargetBreakpointConsumer targetBptConsumer, EmuBreakpointConsumer emuLocConsumer) {
|
||||
ControlMode mode = getMode(tb.getTrace());
|
||||
if (mode.useEmulatedBreakpoints()) {
|
||||
|
@ -1293,7 +1294,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
}
|
||||
|
||||
private void planActOnLocTarget(BreakpointActionSet actions, TraceBreakpoint tb,
|
||||
private void planActOnLocTarget(BreakpointActionSet actions, TraceBreakpointLocation tb,
|
||||
TargetBreakpointConsumer targetBptConsumer) {
|
||||
Target target = targetService == null ? null : targetService.getTarget(tb.getTrace());
|
||||
if (target == null) {
|
||||
|
@ -1302,7 +1303,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
targetBptConsumer.accept(actions, target, tb);
|
||||
}
|
||||
|
||||
private void planActOnLocEmu(BreakpointActionSet actions, TraceBreakpoint tb,
|
||||
private void planActOnLocEmu(BreakpointActionSet actions, TraceBreakpointLocation tb,
|
||||
EmuBreakpointConsumer emuLocConsumer) {
|
||||
InfoPerTrace info = traceInfos.get(tb.getTrace());
|
||||
if (info == null) {
|
||||
|
@ -1312,12 +1313,12 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
emuLocConsumer.accept(actions, tb, info.snap);
|
||||
}
|
||||
|
||||
protected CompletableFuture<Void> actOnLocs(Collection<TraceBreakpoint> col,
|
||||
protected CompletableFuture<Void> actOnLocs(Collection<TraceBreakpointLocation> col,
|
||||
TargetBreakpointConsumer targetBptConsumer,
|
||||
EmuBreakpointConsumer emuLocConsumer,
|
||||
ProgramBreakpointConsumer progConsumer) {
|
||||
BreakpointActionSet actions = new BreakpointActionSet();
|
||||
for (TraceBreakpoint tb : col) {
|
||||
for (TraceBreakpointLocation tb : col) {
|
||||
LogicalBreakpoint lb = getBreakpoint(tb);
|
||||
if (col.containsAll(lb.getTraceBreakpoints())) {
|
||||
progConsumer.accept(lb);
|
||||
|
@ -1328,19 +1329,19 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> enableLocs(Collection<TraceBreakpoint> col) {
|
||||
public CompletableFuture<Void> enableLocs(Collection<TraceBreakpointLocation> col) {
|
||||
return actOnLocs(col, BreakpointActionSet::planEnableTarget,
|
||||
BreakpointActionSet::planEnableEmu, LogicalBreakpoint::enableForProgram);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> disableLocs(Collection<TraceBreakpoint> col) {
|
||||
public CompletableFuture<Void> disableLocs(Collection<TraceBreakpointLocation> col) {
|
||||
return actOnLocs(col, BreakpointActionSet::planDisableTarget,
|
||||
BreakpointActionSet::planDisableEmu, LogicalBreakpoint::disableForProgram);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteLocs(Collection<TraceBreakpoint> col) {
|
||||
public CompletableFuture<Void> deleteLocs(Collection<TraceBreakpointLocation> col) {
|
||||
return actOnLocs(col, BreakpointActionSet::planDeleteTarget,
|
||||
BreakpointActionSet::planDeleteEmu, lb -> {
|
||||
// Never delete bookmark when user requests deleting locations
|
||||
|
|
|
@ -19,20 +19,20 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import db.Transaction;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public record DeleteEmuBreakpointActionItem(TraceBreakpoint bpt, long snap)
|
||||
public record DeleteEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap)
|
||||
implements BreakpointActionItem {
|
||||
@Override
|
||||
public CompletableFuture<Void> execute() {
|
||||
try (Transaction tx =
|
||||
bpt.getTrace().openTransaction("Delete Emulated Breakpoint")) {
|
||||
String emuName = PlaceEmuBreakpointActionItem.createName(bpt.getMinAddress(snap));
|
||||
if (bpt.getPath().contains(emuName)) {
|
||||
bpt.delete();
|
||||
loc.getTrace().openTransaction("Delete Emulated Breakpoint")) {
|
||||
String emuName = PlaceEmuBreakpointActionItem.createName(loc.getMinAddress(snap));
|
||||
if (loc.getPath().contains(emuName)) {
|
||||
loc.delete();
|
||||
}
|
||||
else {
|
||||
bpt.setEmuEnabled(snap, false);
|
||||
loc.setEmuEnabled(snap, false);
|
||||
}
|
||||
}
|
||||
return AsyncUtils.nil();
|
||||
|
|
|
@ -18,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public record DeleteTargetBreakpointActionItem(Target target, TraceBreakpoint bpt)
|
||||
public record DeleteTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc)
|
||||
implements BreakpointActionItem {
|
||||
@Override
|
||||
public CompletableFuture<Void> execute() {
|
||||
return target.deleteBreakpointAsync(bpt);
|
||||
return target.deleteBreakpointAsync(loc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import db.Transaction;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public record DisableEmuBreakpointActionItem(TraceBreakpoint bpt, long snap)
|
||||
public record DisableEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap)
|
||||
implements BreakpointActionItem {
|
||||
@Override
|
||||
public CompletableFuture<Void> execute() {
|
||||
try (Transaction tx =
|
||||
bpt.getTrace().openTransaction("Disable Emulated Breakpoint")) {
|
||||
bpt.setEmuEnabled(snap, false);
|
||||
loc.getTrace().openTransaction("Disable Emulated Breakpoint")) {
|
||||
loc.setEmuEnabled(snap, false);
|
||||
}
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public record DisableTargetBreakpointActionItem(Target target, TraceBreakpoint bpt)
|
||||
public record DisableTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc)
|
||||
implements BreakpointActionItem {
|
||||
@Override
|
||||
public CompletableFuture<Void> execute() {
|
||||
return target.toggleBreakpointAsync(bpt, false);
|
||||
return target.toggleBreakpointAsync(loc, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import db.Transaction;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public record EnableEmuBreakpointActionItem(TraceBreakpoint bpt, long snap)
|
||||
public record EnableEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap)
|
||||
implements BreakpointActionItem {
|
||||
@Override
|
||||
public CompletableFuture<Void> execute() {
|
||||
try (Transaction tx =
|
||||
bpt.getTrace().openTransaction("Enable Emulated Breakpoint")) {
|
||||
bpt.setEmuEnabled(snap, true);
|
||||
loc.getTrace().openTransaction("Enable Emulated Breakpoint")) {
|
||||
loc.setEmuEnabled(snap, true);
|
||||
}
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public record EnableTargetBreakpointActionItem(Target target, TraceBreakpoint bpt)
|
||||
public record EnableTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc)
|
||||
implements BreakpointActionItem {
|
||||
@Override
|
||||
public CompletableFuture<Void> execute() {
|
||||
return target.toggleBreakpointAsync(bpt, true);
|
||||
return target.toggleBreakpointAsync(loc, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.listing.Bookmark;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public interface LogicalBreakpointInternal extends LogicalBreakpoint {
|
||||
/**
|
||||
|
@ -60,13 +60,13 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint {
|
|||
* @return true if it can be aggregated.
|
||||
* @throws TrackedTooSoonException if the containing trace is still being added to the manager
|
||||
*/
|
||||
boolean canMerge(TraceBreakpoint breakpoint, long snap) throws TrackedTooSoonException;
|
||||
boolean canMerge(TraceBreakpointLocation breakpoint, long snap) throws TrackedTooSoonException;
|
||||
|
||||
boolean trackBreakpoint(Bookmark bookmark);
|
||||
|
||||
boolean trackBreakpoint(TraceBreakpoint breakpoint);
|
||||
boolean trackBreakpoint(TraceBreakpointLocation breakpoint);
|
||||
|
||||
boolean untrackBreakpoint(TraceBreakpoint breakpoint);
|
||||
boolean untrackBreakpoint(TraceBreakpointLocation breakpoint);
|
||||
|
||||
boolean untrackBreakpoint(Program program, Bookmark bookmark);
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ import ghidra.program.model.listing.Bookmark;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
|
||||
private final Set<Trace> justThisTrace;
|
||||
|
@ -111,12 +111,12 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceBreakpoint> getTraceBreakpoints() {
|
||||
public Set<TraceBreakpointLocation> getTraceBreakpoints() {
|
||||
return breaks.getBreakpoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceBreakpoint> getTraceBreakpoints(Trace trace) {
|
||||
public Set<TraceBreakpointLocation> getTraceBreakpoints(Trace trace) {
|
||||
return breaks.getTrace() != trace ? Set.of() : getTraceBreakpoints();
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State computeStateForLocation(TraceBreakpoint loc) {
|
||||
public State computeStateForLocation(TraceBreakpointLocation loc) {
|
||||
if (!breaks.getBreakpoints().contains(loc)) {
|
||||
return State.NONE;
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canMerge(TraceBreakpoint breakpoint, long snap) {
|
||||
public boolean canMerge(TraceBreakpointLocation breakpoint, long snap) {
|
||||
if (!Objects.equals(kinds, breakpoint.getKinds(snap))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean trackBreakpoint(TraceBreakpoint breakpoint) {
|
||||
public boolean trackBreakpoint(TraceBreakpointLocation breakpoint) {
|
||||
return breaks.add(breakpoint);
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean untrackBreakpoint(TraceBreakpoint breakpoint) {
|
||||
public boolean untrackBreakpoint(TraceBreakpointLocation breakpoint) {
|
||||
return breaks.remove(breakpoint);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import ghidra.program.model.listing.Bookmark;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
||||
|
||||
|
@ -309,8 +309,8 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceBreakpoint> getTraceBreakpoints() {
|
||||
Set<TraceBreakpoint> result = new HashSet<>();
|
||||
public Set<TraceBreakpointLocation> getTraceBreakpoints() {
|
||||
Set<TraceBreakpointLocation> result = new HashSet<>();
|
||||
synchronized (traceBreaks) {
|
||||
for (TraceBreakpointSet breaks : traceBreaks.values()) {
|
||||
result.addAll(breaks.getBreakpoints());
|
||||
|
@ -320,7 +320,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceBreakpoint> getTraceBreakpoints(Trace trace) {
|
||||
public Set<TraceBreakpointLocation> getTraceBreakpoints(Trace trace) {
|
||||
TraceBreakpointSet breaks;
|
||||
synchronized (traceBreaks) {
|
||||
breaks = traceBreaks.get(trace);
|
||||
|
@ -400,7 +400,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
return progMode.combineTrace(traceMode, Perspective.TRACE);
|
||||
}
|
||||
|
||||
protected TraceMode computeTraceModeForLocation(TraceBreakpoint loc) {
|
||||
protected TraceMode computeTraceModeForLocation(TraceBreakpointLocation loc) {
|
||||
TraceBreakpointSet breaks;
|
||||
synchronized (traceBreaks) {
|
||||
breaks = traceBreaks.get(loc.getTrace());
|
||||
|
@ -412,7 +412,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State computeStateForLocation(TraceBreakpoint loc) {
|
||||
public State computeStateForLocation(TraceBreakpointLocation loc) {
|
||||
ProgramMode progMode = progBreak.computeMode();
|
||||
TraceMode traceMode = computeTraceModeForLocation(loc);
|
||||
return progMode.combineTrace(traceMode, Perspective.TRACE);
|
||||
|
@ -478,7 +478,8 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canMerge(TraceBreakpoint breakpoint, long snap) throws TrackedTooSoonException {
|
||||
public boolean canMerge(TraceBreakpointLocation breakpoint, long snap)
|
||||
throws TrackedTooSoonException {
|
||||
TraceBreakpointSet breaks;
|
||||
synchronized (traceBreaks) {
|
||||
breaks = traceBreaks.get(breakpoint.getTrace());
|
||||
|
@ -530,7 +531,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean trackBreakpoint(TraceBreakpoint breakpoint) {
|
||||
public boolean trackBreakpoint(TraceBreakpointLocation breakpoint) {
|
||||
TraceBreakpointSet breaks;
|
||||
synchronized (traceBreaks) {
|
||||
breaks = traceBreaks.get(breakpoint.getTrace());
|
||||
|
@ -556,7 +557,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean untrackBreakpoint(TraceBreakpoint breakpoint) {
|
||||
public boolean untrackBreakpoint(TraceBreakpointLocation breakpoint) {
|
||||
TraceBreakpointSet breaks;
|
||||
synchronized (traceBreaks) {
|
||||
breaks = traceBreaks.get(breakpoint.getTrace());
|
||||
|
|
|
@ -26,7 +26,6 @@ import ghidra.trace.model.Lifespan;
|
|||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.path.PathFilter;
|
||||
|
@ -49,42 +48,37 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
|
|||
this.emuSleigh = emuSleigh;
|
||||
}
|
||||
|
||||
private TraceObjectMemoryRegion findRegion() {
|
||||
private TraceMemoryRegion findRegion() {
|
||||
TraceMemoryRegion region = trace.getMemoryManager().getRegionContaining(snap, address);
|
||||
if (region != null) {
|
||||
return (TraceObjectMemoryRegion) region;
|
||||
return region;
|
||||
}
|
||||
AddressSpace space = address.getAddressSpace();
|
||||
Collection<? extends TraceMemoryRegion> regionsInSpace = trace.getMemoryManager()
|
||||
.getRegionsIntersecting(Lifespan.at(snap),
|
||||
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()));
|
||||
if (!regionsInSpace.isEmpty()) {
|
||||
return (TraceObjectMemoryRegion) regionsInSpace.iterator().next();
|
||||
return regionsInSpace.iterator().next();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private TraceObject findBreakpointContainer() {
|
||||
TraceObjectMemoryRegion region = findRegion();
|
||||
TraceMemoryRegion region = findRegion();
|
||||
if (region == null) {
|
||||
throw new IllegalArgumentException("Address does not belong to a memory in the trace");
|
||||
}
|
||||
return region.getObject()
|
||||
.findSuitableContainerInterface(TraceObjectBreakpointSpec.class);
|
||||
return region.getObject().findSuitableContainerInterface(TraceBreakpointSpec.class);
|
||||
}
|
||||
|
||||
private String computePath() {
|
||||
String name = createName(address);
|
||||
if (Trace.isLegacy(trace)) {
|
||||
return "Breakpoints[" + name + "]";
|
||||
}
|
||||
TraceObject container = findBreakpointContainer();
|
||||
if (container == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Address is not associated with a breakpoint container");
|
||||
}
|
||||
PathFilter specFilter =
|
||||
container.getSchema().searchFor(TraceObjectBreakpointSpec.class, true);
|
||||
PathFilter specFilter = container.getSchema().searchFor(TraceBreakpointSpec.class, true);
|
||||
if (specFilter == null) {
|
||||
throw new IllegalArgumentException("Cannot find path to breakpoint specifications");
|
||||
}
|
||||
|
@ -94,7 +88,7 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
|
|||
}
|
||||
PathFilter locFilter = container.getSchema()
|
||||
.getSuccessorSchema(specRelPath)
|
||||
.searchFor(TraceObjectBreakpointLocation.class, true);
|
||||
.searchFor(TraceBreakpointLocation.class, true);
|
||||
if (locFilter == null) {
|
||||
throw new IllegalArgumentException("Cannot find path to breakpoint locations");
|
||||
}
|
||||
|
@ -109,11 +103,11 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
|
|||
public CompletableFuture<Void> execute() {
|
||||
try (Transaction tx = trace.openTransaction("Place Emulated Breakpoint")) {
|
||||
// Defaults with emuEnable=true
|
||||
TraceBreakpoint bpt = trace.getBreakpointManager()
|
||||
TraceBreakpointLocation loc = trace.getBreakpointManager()
|
||||
.addBreakpoint(computePath(), Lifespan.at(snap),
|
||||
BreakpointActionItem.range(address, length), Set.of(), kinds, false, null);
|
||||
bpt.setName(snap, createName(address));
|
||||
bpt.setEmuSleigh(snap, emuSleigh);
|
||||
loc.setName(snap, createName(address));
|
||||
loc.setEmuSleigh(snap, emuSleigh);
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
|
|
|
@ -28,8 +28,8 @@ import ghidra.framework.plugintool.PluginTool;
|
|||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import utilities.util.IDHashed;
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@ class TraceBreakpointSet {
|
|||
private final Trace trace;
|
||||
private final Address address;
|
||||
|
||||
private final Set<IDHashed<TraceBreakpoint>> breakpoints = new HashSet<>();
|
||||
private final Set<IDHashed<TraceBreakpointLocation>> breakpoints = new HashSet<>();
|
||||
|
||||
private Target target;
|
||||
private String emuSleigh;
|
||||
|
@ -120,8 +120,8 @@ class TraceBreakpointSet {
|
|||
*
|
||||
* <p>
|
||||
* In most cases, there is 0 or 1 trace breakpoints that "fit" the logical breakpoint. The mode
|
||||
* is derived from one of {@link TraceBreakpoint#isEnabled(long)} or
|
||||
* {@link TraceBreakpoint#isEmuEnabled(long)}, depending on the UI's control mode for this
|
||||
* is derived from one of {@link TraceBreakpointLocation#isEnabled(long)} or
|
||||
* {@link TraceBreakpointLocation#isEmuEnabled(long)}, depending on the UI's control mode for this
|
||||
* trace.
|
||||
*
|
||||
* @return the mode
|
||||
|
@ -130,7 +130,7 @@ class TraceBreakpointSet {
|
|||
TraceMode mode = TraceMode.NONE;
|
||||
synchronized (breakpoints) {
|
||||
if (getControlMode().useEmulatedBreakpoints()) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
mode = mode.combine(computeEmuMode(bpt.obj));
|
||||
if (mode == TraceMode.MISSING) {
|
||||
return mode;
|
||||
|
@ -138,7 +138,7 @@ class TraceBreakpointSet {
|
|||
}
|
||||
return mode;
|
||||
}
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
mode = mode.combine(computeTargetMode(bpt.obj));
|
||||
if (mode == TraceMode.MISSING) {
|
||||
return mode;
|
||||
|
@ -152,14 +152,14 @@ class TraceBreakpointSet {
|
|||
* Compute the mode (enablement) of the given breakpoint
|
||||
*
|
||||
* <p>
|
||||
* The mode is derived from one of {@link TraceBreakpoint#isEnabled(long)} or
|
||||
* {@link TraceBreakpoint#isEmuEnabled(long)}, depending on the UI's control mode for this
|
||||
* The mode is derived from one of {@link TraceBreakpointLocation#isEnabled(long)} or
|
||||
* {@link TraceBreakpointLocation#isEmuEnabled(long)}, depending on the UI's control mode for this
|
||||
* trace.
|
||||
*
|
||||
* @param bpt the breakpoint
|
||||
* @return the mode
|
||||
*/
|
||||
public TraceMode computeMode(TraceBreakpoint bpt) {
|
||||
public TraceMode computeMode(TraceBreakpointLocation bpt) {
|
||||
return getControlMode().useEmulatedBreakpoints()
|
||||
? computeEmuMode(bpt)
|
||||
: computeTargetMode(bpt);
|
||||
|
@ -171,7 +171,7 @@ class TraceBreakpointSet {
|
|||
* @param bpt the breakpoint
|
||||
* @return the mode
|
||||
*/
|
||||
public TraceMode computeTargetMode(TraceBreakpoint bpt) {
|
||||
public TraceMode computeTargetMode(TraceBreakpointLocation bpt) {
|
||||
return TraceMode.fromBool(bpt.isEnabled(getSnap()));
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ class TraceBreakpointSet {
|
|||
* @param bpt the breakpoint
|
||||
* @return the mode
|
||||
*/
|
||||
public TraceMode computeEmuMode(TraceBreakpoint bpt) {
|
||||
public TraceMode computeEmuMode(TraceBreakpointLocation bpt) {
|
||||
return TraceMode.fromBool(bpt.isEmuEnabled(getSnap()));
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ class TraceBreakpointSet {
|
|||
String sleigh = null;
|
||||
long snap = getSnap();
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
String s = bpt.obj.getEmuSleigh(snap);
|
||||
if (sleigh != null && !sleigh.equals(s)) {
|
||||
return null;
|
||||
|
@ -215,7 +215,7 @@ class TraceBreakpointSet {
|
|||
long snap = getSnap();
|
||||
try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
bpt.obj.setEmuSleigh(snap, emuSleigh);
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ class TraceBreakpointSet {
|
|||
*
|
||||
* @return the breakpoints
|
||||
*/
|
||||
public Set<TraceBreakpoint> getBreakpoints() {
|
||||
public Set<TraceBreakpointLocation> getBreakpoints() {
|
||||
synchronized (breakpoints) {
|
||||
return breakpoints.stream().map(e -> e.obj).collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
@ -248,13 +248,13 @@ class TraceBreakpointSet {
|
|||
* Add a breakpoint to this set
|
||||
*
|
||||
* <p>
|
||||
* The caller should first call {@link #canMerge(TraceBreakpoint)} to check if the breakpoint
|
||||
* The caller should first call {@link #canMerge(TraceBreakpointLocation)} to check if the breakpoint
|
||||
* "fits."
|
||||
*
|
||||
* @param bpt the breakpoint
|
||||
* @return true if the set actually changed as a result
|
||||
*/
|
||||
public boolean add(TraceBreakpoint bpt) {
|
||||
public boolean add(TraceBreakpointLocation bpt) {
|
||||
long snap = getSnap();
|
||||
if (SleighUtils.UNCONDITIONAL_BREAK.equals(bpt.getEmuSleigh(snap)) && emuSleigh != null) {
|
||||
try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) {
|
||||
|
@ -275,7 +275,7 @@ class TraceBreakpointSet {
|
|||
* @param bpt the breakpoint
|
||||
* @return true if it fits
|
||||
*/
|
||||
public boolean canMerge(TraceBreakpoint bpt) {
|
||||
public boolean canMerge(TraceBreakpointLocation bpt) {
|
||||
if (trace != bpt.getTrace()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ class TraceBreakpointSet {
|
|||
* @param bpt the breakpoint
|
||||
* @return true if the set actually changes as a result
|
||||
*/
|
||||
public boolean remove(TraceBreakpoint bpt) {
|
||||
public boolean remove(TraceBreakpointLocation bpt) {
|
||||
synchronized (breakpoints) {
|
||||
return breakpoints.remove(new IDHashed<>(bpt));
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ class TraceBreakpointSet {
|
|||
|
||||
private void planEnableTarget(BreakpointActionSet actions) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
actions.planEnableTarget(target, bpt.obj);
|
||||
}
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ class TraceBreakpointSet {
|
|||
|
||||
private void planEnableEmu(BreakpointActionSet actions) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
actions.planEnableEmu(bpt.obj, getSnap());
|
||||
}
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ class TraceBreakpointSet {
|
|||
private void planDisableTarget(BreakpointActionSet actions, long length,
|
||||
Collection<TraceBreakpointKind> kinds) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
actions.planDisableTarget(target, bpt.obj);
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ class TraceBreakpointSet {
|
|||
|
||||
private void planDisableEmu(BreakpointActionSet actions) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
actions.planDisableEmu(bpt.obj, getSnap());
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ class TraceBreakpointSet {
|
|||
private void planDeleteTarget(BreakpointActionSet actions, long length,
|
||||
Set<TraceBreakpointKind> kinds) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
actions.planDeleteTarget(target, bpt.obj);
|
||||
}
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ class TraceBreakpointSet {
|
|||
|
||||
private void planDeleteEmu(BreakpointActionSet actions) {
|
||||
synchronized (breakpoints) {
|
||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||
for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
|
||||
actions.planDeleteEmu(bpt.obj, getSnap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package ghidra.app.plugin.core.debug.service.emulation;
|
|||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
@ -45,6 +45,7 @@ import ghidra.async.AsyncLazyMap;
|
|||
import ghidra.debug.api.control.ControlMode;
|
||||
import ghidra.debug.api.emulation.DebuggerPcodeEmulatorFactory;
|
||||
import ghidra.debug.api.emulation.DebuggerPcodeMachine;
|
||||
import ghidra.debug.api.modules.DebuggerStaticMappingChangeListener;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
|
@ -638,7 +639,7 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm
|
|||
Lifespan span = Lifespan.at(snap);
|
||||
TraceBreakpointManager bm = trace.getBreakpointManager();
|
||||
for (AddressSpace as : trace.getBaseAddressFactory().getAddressSpaces()) {
|
||||
for (TraceBreakpoint bpt : bm.getBreakpointsIntersecting(span,
|
||||
for (TraceBreakpointLocation bpt : bm.getBreakpointsIntersecting(span,
|
||||
new AddressRangeImpl(as.getMinAddress(), as.getMaxAddress()))) {
|
||||
if (!bpt.isEmuEnabled(snap)) {
|
||||
continue;
|
||||
|
@ -797,14 +798,43 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm
|
|||
}
|
||||
}
|
||||
|
||||
class TraceMappingWaiter extends CompletableFuture<Void>
|
||||
implements DebuggerStaticMappingChangeListener {
|
||||
private final Trace trace;
|
||||
|
||||
public TraceMappingWaiter(Trace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mappingsChanged(Set<Trace> affectedTraces, Set<Program> affectedPrograms) {
|
||||
if (affectedTraces.contains(trace)) {
|
||||
complete(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void softWait() {
|
||||
try {
|
||||
get(1, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
Msg.warn(this, "Mappings not reported by service after 1 second");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trace launchProgram(Program program, Address address) throws IOException {
|
||||
Trace trace = null;
|
||||
try {
|
||||
trace = ProgramEmulationUtils.launchEmulationTrace(program, address, this);
|
||||
trace.flushEvents();
|
||||
|
||||
TraceMappingWaiter waiter = new TraceMappingWaiter(trace);
|
||||
staticMappings.addChangeListener(waiter);
|
||||
traceManager.openTrace(trace);
|
||||
traceManager.activateTrace(trace);
|
||||
Swing.allowSwingToProcessEvents();
|
||||
waiter.softWait();
|
||||
}
|
||||
finally {
|
||||
if (trace != null) {
|
||||
|
|
|
@ -45,7 +45,8 @@ import ghidra.trace.model.target.iface.TraceObjectInterface;
|
|||
import ghidra.trace.model.target.path.*;
|
||||
import ghidra.trace.model.target.schema.*;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.thread.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.thread.TraceThreadManager;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
@ -290,19 +291,13 @@ public class ProgramEmulationUtils {
|
|||
}
|
||||
|
||||
public static PathPattern computePatternRegion(Trace trace) {
|
||||
TraceObjectSchema root = trace.getObjectManager().getRootSchema();
|
||||
if (root == null) {
|
||||
return PathFilter.parse("Memory[]");
|
||||
}
|
||||
return computePattern(root, trace, TraceObjectMemoryRegion.class);
|
||||
TraceObjectSchema root = trace.getObjectManager().requireRootSchema();
|
||||
return computePattern(root, trace, TraceMemoryRegion.class);
|
||||
}
|
||||
|
||||
public static PathPattern computePatternThread(Trace trace) {
|
||||
TraceObjectSchema root = trace.getObjectManager().getRootSchema();
|
||||
if (root == null) {
|
||||
return PathFilter.parse("Threads[]");
|
||||
}
|
||||
return computePattern(root, trace, TraceObjectThread.class);
|
||||
TraceObjectSchema root = trace.getObjectManager().requireRootSchema();
|
||||
return computePattern(root, trace, TraceThread.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,18 +342,16 @@ public class ProgramEmulationUtils {
|
|||
public static void initializeRegisters(Trace trace, long snap, TraceThread thread,
|
||||
Program program, Address tracePc, Address programPc, AddressRange stack) {
|
||||
TraceMemoryManager memory = trace.getMemoryManager();
|
||||
if (thread instanceof TraceObjectThread ot) {
|
||||
TraceObject object = ot.getObject();
|
||||
PathFilter regsFilter = object.getRoot()
|
||||
.getSchema()
|
||||
.searchForRegisterContainer(0, object.getCanonicalPath());
|
||||
if (regsFilter.isNone()) {
|
||||
throw new IllegalArgumentException("Cannot create register container");
|
||||
}
|
||||
for (PathPattern regsPattern : regsFilter.getPatterns()) {
|
||||
trace.getObjectManager().createObject(regsPattern.getSingletonPath());
|
||||
break;
|
||||
}
|
||||
TraceObject object = thread.getObject();
|
||||
PathFilter regsFilter = object.getRoot()
|
||||
.getSchema()
|
||||
.searchForRegisterContainer(0, object.getCanonicalPath());
|
||||
if (regsFilter.isNone()) {
|
||||
throw new IllegalArgumentException("Cannot create register container");
|
||||
}
|
||||
for (PathPattern regsPattern : regsFilter.getPatterns()) {
|
||||
trace.getObjectManager().createObject(regsPattern.getSingletonPath());
|
||||
break;
|
||||
}
|
||||
TraceMemorySpace regSpace = memory.getMemoryRegisterSpace(thread, true);
|
||||
if (program != null) {
|
||||
|
@ -606,7 +599,12 @@ public class ProgramEmulationUtils {
|
|||
throw new EmulatorOutOfMemoryException();
|
||||
}
|
||||
|
||||
protected static void createObjects(Trace trace) {
|
||||
/**
|
||||
* Initialize a given emulation trace with some required/expected objects
|
||||
*
|
||||
* @param trace the trace
|
||||
*/
|
||||
public static void createObjects(Trace trace) {
|
||||
TraceObjectManager om = trace.getObjectManager();
|
||||
om.createRootObject(EMU_SESSION_SCHEMA);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import ghidra.program.model.lang.RegisterValue;
|
|||
import ghidra.program.util.MarkerLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceSpan;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointCommon;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
|
@ -321,12 +321,12 @@ public abstract class AbstractTarget implements Target {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void deleteBreakpoint(TraceBreakpoint breakpoint) {
|
||||
public void deleteBreakpoint(TraceBreakpointCommon breakpoint) {
|
||||
runSync("delete breakpoint", () -> deleteBreakpointAsync(breakpoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled) {
|
||||
public void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled) {
|
||||
String msg = enabled ? "enable breakpoint" : "disable breakpoint";
|
||||
runSync(msg, () -> toggleBreakpointAsync(breakpoint, enabled));
|
||||
}
|
||||
|
|
|
@ -70,24 +70,16 @@ public class DebuggerListingPluginScreenShots extends GhidraScreenShotGenerator
|
|||
TraceSymbolManager symbolManager = tb.trace.getSymbolManager();
|
||||
TraceNamespaceSymbol global = symbolManager.getGlobalNamespace();
|
||||
|
||||
TraceSymbol mainLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400000),
|
||||
"main", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol mainLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400000), "main", global, SourceType.USER_DEFINED);
|
||||
@SuppressWarnings("unused")
|
||||
TraceSymbol cloneLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400060),
|
||||
"clone", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol childLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400032),
|
||||
"child", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol cloneLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol childLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400032), "child", global, SourceType.USER_DEFINED);
|
||||
@SuppressWarnings("unused")
|
||||
TraceSymbol exitLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400061),
|
||||
"exit", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol exitLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400061), "exit", global, SourceType.USER_DEFINED);
|
||||
|
||||
Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView());
|
||||
|
||||
|
|
|
@ -72,24 +72,16 @@ public class DebuggerMemoryBytesPluginScreenShots extends GhidraScreenShotGenera
|
|||
TraceSymbolManager symbolManager = tb.trace.getSymbolManager();
|
||||
TraceNamespaceSymbol global = symbolManager.getGlobalNamespace();
|
||||
|
||||
TraceSymbol mainLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400000),
|
||||
"main", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol mainLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400000), "main", global, SourceType.USER_DEFINED);
|
||||
@SuppressWarnings("unused")
|
||||
TraceSymbol cloneLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400060),
|
||||
"clone", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol childLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400034),
|
||||
"child", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol cloneLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol childLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400034), "child", global, SourceType.USER_DEFINED);
|
||||
@SuppressWarnings("unused")
|
||||
TraceSymbol exitLabel = symbolManager
|
||||
.labels()
|
||||
.create(snap, null, tb.addr(0x00400061),
|
||||
"exit", global, SourceType.USER_DEFINED);
|
||||
TraceSymbol exitLabel = symbolManager.labels()
|
||||
.create(snap, tb.addr(0x00400061), "exit", global, SourceType.USER_DEFINED);
|
||||
|
||||
Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView());
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import ghidra.trace.database.target.DBTraceObjectValue;
|
|||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.iface.TraceObjectEventScope;
|
||||
import ghidra.trace.model.target.iface.TraceEventScope;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
|
@ -180,7 +180,7 @@ public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
|
|||
proc.child("Modules");
|
||||
}
|
||||
}
|
||||
root.value(TraceObjectEventScope.KEY_EVENT_THREAD, l.thread);
|
||||
root.value(TraceEventScope.KEY_EVENT_THREAD, l.thread);
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
|
|
@ -29,7 +29,7 @@ import ghidra.test.ToyProgramBuilder;
|
|||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class DebuggerPcodeStepperPluginScreenShots extends GhidraScreenShotGener
|
|||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
|
||||
TraceObjectThread thread = (TraceObjectThread) tb.getOrAddThread("Threads[1]", snap0);
|
||||
TraceThread thread = tb.getOrAddThread("Threads[1]", snap0);
|
||||
tb.trace.getObjectManager()
|
||||
.createObject(thread.getObject().getCanonicalPath().key("Registers"));
|
||||
|
||||
|
|
|
@ -22,10 +22,6 @@ import db.Transaction;
|
|||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||
import ghidra.trace.database.target.DBTraceObjectManagerTest;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
|
||||
public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator {
|
||||
|
@ -41,11 +37,9 @@ public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator
|
|||
|
||||
@Test
|
||||
public void testCaptureDebuggerSelectPlatformOfferDialog() throws Throwable {
|
||||
SchemaContext ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX);
|
||||
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("echo", "DATA:BE:64:default")) {
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.trace.getObjectManager()
|
||||
.createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||
tb.createRootObject();
|
||||
}
|
||||
traceManager.openTrace(tb.trace);
|
||||
traceManager.activateTrace(tb.trace);
|
||||
|
|
|
@ -45,7 +45,7 @@ import ghidra.trace.model.DefaultTraceLocation;
|
|||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import help.screenshot.GhidraScreenShotGenerator;
|
||||
|
||||
|
@ -103,14 +103,10 @@ public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator
|
|||
sm.getSnapshot(13, true);
|
||||
|
||||
DBTraceThreadManager tm = tb.trace.getThreadManager();
|
||||
TraceObjectThread t1 =
|
||||
(TraceObjectThread) tm.addThread("Threads[1]", "main", Lifespan.nowOn(0));
|
||||
TraceObjectThread t2 =
|
||||
(TraceObjectThread) tm.addThread("Threads[2]", "server", Lifespan.nowOn(2));
|
||||
TraceObjectThread t3 =
|
||||
(TraceObjectThread) tm.addThread("Threads[3]", "handler 1", Lifespan.span(5, 10));
|
||||
TraceObjectThread t4 =
|
||||
(TraceObjectThread) tm.addThread("Threads[4]", "handler 2", Lifespan.span(8, 13));
|
||||
TraceThread t1 = tm.addThread("Threads[1]", "main", Lifespan.nowOn(0));
|
||||
TraceThread t2 = tm.addThread("Threads[2]", "server", Lifespan.nowOn(2));
|
||||
TraceThread t3 = tm.addThread("Threads[3]", "handler 1", Lifespan.span(5, 10));
|
||||
TraceThread t4 = tm.addThread("Threads[4]", "handler 2", Lifespan.span(8, 13));
|
||||
|
||||
t1.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED");
|
||||
t2.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED");
|
||||
|
|
|
@ -62,7 +62,7 @@ public class DebuggerWatchesPluginScreenShots extends GhidraScreenShotGenerator
|
|||
|
||||
tb.trace.getSymbolManager()
|
||||
.labels()
|
||||
.create(snap1, null, tb.addr(0x7fff0004), "fiveUp",
|
||||
.create(snap1, tb.addr(0x7fff0004), "fiveUp",
|
||||
tb.trace.getSymbolManager().getGlobalNamespace(), SourceType.USER_DEFINED);
|
||||
|
||||
thread = tb.getOrAddThread("[1]", snap0);
|
||||
|
|
|
@ -48,6 +48,7 @@ import ghidra.program.model.lang.*;
|
|||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder;
|
||||
import ghidra.trace.database.listing.DBTraceInstruction;
|
||||
import ghidra.trace.database.listing.DBTraceInstructionsMemoryView;
|
||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||
|
@ -59,16 +60,16 @@ import ghidra.trace.model.Lifespan;
|
|||
import ghidra.trace.model.guest.TraceGuestPlatform;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.stack.*;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.iface.TraceObjectEnvironment;
|
||||
import ghidra.trace.model.target.iface.TraceEnvironment;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -162,12 +163,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
sel, null);
|
||||
}
|
||||
|
||||
protected TraceObjectThread createPolyglotTrace(String arch, long offset,
|
||||
protected TraceThread createPolyglotTrace(String arch, long offset,
|
||||
Supplier<ByteBuffer> byteSupplier) throws Exception {
|
||||
return createPolyglotTrace(arch, offset, byteSupplier, true);
|
||||
}
|
||||
|
||||
protected TraceObjectThread createPolyglotTrace(String arch, long offset,
|
||||
protected TraceThread createPolyglotTrace(String arch, long offset,
|
||||
Supplier<ByteBuffer> byteSupplier, boolean pcInStack) throws Exception {
|
||||
createAndOpenTrace("DATA:BE:64:default");
|
||||
|
||||
|
@ -179,13 +180,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertEquals(ctx.getSchema(new SchemaName("Environment")), env.getSchema());
|
||||
Lifespan zeroOn = Lifespan.nowOn(0);
|
||||
env.insert(zeroOn, ConflictResolution.DENY);
|
||||
env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_DEBUGGER, "test");
|
||||
env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_ARCH, arch);
|
||||
env.setAttribute(zeroOn, TraceEnvironment.KEY_DEBUGGER, "test");
|
||||
env.setAttribute(zeroOn, TraceEnvironment.KEY_ARCH, arch);
|
||||
|
||||
DBTraceObject objBinText =
|
||||
objects.createObject(KeyPath.parse("Targets[0].Memory[bin:.text]"));
|
||||
TraceObjectMemoryRegion binText =
|
||||
objBinText.queryInterface(TraceObjectMemoryRegion.class);
|
||||
TraceMemoryRegion binText = objBinText.queryInterface(TraceMemoryRegion.class);
|
||||
binText.addFlags(zeroOn, Set.of(TraceMemoryFlag.EXECUTE));
|
||||
binText.setRange(zeroOn, tb.range(offset, offset + 0xffff));
|
||||
// TODO: Why doesn't setRange work after insert?
|
||||
|
@ -196,16 +196,16 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
DBTraceObject objFrame = objects
|
||||
.createObject(KeyPath.parse("Targets[0].Threads[0].Stack[0]"));
|
||||
objFrame.insert(zeroOn, ConflictResolution.DENY);
|
||||
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
||||
TraceStackFrame frame = objFrame.queryInterface(TraceStackFrame.class);
|
||||
frame.setProgramCounter(zeroOn, tb.addr(offset));
|
||||
}
|
||||
else {
|
||||
objects.createObject(
|
||||
KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
||||
.insert(zeroOn, ConflictResolution.DENY);
|
||||
TraceObjectThread thread = objects
|
||||
.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
|
||||
.queryInterface(TraceObjectThread.class);
|
||||
TraceThread thread =
|
||||
objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
|
||||
.queryInterface(TraceThread.class);
|
||||
traceManager.activateThread(thread);
|
||||
DBTraceMemorySpace regs =
|
||||
Objects.requireNonNull(memory.getMemoryRegisterSpace(thread, true));
|
||||
|
@ -218,14 +218,14 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
ByteBuffer bytes = byteSupplier.get();
|
||||
assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes));
|
||||
}
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
|
||||
.queryInterface(TraceObjectThread.class);
|
||||
.queryInterface(TraceThread.class);
|
||||
traceManager.activateThread(thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
protected void setLegacyProgramCounterInStack(long offset, TraceThread thread, long snap) {
|
||||
protected void setProgramCounterInStack(long offset, TraceThread thread, long snap) {
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
DBTraceStackManager manager = tb.trace.getStackManager();
|
||||
TraceStack stack = manager.getStack(thread, snap, true);
|
||||
|
@ -234,7 +234,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
}
|
||||
}
|
||||
|
||||
protected void setLegacyProgramCounterInRegs(long offset, TraceThread thread, long snap) {
|
||||
protected void setProgramCounterInRegs(long offset, TraceThread thread, long snap) {
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
|
||||
|
@ -243,11 +243,19 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
}
|
||||
}
|
||||
|
||||
protected void createLegacyTrace(String langID, long offset, Supplier<ByteBuffer> byteSupplier)
|
||||
protected SchemaContext buildContext() {
|
||||
return new ToySchemaBuilder()
|
||||
.noRegisterGroups()
|
||||
.useRegistersPerFrame()
|
||||
.build();
|
||||
}
|
||||
|
||||
protected void createTrace(String langID, long offset, Supplier<ByteBuffer> byteSupplier)
|
||||
throws Throwable {
|
||||
createAndOpenTrace(langID);
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject(buildContext(), "Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion("Memory[bin:.text]", 0, tb.range(offset, offset + 0xffff),
|
||||
Set.of(TraceMemoryFlag.EXECUTE, TraceMemoryFlag.READ));
|
||||
|
@ -275,27 +283,27 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
@Test
|
||||
public void testAutoDisasembleReDisasembleX8664Offcut() throws Throwable {
|
||||
enableAutoDisassembly();
|
||||
createLegacyTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0));
|
||||
createTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0));
|
||||
|
||||
TraceThread thread;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
thread = tb.getOrAddThread("Threads[1]", 0);
|
||||
}
|
||||
|
||||
setLegacyProgramCounterInStack(0x00400000, thread, 0);
|
||||
setProgramCounterInStack(0x00400000, thread, 0);
|
||||
|
||||
waitForPass(() -> {
|
||||
DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions();
|
||||
assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000)));
|
||||
/**
|
||||
* Depending on preference for branch or fall-through, the disassembler may or may not
|
||||
* proceed to the following instructions. I don't really care, since the test is that the
|
||||
* JMP gets deleted after the update to PC.
|
||||
* proceed to the following instructions. I don't really care, since the test is that
|
||||
* the JMP gets deleted after the update to PC.
|
||||
*/
|
||||
});
|
||||
|
||||
// The jump will advance one byte. Just simulate that by updating the stack and/or regs
|
||||
setLegacyProgramCounterInStack(0x00400001, thread, 1);
|
||||
setProgramCounterInStack(0x00400001, thread, 1);
|
||||
traceManager.activateSnap(1);
|
||||
|
||||
waitForPass(() -> {
|
||||
|
@ -310,22 +318,23 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
public void testAutoDisassembleReDisassembleX8664OffcutByEmulation() throws Throwable {
|
||||
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
||||
enableAutoDisassembly();
|
||||
createLegacyTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0));
|
||||
createTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0));
|
||||
|
||||
TraceThread thread;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
thread = tb.getOrAddThread("Thread 1", 0);
|
||||
thread = tb.getOrAddThread("Threads[1]", 0);
|
||||
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
|
||||
}
|
||||
|
||||
setLegacyProgramCounterInRegs(0x00400000, thread, 0);
|
||||
setProgramCounterInRegs(0x00400000, thread, 0);
|
||||
|
||||
waitForPass(() -> {
|
||||
DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions();
|
||||
assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000)));
|
||||
/**
|
||||
* Depending on preference for branch or fall-through, the disassembler may or may not
|
||||
* proceed to the following instructions. I don't really care, since the test is that the
|
||||
* JMP gets deleted after the update to PC.
|
||||
* proceed to the following instructions. I don't really care, since the test is that
|
||||
* the JMP gets deleted after the update to PC.
|
||||
*/
|
||||
});
|
||||
|
||||
|
@ -374,8 +383,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000)));
|
||||
/**
|
||||
* Depending on preference for branch or fall-through, the disassembler may or may not
|
||||
* proceed to the following instructions. I don't really care, since the test is that the
|
||||
* JMP gets deleted after the update to PC.
|
||||
* proceed to the following instructions. I don't really care, since the test is that
|
||||
* the JMP gets deleted after the update to PC.
|
||||
*/
|
||||
});
|
||||
|
||||
|
@ -411,12 +420,13 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testCurrentDisassembleActionHostArm() throws Throwable {
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
|
||||
// Fabricate the cpsr so that ARM is used. Otherwise, it will assume Cortex-M, so THUMB
|
||||
TraceThread thread;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
thread = tb.getOrAddThread("Threads[0]", 0);
|
||||
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
|
||||
DBTraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO));
|
||||
|
@ -442,12 +452,13 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testCurrentDisassembleActionHostThumb() throws Throwable {
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x70, 0x47));
|
||||
createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x70, 0x47));
|
||||
|
||||
// Fabricate the cpsr so that THUMB is used, even though we could omit as in Cortex-M
|
||||
TraceThread thread;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
thread = tb.getOrAddThread("Threads[0]", 0);
|
||||
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
|
||||
DBTraceMemorySpace regs =
|
||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0,
|
||||
|
@ -474,7 +485,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testCurrentDisassembleActionGuestArm() throws Throwable {
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
traceManager.activateThread(thread);
|
||||
waitForSwing();
|
||||
|
@ -510,7 +521,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testCurrentDisassembleActionGuestThumb() throws Throwable {
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47));
|
||||
traceManager.activateThread(thread);
|
||||
waitForSwing();
|
||||
|
@ -557,7 +568,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testFixedDisassembleActionsHostArm() throws Throwable {
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
Address start = tb.addr(0x00400000);
|
||||
|
||||
// Ensure the mapper is added to the trace
|
||||
|
@ -573,7 +584,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testFixedDisassembleActionsGuestArm() throws Throwable {
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
|
||||
Address start = tb.addr(0x00400000);
|
||||
|
||||
|
@ -590,7 +601,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
@Test
|
||||
public void testFixedDisassembleActionsGuestThumb() throws Throwable {
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47));
|
||||
Address start = tb.addr(0x00400000);
|
||||
|
||||
|
@ -610,7 +621,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Assemble actions will think read-only otherwise
|
||||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00));
|
||||
createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00));
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
||||
|
@ -638,7 +649,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
// Don't cheat here and choose v8T!
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00));
|
||||
createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00));
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
||||
|
@ -669,7 +680,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Assemble actions will think read-only otherwise
|
||||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00));
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
@ -699,7 +710,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Assemble actions will think read-only otherwise
|
||||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
TraceObjectThread thread =
|
||||
TraceThread thread =
|
||||
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00));
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
@ -749,7 +760,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Assemble actions will think read-only otherwise
|
||||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf());
|
||||
createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf());
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
||||
|
@ -768,7 +779,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Assemble actions will think read-only otherwise
|
||||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
TraceObjectThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf());
|
||||
TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf());
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
||||
|
@ -787,7 +798,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Assemble actions will think read-only otherwise
|
||||
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||
|
||||
TraceObjectThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf());
|
||||
TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf());
|
||||
Address start = tb.addr(0x00400000);
|
||||
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
|||
import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyPlan.AllCopiers;
|
||||
import ghidra.app.util.viewer.listingpanel.PropertyBasedBackgroundColorModel;
|
||||
import ghidra.program.database.IntRangeMap;
|
||||
import ghidra.program.disassemble.Disassembler;
|
||||
import ghidra.program.disassemble.DisassemblerMessageListener;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
|
@ -75,9 +73,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
byte src[] = new byte[0x10000];
|
||||
r.nextBytes(src);
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.wrap(src));
|
||||
}
|
||||
|
||||
|
@ -107,9 +106,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.STATE.isAvailable(view, program));
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.allocate(4096));
|
||||
memory.setState(0, tb.addr(0x55551000), TraceMemoryState.ERROR);
|
||||
}
|
||||
|
@ -182,10 +182,14 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
AddressRange trng = tb.range(0x55550000, 0x5555ffff);
|
||||
Assembler asm = Assemblers.getAssembler(view);
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
InstructionIterator iit =
|
||||
asm.assemble(tb.addr(0x55550000), "imm r0, #123", "imm r1, #234", "add r0, r1");
|
||||
memory.createRegion("Memory[.text]", 0, trng,
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
InstructionIterator iit = asm.assemble(tb.addr(0x55550000),
|
||||
"imm r0, #123",
|
||||
"imm r1, #234",
|
||||
"add r0, r1");
|
||||
assertTrue(iit.hasNext());
|
||||
}
|
||||
|
||||
|
@ -228,10 +232,14 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
AddressRange trng = tb.range(0x55550000, 0x5555ffff);
|
||||
Assembler asm = Assemblers.getAssembler(view);
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
InstructionIterator iit =
|
||||
asm.assemble(tb.addr(0x55550000), "MOV RAX, 1234", "MOV RCX, 2345", "ADD RAX, RCX");
|
||||
memory.createRegion("Memory[.text]", 0, trng,
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
InstructionIterator iit = asm.assemble(tb.addr(0x55550000),
|
||||
"MOV RAX, 1234",
|
||||
"MOV RCX, 2345",
|
||||
"ADD RAX, RCX");
|
||||
assertTrue(iit.hasNext());
|
||||
}
|
||||
|
||||
|
@ -272,7 +280,7 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.INSTRUCTIONS.isAvailable(view, program));
|
||||
|
||||
AddressRange trng = tb.range(0x55550000, 0x5555ffff);
|
||||
// Assembler asm = Assemblers.getAssembler(view);
|
||||
Assembler asm = Assemblers.getAssembler(view);
|
||||
|
||||
Register contextReg = tb.language.getContextBaseRegister();
|
||||
Register longMode = tb.language.getRegister("longMode");
|
||||
|
@ -281,26 +289,17 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
rv = rv.assign(longMode, BigInteger.ZERO);
|
||||
Instruction checkCtx;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, trng,
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.trace.getRegisterContextManager().setValue(tb.language, rv, Lifespan.nowOn(0), trng);
|
||||
|
||||
// TODO: Once GP-1426 is resolved, use the assembler
|
||||
/*
|
||||
InstructionIterator iit = asm.assemble(tb.addr(0x55550000),
|
||||
"MOV EAX, 1234",
|
||||
"MOV ECX, 2345",
|
||||
"ADD EAX, ECX");
|
||||
checkCtx = iit.next();
|
||||
*/
|
||||
memory.putBytes(0, tb.addr(0x55550000), tb.buf(0xb8, 0xd2, 0x04, 0x00, 0x00, // MOV EAX,1234
|
||||
0xb9, 0x29, 0x09, 0x00, 0x00, // MOV ECX,2345
|
||||
0x01, 0xc8 // ADD EAX,ECX
|
||||
));
|
||||
Disassembler
|
||||
.getDisassembler(view, TaskMonitor.DUMMY, DisassemblerMessageListener.IGNORE)
|
||||
.disassemble(tb.addr(0x55550000), tb.set(tb.range(0x55550000, 0x5555000b)));
|
||||
checkCtx = tb.trace.getCodeManager().instructions().getAt(0, tb.addr(0x55550000));
|
||||
}
|
||||
// Sanity pre-check
|
||||
RegisterValue insCtx = checkCtx.getRegisterValue(contextReg);
|
||||
|
@ -352,8 +351,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
AddressRange trng = tb.range(0x55560000, 0x5556ffff);
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".data", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
memory.createRegion("Memory[.data]", 0, trng,
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12));
|
||||
tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34));
|
||||
tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType,
|
||||
|
@ -412,8 +413,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
|
||||
AddressRange trng = tb.range(0x55560000, 0x5556ffff);
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".data", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
memory.createRegion("Memory[.data]", 0, trng,
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12));
|
||||
tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34));
|
||||
tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType,
|
||||
|
@ -479,21 +482,20 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.LABELS.isAvailable(view, program));
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
DBTraceNamespaceSymbol global = tb.trace.getSymbolManager().getGlobalNamespace();
|
||||
|
||||
DBTraceLabelSymbolView labels = tb.trace.getSymbolManager().labels();
|
||||
labels.create(0, null, tb.addr(0x55550000), "test_label1", global, SourceType.IMPORTED);
|
||||
labels.create(0, null, tb.addr(0x55550005), "test_label2", global,
|
||||
SourceType.USER_DEFINED);
|
||||
labels.create(0, tb.addr(0x55550000), "test_label1", global, SourceType.IMPORTED);
|
||||
labels.create(0, tb.addr(0x55550005), "test_label2", global, SourceType.USER_DEFINED);
|
||||
DBTraceNamespaceSymbolView namespaces = tb.trace.getSymbolManager().namespaces();
|
||||
DBTraceNamespaceSymbol testNs = namespaces.add("test_ns", global, SourceType.ANALYSIS);
|
||||
DBTraceNamespaceSymbol testNsChild =
|
||||
namespaces.add("test_ns_child", testNs, SourceType.USER_DEFINED);
|
||||
labels.create(0, null, tb.addr(0x55550800), "test_label3", testNsChild,
|
||||
SourceType.ANALYSIS);
|
||||
labels.create(0, tb.addr(0x55550800), "test_label3", testNsChild, SourceType.ANALYSIS);
|
||||
}
|
||||
|
||||
Address paddr = tb.addr(stSpace, 0x00400000);
|
||||
|
@ -550,14 +552,15 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.BREAKPOINTS.isAvailable(view, program));
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
DBTraceBreakpointManager breakpoints = tb.trace.getBreakpointManager();
|
||||
breakpoints.placeBreakpoint("[1]", 0, tb.addr(0x55550123), List.of(),
|
||||
breakpoints.placeBreakpoint("Breakpoints[1]", 0, tb.addr(0x55550123), List.of(),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "Test-1");
|
||||
breakpoints.placeBreakpoint("[2]", 0, tb.addr(0x55550321), List.of(),
|
||||
breakpoints.placeBreakpoint("Breakpoints[2]", 0, tb.addr(0x55550321), List.of(),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), false, "Test-2");
|
||||
}
|
||||
|
||||
|
@ -603,9 +606,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.BOOKMARKS.isAvailable(view, program));
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
BookmarkManager bookmarks = view.getBookmarkManager();
|
||||
bookmarks.defineType("TestType", DebuggerResources.ICON_DEBUGGER, Palette.BLUE, 1);
|
||||
|
@ -651,11 +655,12 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.REFERENCES.isAvailable(view, program));
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion(".data", 0, tb.range(0x55560000, 0x5556ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.WRITE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.data]", 0, tb.range(0x55560000, 0x5556ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
|
||||
ReferenceManager references = view.getReferenceManager();
|
||||
references.addMemoryReference(tb.addr(0x55550123), tb.addr(0x55550321),
|
||||
|
@ -702,9 +707,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
assertTrue(AllCopiers.COMMENTS.isAvailable(view, program));
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
Listing listing = view.getListing();
|
||||
listing.setComment(tb.addr(0x55550123), CommentType.EOL, "Test EOL Comment");
|
||||
|
|
|
@ -129,8 +129,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge
|
|||
public void testColorsDiffBytes() throws Throwable {
|
||||
createAndOpenTrace();
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text
|
||||
|
@ -164,8 +165,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge
|
|||
public void testActionPrevDiff() throws Throwable {
|
||||
createAndOpenTrace();
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text
|
||||
|
@ -201,8 +203,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge
|
|||
public void testActionNextDiff() throws Throwable {
|
||||
createAndOpenTrace();
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
DBTraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text
|
||||
|
|
|
@ -45,7 +45,6 @@ import ghidra.program.util.ProgramSelection;
|
|||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.modules.TraceStaticMapping;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
|
@ -80,10 +79,10 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
DebuggerRegionsProvider provider;
|
||||
|
||||
TraceObjectMemoryRegion regionExeText;
|
||||
TraceObjectMemoryRegion regionExeData;
|
||||
TraceObjectMemoryRegion regionLibText;
|
||||
TraceObjectMemoryRegion regionLibData;
|
||||
TraceMemoryRegion regionExeText;
|
||||
TraceMemoryRegion regionExeData;
|
||||
TraceMemoryRegion regionLibText;
|
||||
TraceMemoryRegion regionLibData;
|
||||
|
||||
MemoryBlock blockExeText;
|
||||
MemoryBlock blockExeData;
|
||||
|
@ -109,21 +108,21 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
}
|
||||
}
|
||||
|
||||
protected TraceObjectMemoryRegion addRegion(String name, long loaded, AddressRange range) {
|
||||
protected TraceMemoryRegion addRegion(String name, long loaded, AddressRange range) {
|
||||
boolean isData = name.endsWith(".data");
|
||||
TraceObjectManager om = tb.trace.getObjectManager();
|
||||
KeyPath memPath = KeyPath.parse("Memory");
|
||||
Lifespan span = Lifespan.nowOn(loaded);
|
||||
TraceObjectMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name))
|
||||
TraceMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name))
|
||||
.insert(span, ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectMemoryRegion.class));
|
||||
.queryInterface(TraceMemoryRegion.class));
|
||||
TraceObject obj = region.getObject();
|
||||
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_DISPLAY, name);
|
||||
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE, range);
|
||||
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true);
|
||||
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE, isData);
|
||||
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE, !isData);
|
||||
obj.setAttribute(span, TraceMemoryRegion.KEY_DISPLAY, name);
|
||||
obj.setAttribute(span, TraceMemoryRegion.KEY_RANGE, range);
|
||||
obj.setAttribute(span, TraceMemoryRegion.KEY_READABLE, true);
|
||||
obj.setAttribute(span, TraceMemoryRegion.KEY_WRITABLE, isData);
|
||||
obj.setAttribute(span, TraceMemoryRegion.KEY_EXECUTABLE, !isData);
|
||||
return region;
|
||||
}
|
||||
|
||||
|
@ -218,7 +217,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
public void testAddThenActivateTracePopulates() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
@ -240,7 +239,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
waitForPass(() -> assertTableSize(0));
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
@ -257,7 +256,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
public void testRemoveRegionRemovesFromTable() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
@ -284,7 +283,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
public void testUndoRedo() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
@ -320,7 +319,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
createAndOpenTrace();
|
||||
traceManager.activateTrace(tb.trace);
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
waitForDomainObject(tb.trace);
|
||||
|
@ -346,7 +345,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
@ -465,7 +464,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
@ -514,7 +513,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectMemoryRegion region;
|
||||
TraceMemoryRegion region;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
|
||||
}
|
||||
|
|
|
@ -43,13 +43,12 @@ import ghidra.trace.database.ToyDBTraceBuilder.EventSuspension;
|
|||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.target.*;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.iface.TraceObjectEventScope;
|
||||
import ghidra.trace.model.target.iface.TraceEventScope;
|
||||
import ghidra.trace.model.target.iface.TraceObjectInterface;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
||||
public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||
|
@ -164,7 +163,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
prevThread.setAttribute(Lifespan.nowOn(i), "_next", thread);
|
||||
}
|
||||
objects.getRootObject()
|
||||
.setAttribute(Lifespan.nowOn(i), TraceObjectEventScope.KEY_EVENT_THREAD,
|
||||
.setAttribute(Lifespan.nowOn(i), TraceEventScope.KEY_EVENT_THREAD,
|
||||
thread);
|
||||
return thread;
|
||||
}
|
||||
|
@ -700,6 +699,8 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
* sufficient events to overload the queue, the event support with clear them and just issue an
|
||||
* OBJ_RESTORED event instead. This test ensures we update attributes in the tree when that
|
||||
* happens.
|
||||
*
|
||||
* @throws Throwable because
|
||||
*/
|
||||
@Test
|
||||
public void testTreeTracksChangeAttributeWithEventsSuspended() throws Throwable {
|
||||
|
@ -998,7 +999,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||
TraceObject threadObj0 =
|
||||
objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[0]"));
|
||||
TraceThread thread0 = threadObj0.queryInterface(TraceObjectThread.class);
|
||||
TraceThread thread0 = threadObj0.queryInterface(TraceThread.class);
|
||||
createStack(threadObj0);
|
||||
return thread0;
|
||||
}
|
||||
|
|
|
@ -51,12 +51,10 @@ import ghidra.framework.main.DataTreeDialog;
|
|||
import ghidra.plugin.importer.ImporterPlugin;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.trace.database.module.TraceObjectSection;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.modules.TraceObjectModule;
|
||||
import ghidra.trace.model.modules.TraceStaticMapping;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.modules.*;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.TraceObjectManager;
|
||||
|
@ -109,13 +107,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
DebuggerModulesProvider provider;
|
||||
|
||||
protected TraceObjectModule modExe;
|
||||
protected TraceObjectSection secExeText;
|
||||
protected TraceObjectSection secExeData;
|
||||
protected TraceModule modExe;
|
||||
protected TraceSection secExeText;
|
||||
protected TraceSection secExeData;
|
||||
|
||||
protected TraceObjectModule modLib;
|
||||
protected TraceObjectSection secLibText;
|
||||
protected TraceObjectSection secLibData;
|
||||
protected TraceModule modLib;
|
||||
protected TraceSection secLibText;
|
||||
protected TraceSection secLibData;
|
||||
|
||||
protected SchemaContext ctx;
|
||||
|
||||
|
@ -145,13 +143,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
try (Transaction tx = tb.startTransaction()) {
|
||||
TraceObject root = om.getRootObject();
|
||||
for (TraceObject module : (Iterable<TraceObject>) () -> root
|
||||
.findSuccessorsInterface(Lifespan.at(0), TraceObjectModule.class, true)
|
||||
.findSuccessorsInterface(Lifespan.at(0), TraceModule.class, true)
|
||||
.map(p -> p.getDestination(root))
|
||||
.iterator()) {
|
||||
String moduleName = module.getCanonicalPath().index();
|
||||
Lifespan span = module.getLife().bound();
|
||||
for (TraceObject section : (Iterable<TraceObject>) () -> module
|
||||
.findSuccessorsInterface(Lifespan.at(0), TraceObjectSection.class,
|
||||
.findSuccessorsInterface(Lifespan.at(0), TraceSection.class,
|
||||
true)
|
||||
.map(p -> p.getDestination(root))
|
||||
.iterator()) {
|
||||
|
@ -161,42 +159,42 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
.getSingletonPath())
|
||||
.insert(span, ConflictResolution.TRUNCATE)
|
||||
.getDestination(root);
|
||||
region.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE,
|
||||
section.getAttribute(0, TraceObjectSection.KEY_RANGE).getValue());
|
||||
region.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true);
|
||||
region.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE,
|
||||
region.setAttribute(span, TraceMemoryRegion.KEY_RANGE,
|
||||
section.getAttribute(0, TraceSection.KEY_RANGE).getValue());
|
||||
region.setAttribute(span, TraceMemoryRegion.KEY_READABLE, true);
|
||||
region.setAttribute(span, TraceMemoryRegion.KEY_WRITABLE,
|
||||
".data".equals(sectionName));
|
||||
region.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE,
|
||||
region.setAttribute(span, TraceMemoryRegion.KEY_EXECUTABLE,
|
||||
".text".equals(sectionName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected TraceObjectModule addModule(String name, AddressRange range, Lifespan span) {
|
||||
protected TraceModule addModule(String name, AddressRange range, Lifespan span) {
|
||||
PathPattern modulePattern = PathFilter.parse("Processes[1].Modules[]");
|
||||
TraceObjectManager om = tb.trace.getObjectManager();
|
||||
TraceObjectModule module = Objects.requireNonNull(
|
||||
TraceModule module = Objects.requireNonNull(
|
||||
om.createObject(modulePattern.applyKeys(name).getSingletonPath())
|
||||
.insert(span, ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectModule.class));
|
||||
module.getObject().setAttribute(span, TraceObjectModule.KEY_MODULE_NAME, name);
|
||||
module.getObject().setAttribute(span, TraceObjectModule.KEY_RANGE, range);
|
||||
.queryInterface(TraceModule.class));
|
||||
module.getObject().setAttribute(span, TraceModule.KEY_MODULE_NAME, name);
|
||||
module.getObject().setAttribute(span, TraceModule.KEY_RANGE, range);
|
||||
return module;
|
||||
}
|
||||
|
||||
protected TraceObjectSection addSection(TraceObjectModule module, String name,
|
||||
protected TraceSection addSection(TraceModule module, String name,
|
||||
AddressRange range) {
|
||||
TraceObjectManager om = tb.trace.getObjectManager();
|
||||
Lifespan span = module.getObject().getLife().bound();
|
||||
TraceObjectSection section = Objects.requireNonNull(om
|
||||
TraceSection section = Objects.requireNonNull(om
|
||||
.createObject(
|
||||
module.getObject().getCanonicalPath().key("Sections").index(name))
|
||||
.insert(span, ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectSection.class));
|
||||
section.getObject().setAttribute(span, TraceObjectSection.KEY_RANGE, range);
|
||||
.queryInterface(TraceSection.class));
|
||||
section.getObject().setAttribute(span, TraceSection.KEY_RANGE, range);
|
||||
return section;
|
||||
}
|
||||
|
||||
|
@ -719,7 +717,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
for (ValueRow row : visibleSections()) {
|
||||
assertEquals(modExe.getObject(), row.getValue()
|
||||
.getChild()
|
||||
.findCanonicalAncestorsInterface(TraceObjectModule.class)
|
||||
.findCanonicalAncestorsInterface(TraceModule.class)
|
||||
.findFirst()
|
||||
.orElse(null));
|
||||
}
|
||||
|
|
|
@ -115,8 +115,9 @@ public class DebuggerStaticMappingProviderTest extends AbstractGhidraHeadedDebug
|
|||
intoProject(program);
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject("Target");
|
||||
tb.trace.getMemoryManager()
|
||||
.addRegion(".text", Lifespan.nowOn(0),
|
||||
.addRegion("Memory[.text]", Lifespan.nowOn(0),
|
||||
tb.range(0xdeadbeefL, 0xdeadbeefL + 0xff),
|
||||
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE));
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ import org.junit.Test;
|
|||
|
||||
import db.Transaction;
|
||||
import generic.Unique;
|
||||
import generic.theme.*;
|
||||
import generic.theme.ApplicationThemeManager;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.app.plugin.assembler.Assembler;
|
||||
import ghidra.app.plugin.assembler.Assemblers;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
||||
|
@ -46,8 +47,10 @@ import ghidra.pcode.exec.trace.TraceSleighUtils;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.program.model.listing.InstructionIterator;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
|
||||
|
@ -79,15 +82,25 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
|
|||
createTrace();
|
||||
}
|
||||
|
||||
SchemaContext buildContext() {
|
||||
return new ToySchemaBuilder()
|
||||
.useRegistersPerFrame()
|
||||
.noRegisterGroups()
|
||||
.build();
|
||||
}
|
||||
|
||||
protected void populateTrace() throws Exception {
|
||||
start = tb.addr(0x00400000);
|
||||
InstructionIterator iit;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject(buildContext(), "Target");
|
||||
tb.trace.getMemoryManager()
|
||||
.addRegion("echo:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff),
|
||||
.addRegion("Memory[echo:.text]", Lifespan.nowOn(0),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
|
||||
thread = tb.getOrAddThread("1", 0);
|
||||
thread = tb.getOrAddThread("Threads[1]", 0);
|
||||
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
|
||||
|
||||
PcodeExecutor<byte[]> init = TraceSleighUtils.buildByteExecutor(tb.trace, 0, thread, 0);
|
||||
init.executeSleigh("pc = 0x00400000;");
|
||||
|
@ -124,7 +137,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
|
|||
public void testCloseCurrentTraceEmpty() throws Exception {
|
||||
populateTrace();
|
||||
|
||||
TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1");
|
||||
TraceSchedule schedule1 = TraceSchedule.parse("0:.t%d-1".formatted(thread.getKey()));
|
||||
traceManager.openTrace(tb.trace);
|
||||
traceManager.activateThread(thread);
|
||||
waitForPass(() -> assertDecodeStep());
|
||||
|
@ -166,13 +179,13 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
|
|||
});
|
||||
|
||||
// Just one p-code step to load injection (decode step)
|
||||
TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1");
|
||||
TraceSchedule schedule1 = TraceSchedule.parse("0:.t%d-1".formatted(thread.getKey()));
|
||||
traceManager.openTrace(tb.trace);
|
||||
traceManager.activateThread(thread);
|
||||
traceManager.activateTime(schedule1);
|
||||
waitForPass(() -> assertEquals(schedule1, pcodeProvider.current.getTime()));
|
||||
|
||||
waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.getModelData()
|
||||
waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.copyModelData()
|
||||
.stream()
|
||||
.anyMatch(r -> r.getCode().contains("stepper_test_userop"))));
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ import ghidra.program.model.listing.Function;
|
|||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.stack.TraceObjectStack;
|
||||
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.TraceObjectManager;
|
||||
|
@ -51,7 +51,7 @@ import ghidra.trace.model.target.path.*;
|
|||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.table.GhidraTable;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
|
@ -167,7 +167,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
}
|
||||
}
|
||||
|
||||
protected TraceObjectThread addThread(int n) {
|
||||
protected TraceThread addThread(int n) {
|
||||
PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]");
|
||||
KeyPath threadPath = threadPattern.applyIntKeys(n).getSingletonPath();
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
|
@ -175,26 +175,26 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
.createObject(threadPath)
|
||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectThread.class));
|
||||
.queryInterface(TraceThread.class));
|
||||
}
|
||||
}
|
||||
|
||||
protected TraceObjectStack addStack(TraceObjectThread thread) {
|
||||
protected TraceStack addStack(TraceThread thread) {
|
||||
KeyPath stackPath = thread.getObject().getCanonicalPath().extend("Stack");
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
return Objects.requireNonNull(tb.trace.getObjectManager()
|
||||
.createObject(stackPath)
|
||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectStack.class));
|
||||
.queryInterface(TraceStack.class));
|
||||
}
|
||||
}
|
||||
|
||||
protected void addStackFrames(TraceObjectStack stack) {
|
||||
protected void addStackFrames(TraceStack stack) {
|
||||
addStackFrames(stack, 2);
|
||||
}
|
||||
|
||||
protected void addStackFrames(TraceObjectStack stack, int count) {
|
||||
protected void addStackFrames(TraceStack stack, int count) {
|
||||
KeyPath stackPath = stack.getObject().getCanonicalPath();
|
||||
TraceObjectManager om = tb.trace.getObjectManager();
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
|
@ -202,7 +202,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
TraceObject frame = om.createObject(stackPath.index(i))
|
||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||
.getDestination(null);
|
||||
frame.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC,
|
||||
frame.setAttribute(Lifespan.nowOn(0), TraceStackFrame.KEY_PC,
|
||||
tb.addr(0x00400100 + 0x100 * i));
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testActivateThreadNoStackEmpty() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceThread thread = addThread(1);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
traceManager.activateObject(thread.getObject());
|
||||
|
@ -275,7 +275,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testActivateThreadThenAddEmptyStackEmpty() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceThread thread = addThread(1);
|
||||
addStack(thread);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -289,9 +289,9 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testActivateThreadThenAddStackPopulatesProvider() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceThread thread = addThread(1);
|
||||
traceManager.activateObject(thread.getObject());
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
waitForTasks();
|
||||
|
@ -303,8 +303,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testAddStackThenActivateThreadPopulatesProvider() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -316,12 +316,14 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
|
||||
/**
|
||||
* Because keys are strings, we need to ensure they get sorted numerically
|
||||
*
|
||||
* @throws Exception because
|
||||
*/
|
||||
@Test
|
||||
public void testTableSortedCorrectly() throws Exception {
|
||||
createAndOpenTrace();
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack, 15);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -341,8 +343,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testAppendStackUpdatesProvider() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -356,7 +358,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
.createObject(stack.getObject().getCanonicalPath().index(2))
|
||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||
.getDestination(null);
|
||||
frame2.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC,
|
||||
frame2.setAttribute(Lifespan.nowOn(0), TraceStackFrame.KEY_PC,
|
||||
tb.addr(0x00400300));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
|
@ -374,8 +376,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testRemoveFrameUpdatesProvider() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -400,8 +402,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testRemoveStackUpdatesProvider() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -423,9 +425,9 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testActivateOtherThreadEmptiesProvider() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread1 = addThread(1);
|
||||
TraceObjectThread thread2 = addThread(2);
|
||||
TraceObjectStack stack1 = addStack(thread1);
|
||||
TraceThread thread1 = addThread(1);
|
||||
TraceThread thread2 = addThread(2);
|
||||
TraceStack stack1 = addStack(thread1);
|
||||
addStackFrames(stack1);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -444,8 +446,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testActivateSnap() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -477,8 +479,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testCloseCurrentTraceEmpty() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -497,8 +499,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testActivateFrameSelectsRow() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -524,8 +526,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
public void testDoubleClickRowActivateFrame() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -557,8 +559,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
traceManager.openTrace(tb.trace);
|
||||
programManager.openProgram(program);
|
||||
|
||||
TraceObjectThread thread = addThread(1);
|
||||
TraceObjectStack stack = addStack(thread);
|
||||
TraceThread thread = addThread(1);
|
||||
TraceStack stack = addStack(thread);
|
||||
addStackFrames(stack);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
|
@ -580,13 +582,13 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||
waitForDomainObject(program);
|
||||
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
TraceObjectMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager()
|
||||
TraceMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager()
|
||||
.createObject(KeyPath.parse("Processes[1].Memory[bin:.text]"))
|
||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectMemoryRegion.class));
|
||||
.queryInterface(TraceMemoryRegion.class));
|
||||
region.getObject()
|
||||
.setAttribute(Lifespan.nowOn(0), TraceObjectMemoryRegion.KEY_RANGE,
|
||||
.setAttribute(Lifespan.nowOn(0), TraceMemoryRegion.KEY_RANGE,
|
||||
tb.drng(0x00400000, 0x00400fff));
|
||||
|
||||
TraceLocation dloc =
|
||||
|
|
|
@ -34,13 +34,13 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
|||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||
import ghidra.trace.model.target.TraceObjectManager;
|
||||
import ghidra.trace.model.target.iface.TraceObjectExecutionStateful;
|
||||
import ghidra.trace.model.target.iface.TraceExecutionStateful;
|
||||
import ghidra.trace.model.target.path.PathFilter;
|
||||
import ghidra.trace.model.target.path.PathPattern;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceTimeManager;
|
||||
import ghidra.util.table.GhidraTable;
|
||||
|
||||
|
@ -71,8 +71,8 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
|
||||
DebuggerThreadsProvider provider;
|
||||
|
||||
protected TraceObjectThread thread1;
|
||||
protected TraceObjectThread thread2;
|
||||
protected TraceThread thread1;
|
||||
protected TraceThread thread2;
|
||||
|
||||
protected SchemaContext ctx;
|
||||
|
||||
|
@ -95,18 +95,18 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
}
|
||||
}
|
||||
|
||||
protected TraceObjectThread addThread(int index, Lifespan lifespan, String comment) {
|
||||
protected TraceThread addThread(int index, Lifespan lifespan, String comment) {
|
||||
TraceObjectManager om = tb.trace.getObjectManager();
|
||||
PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]");
|
||||
TraceObjectThread thread = Objects.requireNonNull(om.createObject(
|
||||
TraceThread thread = Objects.requireNonNull(om.createObject(
|
||||
threadPattern.applyIntKeys(index).getSingletonPath())
|
||||
.insert(lifespan, ConflictResolution.TRUNCATE)
|
||||
.getDestination(null)
|
||||
.queryInterface(TraceObjectThread.class));
|
||||
.queryInterface(TraceThread.class));
|
||||
thread.getObject()
|
||||
.setAttribute(lifespan, TraceObjectExecutionStateful.KEY_STATE,
|
||||
.setAttribute(lifespan, TraceExecutionStateful.KEY_STATE,
|
||||
TraceExecutionState.STOPPED.name());
|
||||
thread.getObject().setAttribute(lifespan, TraceObjectThread.KEY_COMMENT, comment);
|
||||
thread.getObject().setAttribute(lifespan, TraceThread.KEY_COMMENT, comment);
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
assertNull(provider.panel.getSelectedItem());
|
||||
}
|
||||
|
||||
protected void assertThreadSelected(TraceObjectThread thread) {
|
||||
protected void assertThreadSelected(TraceThread thread) {
|
||||
ValueRow row = provider.panel.getSelectedItem();
|
||||
assertNotNull(row);
|
||||
assertEquals(thread.getObject(), row.getValue().getChild());
|
||||
|
@ -329,7 +329,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||
waitForTasks();
|
||||
|
||||
waitForPass(() -> assertEquals("A different comment",
|
||||
thread1.getObject().getAttribute(0, TraceObjectThread.KEY_COMMENT).getValue()));
|
||||
thread1.getObject().getAttribute(0, TraceThread.KEY_COMMENT).getValue()));
|
||||
}
|
||||
|
||||
// @Test // Not gonna with write-behind cache
|
||||
|
|
|
@ -92,7 +92,7 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
// Timestamp is left unchecked, since default is current time
|
||||
}
|
||||
|
||||
@Test // TODO: Technically, this is a plugin action.... Different test case?
|
||||
@Test // Technically, this is a plugin action.... Different test case?
|
||||
public void testActionRenameSnapshot() throws Exception {
|
||||
// More often than not, this action will be used from the dynamic listing
|
||||
addPlugin(tool, DebuggerListingPlugin.class);
|
||||
|
@ -125,7 +125,7 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
DBTraceSnapshot snapshot = tb.trace.getTimeManager().getSnapshot(10, false);
|
||||
assertEquals("My Snapshot", snapshot.getDescription());
|
||||
|
||||
// TODO: Test cancelled has no effect
|
||||
// LATER?: Test cancelled has no effect
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -153,7 +153,8 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
createSnaplessTrace();
|
||||
TraceThread thread;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
thread = tb.trace.getThreadManager().createThread("Thread 1", 0);
|
||||
tb.createRootObject("Target");
|
||||
thread = tb.trace.getThreadManager().createThread("Threads[1]", 0);
|
||||
}
|
||||
traceManager.openTrace(tb.trace);
|
||||
traceManager.activateThread(thread);
|
||||
|
|
|
@ -29,8 +29,7 @@ import ghidra.program.model.lang.Register;
|
|||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceExecutionState;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
|
@ -233,27 +232,27 @@ public class MockTarget implements Target {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakpointValid(TraceBreakpoint breakpoint) {
|
||||
public boolean isBreakpointValid(TraceBreakpointLocation breakpoint) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpoint breakpoint) {
|
||||
public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint) {
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBreakpoint(TraceBreakpoint breakpoint) {
|
||||
public void deleteBreakpoint(TraceBreakpointCommon breakpoint) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpoint breakpoint,
|
||||
public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint,
|
||||
boolean enabled) {
|
||||
return AsyncUtils.nil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled) {
|
||||
public void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,16 +52,18 @@ import ghidra.program.model.listing.ProgramContext;
|
|||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.stack.TraceObjectStack;
|
||||
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.path.PathFilter;
|
||||
import ghidra.trace.model.target.schema.SchemaContext;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
|
@ -249,6 +251,13 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
mem.getViewValue(scratch, regW1).getUnsignedValue());
|
||||
}
|
||||
|
||||
protected SchemaContext buildContext() {
|
||||
return new ToySchemaBuilder()
|
||||
.noRegisterGroups()
|
||||
.useRegistersPerFrame()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPureEmulationRelocated() throws Throwable {
|
||||
createAndOpenTrace("x86:LE:64:default");
|
||||
|
@ -282,7 +291,9 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
TraceThread thread;
|
||||
TraceMemorySpace regs;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject(buildContext(), "Target");
|
||||
thread = tb.getOrAddThread("Threads[0]", 0);
|
||||
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
|
||||
regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
|
||||
regs.setValue(0, new RegisterValue(program.getLanguage().getProgramCounter(),
|
||||
BigInteger.valueOf(0x55550000)));
|
||||
|
@ -295,8 +306,8 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
waitForSwing();
|
||||
waitOn(settled);
|
||||
|
||||
long scratch =
|
||||
emulationPlugin.emulate(tb.trace, TraceSchedule.parse("0:t0-1"), TaskMonitor.DUMMY);
|
||||
long scratch = emulationPlugin.emulate(tb.trace,
|
||||
TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), TaskMonitor.DUMMY);
|
||||
|
||||
assertEquals("deadbeefcafebabe",
|
||||
regs.getViewValue(scratch, tb.reg("RAX")).getUnsignedValue().toString(16));
|
||||
|
@ -315,7 +326,9 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
TraceMemoryManager mem = tb.trace.getMemoryManager();
|
||||
TraceThread thread;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
tb.createRootObject(buildContext(), "Target");
|
||||
thread = tb.getOrAddThread("Threads[0]", 0);
|
||||
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
|
||||
buf.assemble("MOV RAX, qword ptr [0x00600800]");
|
||||
mem.putBytes(0, tb.addr(0x00400000), ByteBuffer.wrap(buf.getBytes()));
|
||||
mem.putBytes(0, tb.addr(0x00600800),
|
||||
|
@ -344,8 +357,8 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
tb.exec(platform, 0, thread, 0, "RIP = 0x00400000;");
|
||||
}
|
||||
|
||||
long scratch =
|
||||
emulationPlugin.emulate(platform, TraceSchedule.parse("0:t0-1"), TaskMonitor.DUMMY);
|
||||
long scratch = emulationPlugin.emulate(platform,
|
||||
TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), TaskMonitor.DUMMY);
|
||||
TraceMemorySpace regs = mem.getMemoryRegisterSpace(thread, false);
|
||||
assertEquals("deadbeefcafebabe",
|
||||
regs.getViewValue(platform, scratch, tb.reg(platform, "RAX"))
|
||||
|
@ -494,7 +507,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
TraceBreakpoint tb = trace.getBreakpointManager()
|
||||
TraceBreakpointLocation tb = trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
// Force "partial instruction"
|
||||
|
@ -568,7 +581,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
TraceBreakpoint tb = trace.getBreakpointManager()
|
||||
TraceBreakpointLocation tb = trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
// Force "partial instruction"
|
||||
|
@ -634,7 +647,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
|
||||
|
||||
try (Transaction tx = trace.openTransaction("Add breakpoint")) {
|
||||
TraceBreakpoint tb = trace.getBreakpointManager()
|
||||
TraceBreakpointLocation tb = trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
// Force "partial instruction"
|
||||
|
@ -709,7 +722,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
|
||||
|
||||
try (Transaction tx = trace.openTransaction("Add breakpoint")) {
|
||||
TraceBreakpoint tb = trace.getBreakpointManager()
|
||||
TraceBreakpointLocation tb = trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
tb.setEmuSleigh(0, """
|
||||
|
@ -854,7 +867,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
|
||||
// Inject some logic that would require a cache refresh to materialize
|
||||
try (Transaction tx = trace.openTransaction("Add breakpoint")) {
|
||||
TraceBreakpoint tb = trace.getBreakpointManager()
|
||||
TraceBreakpointLocation tb = trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread),
|
||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
|
||||
tb.setEmuSleigh(0, """
|
||||
|
@ -986,10 +999,10 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
|
|||
public void testEmuSchemaHasWorkingStackFrames() throws Exception {
|
||||
TraceObjectSchema rootSchema = ProgramEmulationUtils.EMU_SESSION_SCHEMA;
|
||||
TraceObjectSchema threadSchema = rootSchema.getSuccessorSchema(KeyPath.parse("Threads[1]"));
|
||||
KeyPath found = threadSchema.searchForCanonicalContainer(TraceObjectStackFrame.class);
|
||||
KeyPath found = threadSchema.searchForCanonicalContainer(TraceStackFrame.class);
|
||||
assertEquals(KeyPath.parse("Stack"), found);
|
||||
|
||||
PathFilter stackFilter = threadSchema.searchFor(TraceObjectStack.class, false);
|
||||
PathFilter stackFilter = threadSchema.searchFor(TraceStack.class, false);
|
||||
assertNotNull("Non-unique Stack", stackFilter.getSingletonPath());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -635,13 +635,14 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg
|
|||
TraceMemoryRegion echoText, echoData, libText, libData;
|
||||
DBTraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
echoText = mm.createRegion("Memory.Regions[/bin/echo (0x00400000)]",
|
||||
tb.createRootObject("Target");
|
||||
echoText = mm.createRegion("Memory[/bin/echo (0x00400000)]",
|
||||
0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
echoData = mm.createRegion("Memory.Regions[/bin/echo (0x00600000)]",
|
||||
echoData = mm.createRegion("Memory[/bin/echo (0x00600000)]",
|
||||
0, tb.range(0x00600000, 0x00600fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
libText = mm.createRegion("Memory.Regions[/lib/libc.so (0x7ff00000)]",
|
||||
libText = mm.createRegion("Memory[/lib/libc.so (0x7ff00000)]",
|
||||
0, tb.range(0x7ff00000, 0x7ff0ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
libData = mm.createRegion("Memory.Regions[/lib/libc.so (0x7ff20000)]",
|
||||
libData = mm.createRegion("Memory[/lib/libc.so (0x7ff20000)]",
|
||||
0, tb.range(0x7ff20000, 0x7ff20fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||
}
|
||||
|
||||
|
@ -688,7 +689,7 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg
|
|||
objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||
}
|
||||
|
||||
TraceModule modBash = objModBash.queryInterface(TraceObjectModule.class);
|
||||
TraceModule modBash = objModBash.queryInterface(TraceModule.class);
|
||||
assertEquals(Map.of(),
|
||||
mappingService.proposeModuleMaps(List.of(modBash), 0, List.of(program)));
|
||||
}
|
||||
|
|
|
@ -80,8 +80,8 @@ import ghidra.program.model.symbol.SourceType;
|
|||
import ghidra.program.util.*;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.TraceLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.listing.TraceData;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
@ -888,7 +888,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
waitOn(frameAtSetup.setReturnAddress(editor, tb.addr(0xdeadbeef)));
|
||||
waitForTasks();
|
||||
|
||||
TraceBreakpoint bptUnwind;
|
||||
TraceBreakpointLocation bptUnwind;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
bptUnwind = tb.trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
|
||||
|
@ -976,7 +976,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
Register sp = program.getCompilerSpec().getStackPointer();
|
||||
long spAtSetup = regs.getValue(0, sp).getUnsignedValue().longValueExact();
|
||||
|
||||
TraceBreakpoint bptUnwind;
|
||||
TraceBreakpointLocation bptUnwind;
|
||||
try (Transaction tx = tb.startTransaction()) {
|
||||
bptUnwind = tb.trace.getBreakpointManager()
|
||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), entry, Set.of(),
|
||||
|
|
|
@ -300,11 +300,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
protected DBTraceBreakpointManager createBreakpointManager(DBTraceThreadManager threadManager)
|
||||
protected DBTraceBreakpointManager createBreakpointManager(DBTraceObjectManager objectManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Breakpoint Manager",
|
||||
(openMode, monitor) -> new DBTraceBreakpointManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this, threadManager));
|
||||
this, objectManager));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
|
@ -367,10 +367,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
}
|
||||
|
||||
@DependentService
|
||||
protected DBTraceModuleManager createModuleManager() throws CancelledException, IOException {
|
||||
protected DBTraceModuleManager createModuleManager(DBTraceObjectManager objectManager)
|
||||
throws CancelledException, IOException {
|
||||
return createTraceManager("Module Manager",
|
||||
(openMode, monitor) -> new DBTraceModuleManager(dbh, openMode, rwLock, monitor,
|
||||
baseLanguage, this));
|
||||
(openMode, monitor) -> new DBTraceModuleManager(dbh, openMode, rwLock, monitor, this,
|
||||
objectManager));
|
||||
}
|
||||
|
||||
@DependentService
|
||||
|
@ -670,16 +671,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
if (recordChanges) {
|
||||
traceChangeSet.sourceArchiveAdded(sourceArchiveID.getValue());
|
||||
}
|
||||
setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.SOURCE_TYPE_ARCHIVE_ADDED, null, sourceArchiveID));
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.SOURCE_TYPE_ARCHIVE_ADDED, null,
|
||||
sourceArchiveID));
|
||||
}
|
||||
|
||||
public void dataTypeChanged(long changedID, DataType changedType) {
|
||||
if (recordChanges) {
|
||||
traceChangeSet.dataTypeChanged(changedID);
|
||||
}
|
||||
setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.DATA_TYPE_CHANGED, null, changedID, changedType));
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_CHANGED, null, changedID,
|
||||
changedType));
|
||||
}
|
||||
|
||||
public void dataTypeAdded(long addedID, DataType addedType) {
|
||||
|
@ -701,16 +702,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
if (recordChanges) {
|
||||
traceChangeSet.dataTypeChanged(movedID);
|
||||
}
|
||||
setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.DATA_TYPE_MOVED, null, movedID, oldPath, newPath));
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_MOVED, null, movedID,
|
||||
oldPath, newPath));
|
||||
}
|
||||
|
||||
public void dataTypeNameChanged(long renamedID, String oldName, String newName) {
|
||||
if (recordChanges) {
|
||||
traceChangeSet.dataTypeChanged(renamedID);
|
||||
}
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_RENAMED, null, renamedID, oldName,
|
||||
newName));
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_RENAMED, null, renamedID,
|
||||
oldName, newName));
|
||||
}
|
||||
|
||||
public void dataTypeDeleted(long deletedID, DataTypePath deletedPath) {
|
||||
|
@ -725,16 +726,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
if (recordChanges) {
|
||||
traceChangeSet.categoryAdded(addedID);
|
||||
}
|
||||
setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_ADDED, null, addedID, addedCategory));
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_ADDED, null, addedID,
|
||||
addedCategory));
|
||||
}
|
||||
|
||||
public void categoryMoved(long movedID, CategoryPath oldPath, CategoryPath newPath) {
|
||||
if (recordChanges) {
|
||||
traceChangeSet.categoryChanged(movedID);
|
||||
}
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_MOVED, null, movedID, oldPath,
|
||||
newPath));
|
||||
setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_MOVED, null, movedID,
|
||||
oldPath, newPath));
|
||||
}
|
||||
|
||||
public void categoryRenamed(long renamedID, String oldName, String newName) {
|
||||
|
|
|
@ -433,18 +433,9 @@ public enum DBTraceUtils {
|
|||
*
|
||||
* @param baseName the base name of the table group
|
||||
* @param space the address space
|
||||
* @param threadKey the thread key, -1 usually indicating "no thread"
|
||||
* @param frameLevel the frame level
|
||||
* @return the table name
|
||||
*/
|
||||
public static String tableName(String baseName, AddressSpace space, long threadKey,
|
||||
int frameLevel) {
|
||||
if (space.isRegisterSpace()) {
|
||||
if (frameLevel == 0) {
|
||||
return baseName + "_" + space.getName() + "_" + threadKey;
|
||||
}
|
||||
return baseName + "_" + space.getName() + "_" + threadKey + "_" + frameLevel;
|
||||
}
|
||||
public static String tableName(String baseName, AddressSpace space) {
|
||||
return baseName + "_" + space.getName();
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
|
|||
keyToRecordMap.remove(key);
|
||||
}
|
||||
|
||||
// Add any remaing overlay which are missing from factory
|
||||
// Add any remaining overlays which are missing from factory
|
||||
for (long key : keyToRecordMap.keySet()) {
|
||||
DBTraceOverlaySpaceEntry ent = keyToRecordMap.get(key);
|
||||
String spaceName = ent.name;
|
||||
|
@ -268,7 +268,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
|
|||
ent.set(space.getName(), base.getName());
|
||||
trace.updateViewsAddSpaceBlock(space);
|
||||
trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.OVERLAY_ADDED, null, trace, null, space));
|
||||
new TraceChangeRecord<>(TraceEvents.OVERLAY_ADDED, space, trace, null, space));
|
||||
return space;
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
|
|||
factory.removeOverlaySpace(name);
|
||||
trace.updateViewsDeleteSpaceBlock(space);
|
||||
trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.OVERLAY_DELETED, null, trace, space, null));
|
||||
new TraceChangeRecord<>(TraceEvents.OVERLAY_DELETED, space, trace, space, null));
|
||||
invalidateCache(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,8 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD
|
|||
@DBAnnotatedColumn(COMMENT_COLUMN_NAME)
|
||||
static DBObjectColumn COMMENT_COLUMN;
|
||||
|
||||
static String tableName(AddressSpace space, long threadKey, int frameLevel) {
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel);
|
||||
static String tableName(AddressSpace space) {
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space);
|
||||
}
|
||||
|
||||
@DBAnnotatedField(column = TYPE_COLUMN_NAME, indexed = true)
|
||||
|
@ -104,7 +104,7 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD
|
|||
|
||||
@Override
|
||||
public long getId() {
|
||||
return DBTraceBookmarkManager.packId(key, space);
|
||||
return DBTraceBookmarkManager.packId(key, range.getAddressSpace());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -140,14 +140,14 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD
|
|||
update(CATEGORY_COLUMN, COMMENT_COLUMN);
|
||||
}
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.BOOKMARK_CHANGED, space, this));
|
||||
new TraceChangeRecord<>(TraceEvents.BOOKMARK_CHANGED, space.space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
space.bookmarkMapSpace.deleteData(this);
|
||||
space.trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.BOOKMARK_DELETED, space, this));
|
||||
new TraceChangeRecord<>(TraceEvents.BOOKMARK_DELETED, space.space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,7 +29,8 @@ import ghidra.program.model.address.*;
|
|||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
|
||||
import ghidra.trace.database.space.*;
|
||||
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager;
|
||||
import ghidra.trace.database.space.DBTraceDelegatingManager;
|
||||
import ghidra.trace.database.thread.DBTraceThreadManager;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.bookmark.TraceBookmarkManager;
|
||||
|
@ -55,14 +56,6 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
* | SpaceID | Key |
|
||||
* +---------+----------+
|
||||
* }
|
||||
*
|
||||
* For register space:
|
||||
*
|
||||
* {@code
|
||||
* +---12----+----32----+----8----+--12--+
|
||||
* | SpaceID | Thread | Frame | Key |
|
||||
* +---------+----------+---------+------+
|
||||
* }
|
||||
*/
|
||||
// NOTE: There are few address spaces, but their IDs encode other stuff :/
|
||||
protected static final int SPACE_ID_MASK = 0x0FFF;
|
||||
|
@ -71,23 +64,8 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
protected static final long MEM_KEY_MASK = 0x000F_FFFF_FFFF_FFFFL;
|
||||
protected static final int MEM_KEY_SHIFT = 0;
|
||||
|
||||
protected static final long REG_THREAD_MASK = 0x0_FFFF_FFFFL;
|
||||
protected static final int REG_THREAD_SHIFT = 20;
|
||||
|
||||
protected static final long REG_FRAME_MASK = 0x00FF;
|
||||
protected static final int REG_FRAME_SHIFT = 12;
|
||||
|
||||
protected static final long REG_KEY_MASK = 0x0FFF;
|
||||
protected static final int REG_KEY_SHIFT = 0;
|
||||
|
||||
protected static long packId(long key, DBTraceSpaceKey spaceKey) {
|
||||
return spaceKey.getAddressSpace().isRegisterSpace() ? packRegId(key, spaceKey)
|
||||
: packMemId(key, spaceKey);
|
||||
}
|
||||
|
||||
protected static long packMemId(long key, DBTraceSpaceKey spaceKey) {
|
||||
long spaceId = spaceKey.getAddressSpace().getSpaceID();
|
||||
assert spaceKey.getThread() == null;
|
||||
protected static long packId(long key, AddressSpace space) {
|
||||
long spaceId = space.getSpaceID();
|
||||
|
||||
if ((spaceId & SPACE_ID_MASK) != spaceId) {
|
||||
throw new AssertionError("Bad assumption");
|
||||
|
@ -98,69 +76,17 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
return (spaceId << SPACE_ID_SHIFT) | (key << MEM_KEY_SHIFT);
|
||||
}
|
||||
|
||||
protected static long packRegId(long key, DBTraceSpaceKey spaceKey) {
|
||||
long spaceId = spaceKey.getAddressSpace().getSpaceID();
|
||||
long threadKey = spaceKey.getThread().getKey();
|
||||
int frameLevel = spaceKey.getFrameLevel();
|
||||
|
||||
if ((spaceId & SPACE_ID_MASK) != spaceId) {
|
||||
throw new AssertionError("Bad assumption");
|
||||
}
|
||||
if ((threadKey & REG_THREAD_MASK) != threadKey) {
|
||||
throw new AssertionError("Bad assumption");
|
||||
}
|
||||
if ((frameLevel & REG_FRAME_MASK) != frameLevel) {
|
||||
throw new AssertionError("Bad assumption");
|
||||
}
|
||||
if ((key & REG_KEY_MASK) != key) {
|
||||
throw new AssertionError("Bad assumption");
|
||||
}
|
||||
return (spaceId << SPACE_ID_SHIFT) | (threadKey << REG_THREAD_SHIFT) |
|
||||
(frameLevel << REG_FRAME_SHIFT) | (key << REG_KEY_SHIFT);
|
||||
}
|
||||
|
||||
protected static int unpackSpaceId(long id) {
|
||||
return (int) ((id >> SPACE_ID_SHIFT) & SPACE_ID_MASK);
|
||||
}
|
||||
|
||||
protected static long unpackMemKey(long id) {
|
||||
protected static long unpackKey(long id) {
|
||||
return (id >> MEM_KEY_SHIFT) & MEM_KEY_MASK;
|
||||
}
|
||||
|
||||
protected static long unpackRegThread(long id) {
|
||||
return (id >> REG_THREAD_SHIFT) & REG_THREAD_MASK;
|
||||
}
|
||||
|
||||
protected static int unpackRegFrame(long id) {
|
||||
return (int) ((id >> REG_FRAME_SHIFT) & REG_FRAME_MASK);
|
||||
}
|
||||
|
||||
protected static long unpackRegKey(long id) {
|
||||
return (id >> REG_KEY_SHIFT) & REG_KEY_MASK;
|
||||
}
|
||||
|
||||
protected static DBTraceSpaceKey unpackSpaceKey(long id, Language baseLanguage,
|
||||
DBTraceThreadManager threadManager) {
|
||||
protected static AddressSpace unpackSpace(long id, AddressFactory addressFactory) {
|
||||
int spaceId = unpackSpaceId(id);
|
||||
AddressSpace space = baseLanguage.getAddressFactory().getAddressSpace(spaceId);
|
||||
if (space == null) {
|
||||
return null;
|
||||
}
|
||||
return space.isRegisterSpace() ? unpackRegSpaceKey(space, threadManager, id)
|
||||
: unpackMemSpaceKey(space, id);
|
||||
}
|
||||
|
||||
protected static DBTraceSpaceKey unpackMemSpaceKey(AddressSpace space, long id) {
|
||||
return DBTraceSpaceKey.create(space, null, 0);
|
||||
}
|
||||
|
||||
protected static DBTraceSpaceKey unpackRegSpaceKey(AddressSpace space,
|
||||
DBTraceThreadManager threadManager, long id) {
|
||||
long threadKey = unpackRegThread(id);
|
||||
TraceThread thread = threadManager.getThread(threadKey);
|
||||
assert thread != null;
|
||||
int frameLevel = unpackRegFrame(id);
|
||||
return DBTraceSpaceKey.create(space, thread, frameLevel);
|
||||
return addressFactory.getAddressSpace(spaceId);
|
||||
}
|
||||
|
||||
protected final Map<String, DBTraceBookmarkType> typesByName = new HashMap<>();
|
||||
|
@ -178,13 +104,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
@Override
|
||||
protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceBookmarkSpace(this, space, null, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceBookmarkSpace createRegisterSpace(AddressSpace space, TraceThread thread,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
return new DBTraceBookmarkSpace(this, space, thread, ent.getFrameLevel());
|
||||
return new DBTraceBookmarkSpace(this, space);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -267,16 +187,15 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
@Override
|
||||
public DBTraceBookmark getBookmark(long id) {
|
||||
try (LockHold hold = LockHold.lock(lock.readLock())) {
|
||||
DBTraceSpaceKey spaceKey = unpackSpaceKey(id, baseLanguage, threadManager);
|
||||
if (spaceKey == null) {
|
||||
AddressSpace addressSpace = unpackSpace(id, trace.getInternalAddressFactory());
|
||||
if (addressSpace == null) {
|
||||
return null;
|
||||
}
|
||||
DBTraceBookmarkSpace space = get(spaceKey, false);
|
||||
DBTraceBookmarkSpace space = get(addressSpace, false);
|
||||
if (space == null) {
|
||||
return null;
|
||||
}
|
||||
long bookmarkKey =
|
||||
spaceKey.getAddressSpace().isRegisterSpace() ? unpackRegKey(id) : unpackMemKey(id);
|
||||
long bookmarkKey = unpackKey(id);
|
||||
return space.bookmarkMapSpace.getDataByKey(bookmarkKey);
|
||||
}
|
||||
}
|
||||
|
@ -288,7 +207,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
|
||||
@Override
|
||||
public Set<String> getCategoriesForType(TraceBookmarkType type) {
|
||||
return delegateHashSet(getActiveMemorySpaces(), m -> m.getCategoriesForType(type));
|
||||
return delegateHashSet(getActiveSpaces(), m -> m.getCategoriesForType(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -300,7 +219,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
|
||||
@Override
|
||||
public Collection<? extends DBTraceBookmark> getAllBookmarks() {
|
||||
return delegateCollection(getActiveMemorySpaces(), m -> m.getAllBookmarks());
|
||||
return delegateCollection(getActiveSpaces(), m -> m.getAllBookmarks());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -329,7 +248,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
return Collections.emptySet();
|
||||
}
|
||||
Collection<DBTraceBookmark> result = new ArrayList<>();
|
||||
for (DBTraceBookmarkSpace space : memSpaces.values()) {
|
||||
for (DBTraceBookmarkSpace space : spaces.values()) {
|
||||
result.addAll(space.bookmarkMapSpace
|
||||
.reduce(TraceAddressSnapRangeQuery.added(from, to, space.getAddressSpace()))
|
||||
.values());
|
||||
|
@ -343,7 +262,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
|
|||
return Collections.emptySet();
|
||||
}
|
||||
Collection<DBTraceBookmark> result = new ArrayList<>();
|
||||
for (DBTraceBookmarkSpace space : memSpaces.values()) {
|
||||
for (DBTraceBookmarkSpace space : spaces.values()) {
|
||||
result.addAll(space.bookmarkMapSpace
|
||||
.reduce(TraceAddressSnapRangeQuery.removed(from, to, space.getAddressSpace()))
|
||||
.values());
|
||||
|
|
|
@ -25,9 +25,9 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace;
|
|||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
|
||||
import ghidra.trace.database.space.DBTraceSpaceBased;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.bookmark.TraceBookmarkSpace;
|
||||
import ghidra.trace.model.bookmark.TraceBookmarkType;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.LockHold;
|
||||
|
@ -39,47 +39,37 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
|
|||
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,
|
||||
TraceThread thread, int frameLevel)
|
||||
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space)
|
||||
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, null, 0, DBTraceBookmark.class,
|
||||
new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space), trace,
|
||||
trace.getStoreFactory(), lock, space, DBTraceBookmark.class,
|
||||
(t, s, r) -> new DBTraceBookmark(this, t, s, r));
|
||||
this.bookmarksByTypeName =
|
||||
bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN);
|
||||
this.bookmarkView = Collections.unmodifiableCollection(bookmarkMapSpace.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trace getTrace() {
|
||||
return trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressSpace getAddressSpace() {
|
||||
return space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return thread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) {
|
||||
if (!(type instanceof DBTraceBookmarkType)) {
|
||||
throw new IllegalArgumentException("Given type is not part of this trace");
|
||||
|
@ -110,7 +100,7 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
|
|||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
DBTraceBookmark bookmark = bookmarkMapSpace.put(address, lifespan, null);
|
||||
bookmark.set(type.getTypeString(), category, comment);
|
||||
trace.setChanged(new TraceChangeRecord<>(TraceEvents.BOOKMARK_ADDED, this, bookmark));
|
||||
trace.setChanged(new TraceChangeRecord<>(TraceEvents.BOOKMARK_ADDED, space, bookmark));
|
||||
return bookmark;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,460 +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.breakpoint;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData;
|
||||
import ghidra.trace.database.thread.DBTraceThreadManager;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.database.DBCachedObjectStore;
|
||||
import ghidra.util.database.DBObjectColumn;
|
||||
import ghidra.util.database.annot.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
@DBAnnotatedObjectInfo(version = 1)
|
||||
public class DBTraceBreakpoint
|
||||
extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceBreakpoint>
|
||||
implements TraceBreakpoint {
|
||||
protected static final String TABLE_NAME = "Breakpoints";
|
||||
|
||||
private static final byte ENABLED_MASK = (byte) (1 << 7);
|
||||
private static final byte EMU_ENABLED_MASK = (byte) (1 << 6);
|
||||
|
||||
static final String PATH_COLUMN_NAME = "Path";
|
||||
static final String NAME_COLUMN_NAME = "Name";
|
||||
static final String THREADS_COLUMN_NAME = "Threads";
|
||||
static final String FLAGS_COLUMN_NAME = "Flags";
|
||||
static final String COMMENT_COLUMN_NAME = "Comment";
|
||||
static final String SLEIGH_COLUMN_NAME = "Sleigh";
|
||||
|
||||
@DBAnnotatedColumn(PATH_COLUMN_NAME)
|
||||
static DBObjectColumn PATH_COLUMN;
|
||||
@DBAnnotatedColumn(NAME_COLUMN_NAME)
|
||||
static DBObjectColumn NAME_COLUMN;
|
||||
@DBAnnotatedColumn(THREADS_COLUMN_NAME)
|
||||
static DBObjectColumn THREADS_COLUMN;
|
||||
@DBAnnotatedColumn(FLAGS_COLUMN_NAME)
|
||||
static DBObjectColumn FLAGS_COLUMN;
|
||||
@DBAnnotatedColumn(COMMENT_COLUMN_NAME)
|
||||
static DBObjectColumn COMMENT_COLUMN;
|
||||
@DBAnnotatedColumn(SLEIGH_COLUMN_NAME)
|
||||
static DBObjectColumn SLEIGH_COLUMN;
|
||||
|
||||
protected static String tableName(AddressSpace space, long threadKey) {
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0);
|
||||
}
|
||||
|
||||
@DBAnnotatedField(column = PATH_COLUMN_NAME, indexed = true)
|
||||
private String path;
|
||||
@DBAnnotatedField(column = NAME_COLUMN_NAME)
|
||||
private String name;
|
||||
@DBAnnotatedField(column = THREADS_COLUMN_NAME)
|
||||
private long[] threadKeys;
|
||||
@DBAnnotatedField(column = FLAGS_COLUMN_NAME)
|
||||
private byte flagsByte;
|
||||
@DBAnnotatedField(column = COMMENT_COLUMN_NAME)
|
||||
private String comment;
|
||||
@DBAnnotatedField(column = SLEIGH_COLUMN_NAME)
|
||||
private String emuSleigh;
|
||||
|
||||
private final Set<TraceBreakpointKind> kinds = EnumSet.noneOf(TraceBreakpointKind.class);
|
||||
private final Set<TraceBreakpointKind> kindsView = Collections.unmodifiableSet(kinds);
|
||||
private boolean enabled;
|
||||
private boolean emuEnabled;
|
||||
|
||||
protected final DBTraceBreakpointSpace space;
|
||||
|
||||
public DBTraceBreakpoint(DBTraceBreakpointSpace space,
|
||||
DBTraceAddressSnapRangePropertyMapTree<DBTraceBreakpoint, ?> tree,
|
||||
DBCachedObjectStore<?> store, DBRecord record) {
|
||||
super(tree, store, record);
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fresh(boolean created) throws IOException {
|
||||
super.fresh(created);
|
||||
if (created) {
|
||||
return;
|
||||
}
|
||||
doFresh();
|
||||
}
|
||||
|
||||
private void doFresh() {
|
||||
kinds.clear();
|
||||
for (TraceBreakpointKind k : TraceBreakpointKind.values()) {
|
||||
if ((flagsByte & k.getBits()) != 0) {
|
||||
kinds.add(k);
|
||||
}
|
||||
}
|
||||
enabled = (flagsByte & ENABLED_MASK) != 0;
|
||||
emuEnabled = (flagsByte & EMU_ENABLED_MASK) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTrace getTrace() {
|
||||
return space.trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setRecordValue(DBTraceBreakpoint value) {
|
||||
// Nothing: record is the value
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceBreakpoint getRecordValue() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void set(String path, String name, Collection<TraceThread> threads,
|
||||
Collection<TraceBreakpointKind> kinds, boolean enabled, boolean emuEnabled,
|
||||
String comment) {
|
||||
// TODO: Check that the threads exist and that each's lifespan covers the breakpoint's
|
||||
// TODO: This would require additional validation any time those are updated
|
||||
// TODO: For efficiency, would also require index of breakpoints by thread
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
if (!(threads instanceof Set<?>)) {
|
||||
threads = Set.copyOf(threads);
|
||||
}
|
||||
this.threadKeys = new long[threads.size()];
|
||||
int i = 0;
|
||||
for (TraceThread t : threads) {
|
||||
this.threadKeys[i++] = t.getKey();
|
||||
}
|
||||
this.flagsByte = 0;
|
||||
this.kinds.clear();
|
||||
for (TraceBreakpointKind k : kinds) {
|
||||
this.flagsByte |= k.getBits();
|
||||
this.kinds.add(k);
|
||||
}
|
||||
if (enabled) {
|
||||
this.flagsByte |= ENABLED_MASK;
|
||||
}
|
||||
if (emuEnabled) {
|
||||
this.flagsByte |= EMU_ENABLED_MASK;
|
||||
}
|
||||
this.comment = comment;
|
||||
update(PATH_COLUMN, NAME_COLUMN, THREADS_COLUMN, FLAGS_COLUMN, COMMENT_COLUMN);
|
||||
this.enabled = enabled;
|
||||
this.emuEnabled = emuEnabled;
|
||||
// Msg.debug(this, "trace: breakpoint " + this + " enabled=" + enabled + ", because set");
|
||||
}
|
||||
|
||||
public void set(String path, String name, long[] threadKeys,
|
||||
byte flagsByte, String comment) {
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.threadKeys = Arrays.copyOf(threadKeys, threadKeys.length);
|
||||
this.flagsByte = flagsByte;
|
||||
this.comment = comment;
|
||||
update(PATH_COLUMN, NAME_COLUMN, THREADS_COLUMN, FLAGS_COLUMN, COMMENT_COLUMN);
|
||||
doFresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(long snap, String name) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
this.name = name;
|
||||
update(NAME_COLUMN);
|
||||
}
|
||||
space.trace
|
||||
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceThread> getThreads(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
if (threadKeys.length == 0) {
|
||||
return Set.of();
|
||||
}
|
||||
// NOTE: Caching this result could get hairy if any threads are invalidated....
|
||||
Set<TraceThread> threads = new LinkedHashSet<>(threadKeys.length);
|
||||
DBTraceThreadManager threadManager = space.trace.getThreadManager();
|
||||
for (int i = 0; i < threadKeys.length; i++) {
|
||||
TraceThread t = threadManager.getThread(threadKeys[i]);
|
||||
if (t == null) {
|
||||
Msg.warn(this, "Thread " + threadKeys[i] +
|
||||
" has been deleted since creating this breakpoint.");
|
||||
}
|
||||
threads.add(t);
|
||||
}
|
||||
return Collections.unmodifiableSet(threads);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressRange getRange(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMinAddress(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return range.getMinAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return range.getMaxAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return range.getLength();
|
||||
}
|
||||
}
|
||||
|
||||
protected void setLifespan(Lifespan newLifespan) throws DuplicateNameException {
|
||||
Lifespan oldLifespan;
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
space.manager.checkDuplicatePath(this, path, newLifespan);
|
||||
oldLifespan = lifespan;
|
||||
doSetLifespan(newLifespan);
|
||||
}
|
||||
space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_LIFESPAN_CHANGED,
|
||||
space, this, oldLifespan, newLifespan));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lifespan getLifespan() {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return lifespan;
|
||||
}
|
||||
}
|
||||
|
||||
protected DBTraceBreakpoint doCopy() {
|
||||
DBTraceBreakpoint breakpoint = space.breakpointMapSpace.put(this, null);
|
||||
breakpoint.set(path, name, threadKeys, flagsByte, comment);
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
protected static byte computeFlagsByte(boolean enabled, Collection<TraceBreakpointKind> kinds) {
|
||||
byte flags = 0;
|
||||
for (TraceBreakpointKind k : kinds) {
|
||||
flags |= k.getBits();
|
||||
}
|
||||
if (enabled) {
|
||||
flags |= ENABLED_MASK;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
protected void doSetFlags(boolean enabled, Collection<TraceBreakpointKind> kinds) {
|
||||
this.flagsByte = computeFlagsByte(enabled, kinds);
|
||||
this.kinds.clear();
|
||||
this.kinds.addAll(kinds);
|
||||
this.enabled = enabled;
|
||||
// Msg.debug(this,
|
||||
// "trace: breakpoint " + this + " enabled=" + enabled + ", because doSetFlags");
|
||||
update(FLAGS_COLUMN);
|
||||
}
|
||||
|
||||
protected void doSetEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
// Msg.debug(this,
|
||||
// "trace: breakpoint " + this + " enabled=" + enabled + ", because doSetEnabled");
|
||||
if (enabled) {
|
||||
flagsByte |= ENABLED_MASK;
|
||||
}
|
||||
else {
|
||||
flagsByte &= ~ENABLED_MASK;
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
}
|
||||
|
||||
protected void doSetEmuEnabled(boolean emuEnabled) {
|
||||
this.emuEnabled = emuEnabled;
|
||||
if (emuEnabled) {
|
||||
flagsByte |= EMU_ENABLED_MASK;
|
||||
}
|
||||
else {
|
||||
flagsByte &= ~EMU_ENABLED_MASK;
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
}
|
||||
|
||||
protected void doSetKinds(Collection<TraceBreakpointKind> kinds) {
|
||||
for (TraceBreakpointKind k : TraceBreakpointKind.values()) {
|
||||
if (kinds.contains(k)) {
|
||||
this.flagsByte |= k.getBits();
|
||||
this.kinds.add(k);
|
||||
}
|
||||
else {
|
||||
this.flagsByte &= ~k.getBits();
|
||||
this.kinds.remove(k);
|
||||
}
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(long snap, boolean enabled) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
doSetEnabled(enabled);
|
||||
}
|
||||
space.trace
|
||||
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(long snap) {
|
||||
// NB. Only object mode supports per-snap enablement
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuEnabled(long snap, boolean enabled) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
doSetEmuEnabled(enabled);
|
||||
}
|
||||
space.trace
|
||||
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmuEnabled(long snap) {
|
||||
// NB. Only object mode support per-snap emu-enablement
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return emuEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKinds(long snap, Collection<TraceBreakpointKind> kinds) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
doSetKinds(kinds);
|
||||
}
|
||||
space.trace
|
||||
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceBreakpointKind> getKinds(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return kindsView;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(long snap, String comment) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
this.comment = comment;
|
||||
update(COMMENT_COLUMN);
|
||||
}
|
||||
space.trace
|
||||
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuSleigh(long snap, String emuSleigh) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
if (emuSleigh == null || SleighUtils.UNCONDITIONAL_BREAK.equals(emuSleigh)) {
|
||||
this.emuSleigh = null;
|
||||
}
|
||||
else {
|
||||
this.emuSleigh = emuSleigh.trim();
|
||||
}
|
||||
update(SLEIGH_COLUMN);
|
||||
}
|
||||
space.trace
|
||||
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmuSleigh(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return emuSleigh == null || emuSleigh.isBlank() ? SleighUtils.UNCONDITIONAL_BREAK
|
||||
: emuSleigh;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
space.deleteBreakpoint(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
if (snap <= lifespan.lmin()) {
|
||||
space.deleteBreakpoint(this);
|
||||
}
|
||||
else if (snap <= lifespan.lmax()) {
|
||||
doSetLifespan(lifespan.withMax(snap - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return lifespan.contains(snap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive(Lifespan span) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return lifespan.intersects(span);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,54 +19,55 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.target.*;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointSpec;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.iface.TraceObjectTogglable;
|
||||
import ghidra.trace.model.target.iface.TraceTogglable;
|
||||
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
|
||||
import ghidra.trace.model.target.path.PathFilter;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.*;
|
||||
import ghidra.trace.model.thread.TraceProcess;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.*;
|
||||
import ghidra.util.LockHold;
|
||||
|
||||
public class DBTraceObjectBreakpointLocation
|
||||
implements TraceObjectBreakpointLocation, DBTraceObjectInterface {
|
||||
public class DBTraceBreakpointLocation
|
||||
implements TraceBreakpointLocation, DBTraceObjectInterface {
|
||||
|
||||
protected static class BreakpointChangeTranslator extends Translator<TraceBreakpoint> {
|
||||
protected static class BreakpointChangeTranslator extends Translator<TraceBreakpointLocation> {
|
||||
private static final Map<TraceObjectSchema, Set<String>> KEYS_BY_SCHEMA =
|
||||
new WeakHashMap<>();
|
||||
|
||||
private final Set<String> keys;
|
||||
|
||||
protected BreakpointChangeTranslator(DBTraceObject object, TraceBreakpoint iface) {
|
||||
protected BreakpointChangeTranslator(DBTraceObject object, TraceBreakpointLocation iface) {
|
||||
super(KEY_RANGE, object, iface);
|
||||
TraceObjectSchema schema = object.getSchema();
|
||||
synchronized (KEYS_BY_SCHEMA) {
|
||||
keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of(
|
||||
schema.checkAliasedAttribute(KEY_RANGE),
|
||||
schema.checkAliasedAttribute(KEY_DISPLAY),
|
||||
schema.checkAliasedAttribute(TraceObjectTogglable.KEY_ENABLED),
|
||||
schema.checkAliasedAttribute(TraceTogglable.KEY_ENABLED),
|
||||
schema.checkAliasedAttribute(KEY_COMMENT)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TraceEvent<TraceBreakpoint, Void> getAddedType() {
|
||||
protected TraceEvent<TraceBreakpointLocation, Void> getAddedType() {
|
||||
return TraceEvents.BREAKPOINT_ADDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TraceEvent<TraceBreakpoint, Lifespan> getLifespanChangedType() {
|
||||
protected TraceEvent<TraceBreakpointLocation, Lifespan> getLifespanChangedType() {
|
||||
return TraceEvents.BREAKPOINT_LIFESPAN_CHANGED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TraceEvent<TraceBreakpoint, Void> getChangedType() {
|
||||
protected TraceEvent<TraceBreakpointLocation, Void> getChangedType() {
|
||||
return TraceEvents.BREAKPOINT_CHANGED;
|
||||
}
|
||||
|
||||
|
@ -76,7 +77,7 @@ public class DBTraceObjectBreakpointLocation
|
|||
}
|
||||
|
||||
@Override
|
||||
protected TraceEvent<TraceBreakpoint, Void> getDeletedType() {
|
||||
protected TraceEvent<TraceBreakpointLocation, Void> getDeletedType() {
|
||||
return TraceEvents.BREAKPOINT_DELETED;
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +85,7 @@ public class DBTraceObjectBreakpointLocation
|
|||
private final DBTraceObject object;
|
||||
private final BreakpointChangeTranslator translator;
|
||||
|
||||
public DBTraceObjectBreakpointLocation(DBTraceObject object) {
|
||||
public DBTraceBreakpointLocation(DBTraceObject object) {
|
||||
this.object = object;
|
||||
|
||||
translator = new BreakpointChangeTranslator(object, this);
|
||||
|
@ -107,9 +108,7 @@ public class DBTraceObjectBreakpointLocation
|
|||
|
||||
@Override
|
||||
public void setName(long snap, String name) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
setName(Lifespan.nowOn(snap), name);
|
||||
}
|
||||
setName(Lifespan.nowOn(snap), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -121,7 +120,7 @@ public class DBTraceObjectBreakpointLocation
|
|||
return display;
|
||||
}
|
||||
TraceObject spec =
|
||||
object.findCanonicalAncestorsInterface(TraceObjectBreakpointSpec.class)
|
||||
object.findCanonicalAncestorsInterface(TraceBreakpointSpec.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (spec == null) {
|
||||
|
@ -169,21 +168,19 @@ public class DBTraceObjectBreakpointLocation
|
|||
|
||||
@Override
|
||||
public void setEnabled(Lifespan lifespan, boolean enabled) {
|
||||
object.setValue(lifespan, TraceObjectTogglable.KEY_ENABLED, enabled);
|
||||
object.setValue(lifespan, TraceTogglable.KEY_ENABLED, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(long snap, boolean enabled) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
setEnabled(Lifespan.nowOn(snap), enabled);
|
||||
}
|
||||
setEnabled(Lifespan.nowOn(snap), enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(long snap) {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
Boolean locEn = TraceObjectInterfaceUtils.getValue(object, snap,
|
||||
TraceObjectTogglable.KEY_ENABLED, Boolean.class, null);
|
||||
TraceTogglable.KEY_ENABLED, Boolean.class, null);
|
||||
if (locEn != null) {
|
||||
return locEn && getSpecification().isEnabled(snap);
|
||||
}
|
||||
|
@ -191,31 +188,6 @@ public class DBTraceObjectBreakpointLocation
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKinds(Lifespan lifespan, Collection<TraceBreakpointKind> kinds) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
TraceObjectBreakpointSpec spec = getSpecification();
|
||||
if (spec.getObject() != this.getObject()) {
|
||||
throw new UnsupportedOperationException("Set via the specification instead");
|
||||
}
|
||||
spec.setKinds(lifespan, kinds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKinds(long snap, Collection<TraceBreakpointKind> kinds) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
setKinds(Lifespan.nowOn(snap), kinds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceBreakpointKind> getKinds(long snap) {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return getSpecification().getKinds(snap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceThread> getThreads(long snap) {
|
||||
// TODO: Delete this? It's sort of deprecated out the gate anyway....
|
||||
|
@ -223,17 +195,17 @@ public class DBTraceObjectBreakpointLocation
|
|||
TraceObjectSchema schema = manager.getRootSchema();
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
Set<TraceThread> threads =
|
||||
object.queryAncestorsInterface(Lifespan.at(snap), TraceObjectThread.class)
|
||||
object.queryAncestorsInterface(Lifespan.at(snap), TraceThread.class)
|
||||
.collect(Collectors.toSet());
|
||||
if (!threads.isEmpty()) {
|
||||
return threads;
|
||||
}
|
||||
|
||||
PathFilter procFilter = schema.searchFor(TraceObjectProcess.class, false);
|
||||
PathFilter procFilter = schema.searchFor(TraceProcess.class, false);
|
||||
Lifespan lifespan = Lifespan.at(snap);
|
||||
return object.getAncestorsRoot(lifespan, procFilter)
|
||||
.flatMap(proc -> proc.getSource(object)
|
||||
.querySuccessorsInterface(lifespan, TraceObjectThread.class, true))
|
||||
.querySuccessorsInterface(lifespan, TraceThread.class, true))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
@ -245,9 +217,7 @@ public class DBTraceObjectBreakpointLocation
|
|||
|
||||
@Override
|
||||
public void setComment(long snap, String comment) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
setComment(Lifespan.nowOn(snap), comment);
|
||||
}
|
||||
setComment(Lifespan.nowOn(snap), comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -258,11 +228,11 @@ public class DBTraceObjectBreakpointLocation
|
|||
if (!comment.isBlank()) {
|
||||
return comment;
|
||||
}
|
||||
TraceObjectBreakpointSpec spec = getSpecification();
|
||||
TraceBreakpointSpec spec = getSpecification();
|
||||
if (spec == null) {
|
||||
return "";
|
||||
}
|
||||
return spec.getExpression(snap);
|
||||
return spec.getComment(snap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,20 +310,20 @@ public class DBTraceObjectBreakpointLocation
|
|||
return object;
|
||||
}
|
||||
|
||||
public TraceObjectBreakpointSpec getOrCreateSpecification() {
|
||||
return object.queryOrCreateCanonicalAncestorInterface(TraceObjectBreakpointSpec.class);
|
||||
public TraceBreakpointSpec getOrCreateSpecification() {
|
||||
return object.queryOrCreateCanonicalAncestorInterface(TraceBreakpointSpec.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceObjectBreakpointSpec getSpecification() {
|
||||
public TraceBreakpointSpec getSpecification() {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return object.queryCanonicalAncestorsInterface(TraceObjectBreakpointSpec.class)
|
||||
return object.queryCanonicalAncestorsInterface(TraceBreakpointSpec.class)
|
||||
.findAny()
|
||||
.orElseThrow();
|
||||
}
|
||||
}
|
||||
|
||||
public TraceAddressSpace getTraceAddressSpace(long snap) {
|
||||
public AddressSpace getAddressSpace(long snap) {
|
||||
return spaceForValue(snap, KEY_RANGE);
|
||||
}
|
||||
|
|
@ -17,146 +17,89 @@ package ghidra.trace.database.breakpoint;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
|
||||
import db.DBHandle;
|
||||
import ghidra.framework.data.OpenMode;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager;
|
||||
import ghidra.trace.database.space.DBTraceDelegatingManager;
|
||||
import ghidra.trace.database.thread.DBTraceThreadManager;
|
||||
import ghidra.trace.database.DBTraceManager;
|
||||
import ghidra.trace.database.target.DBTraceObjectManager;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DBTraceBreakpointManager
|
||||
extends AbstractDBTraceSpaceBasedManager<DBTraceBreakpointSpace>
|
||||
implements TraceBreakpointManager, DBTraceDelegatingManager<DBTraceBreakpointSpace> {
|
||||
protected static final String NAME = "Breakpoint";
|
||||
public class DBTraceBreakpointManager implements TraceBreakpointManager, DBTraceManager {
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTrace trace;
|
||||
protected final DBTraceObjectManager objectManager;
|
||||
|
||||
public DBTraceBreakpointManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, Language baseLanguage, DBTrace trace,
|
||||
DBTraceThreadManager threadManager) throws VersionException, IOException {
|
||||
super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager);
|
||||
|
||||
loadSpaces();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceBreakpointSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
TaskMonitor monitor, DBTrace trace, DBTraceObjectManager objectManager)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceBreakpointSpace(this, dbh, space, ent);
|
||||
this.lock = lock;
|
||||
this.trace = trace;
|
||||
this.objectManager = objectManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DBTraceBreakpointSpace createRegisterSpace(AddressSpace space, TraceThread thread,
|
||||
DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
public void dbError(IOException e) {
|
||||
trace.dbError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceBreakpointSpace getForSpace(AddressSpace space, boolean createIfAbsent) {
|
||||
return super.getForSpace(space, createIfAbsent);
|
||||
public void invalidateCache(boolean all) {
|
||||
// NOTE: This is only a wrapper around the object manager
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock readLock() {
|
||||
return lock.readLock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock writeLock() {
|
||||
return lock.writeLock();
|
||||
}
|
||||
|
||||
protected void checkDuplicatePath(TraceBreakpoint ignore, String path, Lifespan lifespan)
|
||||
throws DuplicateNameException {
|
||||
for (TraceBreakpoint pc : getBreakpointsByPath(path)) {
|
||||
if (pc == ignore) {
|
||||
continue;
|
||||
}
|
||||
if (!pc.isAlive(lifespan)) {
|
||||
continue;
|
||||
}
|
||||
throw new DuplicateNameException("A breakpoint having path '" + path +
|
||||
"' already exists within an overlapping snap");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceBreakpoint addBreakpoint(String path, Lifespan lifespan, AddressRange range,
|
||||
public TraceBreakpointLocation addBreakpoint(String path, Lifespan lifespan, AddressRange range,
|
||||
Collection<TraceThread> threads, Collection<TraceBreakpointKind> kinds, boolean enabled,
|
||||
String comment) throws DuplicateNameException {
|
||||
if (trace.getObjectManager().hasSchema()) {
|
||||
return trace.getObjectManager()
|
||||
.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment);
|
||||
}
|
||||
checkDuplicatePath(null, path, lifespan);
|
||||
return delegateWrite(range.getAddressSpace(),
|
||||
m -> m.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment));
|
||||
return objectManager.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceBreakpoint> getAllBreakpoints() {
|
||||
if (trace.getObjectManager().hasSchema()) {
|
||||
return trace.getObjectManager().getAllObjects(TraceObjectBreakpointLocation.class);
|
||||
}
|
||||
return delegateCollection(getActiveMemorySpaces(), m -> m.getAllBreakpoints());
|
||||
public Collection<? extends TraceBreakpointSpec> getAllBreakpointSpecifications() {
|
||||
return objectManager.getAllObjects(TraceBreakpointSpec.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceBreakpoint> getBreakpointsByPath(String path) {
|
||||
if (trace.getObjectManager().hasSchema()) {
|
||||
return trace.getObjectManager()
|
||||
.getObjectsByPath(path, TraceObjectBreakpointLocation.class);
|
||||
}
|
||||
return delegateCollection(getActiveMemorySpaces(), m -> m.getBreakpointsByPath(path));
|
||||
public Collection<? extends TraceBreakpointLocation> getAllBreakpointLocations() {
|
||||
return objectManager.getAllObjects(TraceBreakpointLocation.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceBreakpoint getPlacedBreakpointByPath(long snap, String path) {
|
||||
if (trace.getObjectManager().hasSchema()) {
|
||||
return trace.getObjectManager()
|
||||
.getObjectByPath(snap, path, TraceObjectBreakpointLocation.class);
|
||||
}
|
||||
try (LockHold hold = LockHold.lock(lock.readLock())) {
|
||||
return getBreakpointsByPath(path).stream()
|
||||
.filter(b -> b.isValid(snap))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
}
|
||||
public Collection<? extends TraceBreakpointSpec> getBreakpointSpecificationsByPath(
|
||||
String path) {
|
||||
return objectManager.getObjectsByPath(path, TraceBreakpointSpec.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceBreakpoint> getBreakpointsAt(long snap, Address address) {
|
||||
if (trace.getObjectManager().hasSchema()) {
|
||||
return trace.getObjectManager()
|
||||
.getObjectsContaining(snap, address,
|
||||
TraceObjectBreakpointLocation.KEY_RANGE,
|
||||
TraceObjectBreakpointLocation.class);
|
||||
}
|
||||
return delegateRead(address.getAddressSpace(), m -> m.getBreakpointsAt(snap, address),
|
||||
Collections.emptyList());
|
||||
public Collection<? extends TraceBreakpointLocation> getBreakpointLocationsByPath(String path) {
|
||||
return objectManager.getObjectsByPath(path, TraceBreakpointLocation.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceBreakpoint> getBreakpointsIntersecting(Lifespan span,
|
||||
public TraceBreakpointLocation getPlacedBreakpointByPath(long snap, String path) {
|
||||
return objectManager.getObjectByPath(snap, path, TraceBreakpointLocation.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceBreakpointLocation> getBreakpointsAt(long snap,
|
||||
Address address) {
|
||||
return objectManager.getObjectsContaining(snap, address, TraceBreakpointLocation.KEY_RANGE,
|
||||
TraceBreakpointLocation.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceBreakpointLocation> getBreakpointsIntersecting(Lifespan span,
|
||||
AddressRange range) {
|
||||
if (trace.getObjectManager().hasSchema()) {
|
||||
return trace.getObjectManager()
|
||||
.getObjectsIntersecting(span, range,
|
||||
TraceObjectBreakpointLocation.KEY_RANGE,
|
||||
TraceObjectBreakpointLocation.class);
|
||||
}
|
||||
return delegateRead(range.getAddressSpace(), m -> m.getBreakpointsIntersecting(span, range),
|
||||
Collections.emptyList());
|
||||
return objectManager.getObjectsIntersecting(span, range, TraceBreakpointLocation.KEY_RANGE,
|
||||
TraceBreakpointLocation.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,138 +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.breakpoint;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
|
||||
import db.DBHandle;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace;
|
||||
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
|
||||
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
|
||||
import ghidra.trace.database.space.DBTraceSpaceBased;
|
||||
import ghidra.trace.database.thread.DBTraceThread;
|
||||
import ghidra.trace.database.thread.DBTraceThreadManager;
|
||||
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.database.DBCachedObjectIndex;
|
||||
import ghidra.util.database.DBCachedObjectStoreFactory;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
public class DBTraceBreakpointSpace implements DBTraceSpaceBased {
|
||||
protected final DBTraceBreakpointManager manager;
|
||||
protected final DBHandle dbh;
|
||||
protected final AddressSpace space;
|
||||
protected final ReadWriteLock lock;
|
||||
protected final DBTrace trace;
|
||||
|
||||
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint> breakpointMapSpace;
|
||||
protected final DBCachedObjectIndex<String, DBTraceBreakpoint> breakpointsByPath;
|
||||
protected final Collection<TraceBreakpoint> breakpointView;
|
||||
|
||||
public DBTraceBreakpointSpace(DBTraceBreakpointManager manager, DBHandle dbh,
|
||||
AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
|
||||
this.manager = manager;
|
||||
this.dbh = dbh;
|
||||
this.space = space;
|
||||
this.lock = manager.getLock();
|
||||
this.trace = manager.getTrace();
|
||||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
|
||||
long threadKey = ent.getThreadKey();
|
||||
assert threadKey == -1; // No breakpoints on registers
|
||||
breakpointMapSpace =
|
||||
new DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint>(
|
||||
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);
|
||||
breakpointView = Collections.unmodifiableCollection(breakpointMapSpace.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressSpace getAddressSpace() {
|
||||
return space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceThread getThread() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected DBTraceBreakpoint addBreakpoint(String path, Lifespan lifespan, AddressRange range,
|
||||
Collection<TraceThread> threads, Collection<TraceBreakpointKind> kinds, boolean enabled,
|
||||
String comment) {
|
||||
// NOTE: thread here is not about address/register spaces.
|
||||
// It's about which thread to trap
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
DBTraceThreadManager threadManager = trace.getThreadManager();
|
||||
for (TraceThread t : threads) {
|
||||
threadManager.assertIsMine(t);
|
||||
}
|
||||
DBTraceBreakpoint breakpoint =
|
||||
breakpointMapSpace.put(new ImmutableTraceAddressSnapRange(range, lifespan), null);
|
||||
breakpoint.set(path, path, threads, kinds, enabled, true, comment);
|
||||
trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceEvents.BREAKPOINT_ADDED, this, breakpoint));
|
||||
return breakpoint;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<? extends DBTraceBreakpoint> getAllBreakpoints() {
|
||||
return breakpointMapSpace.values();
|
||||
}
|
||||
|
||||
public Collection<? extends DBTraceBreakpoint> getBreakpointsByPath(String name) {
|
||||
return Collections.unmodifiableCollection(breakpointsByPath.get(name));
|
||||
}
|
||||
|
||||
public Collection<? extends DBTraceBreakpoint> getBreakpointsAt(long snap, Address address) {
|
||||
return Collections.unmodifiableCollection(
|
||||
breakpointMapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).values());
|
||||
}
|
||||
|
||||
public Collection<? extends DBTraceBreakpoint> getBreakpointsIntersecting(Lifespan span,
|
||||
AddressRange range) {
|
||||
return Collections.unmodifiableCollection(breakpointMapSpace.reduce(
|
||||
TraceAddressSnapRangeQuery.intersecting(range, span)).orderedValues());
|
||||
}
|
||||
|
||||
public void deleteBreakpoint(DBTraceBreakpoint breakpoint) {
|
||||
breakpointMapSpace.deleteData(breakpoint);
|
||||
trace.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_DELETED, this, breakpoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCache() {
|
||||
breakpointMapSpace.invalidateCache();
|
||||
}
|
||||
}
|
|
@ -18,8 +18,7 @@ package ghidra.trace.database.breakpoint;
|
|||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.trace.database.target.DBTraceObject;
|
||||
import ghidra.trace.database.target.DBTraceObjectInterface;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
|
@ -28,17 +27,15 @@ import ghidra.trace.model.breakpoint.*;
|
|||
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.iface.TraceObjectInterface;
|
||||
import ghidra.trace.model.target.iface.TraceObjectTogglable;
|
||||
import ghidra.trace.model.target.iface.TraceTogglable;
|
||||
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.util.*;
|
||||
import ghidra.trace.util.TraceChangeRecord;
|
||||
import ghidra.trace.util.TraceEvents;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public class DBTraceObjectBreakpointSpec
|
||||
implements TraceObjectBreakpointSpec, DBTraceObjectInterface {
|
||||
public class DBTraceBreakpointSpec implements TraceBreakpointSpec, DBTraceObjectInterface {
|
||||
private static final Map<TraceObjectSchema, Set<String>> KEYS_BY_SCHEMA = new WeakHashMap<>();
|
||||
|
||||
private final DBTraceObject object;
|
||||
|
@ -46,13 +43,13 @@ public class DBTraceObjectBreakpointSpec
|
|||
|
||||
private TraceBreakpointKindSet kinds = TraceBreakpointKindSet.of();
|
||||
|
||||
public DBTraceObjectBreakpointSpec(DBTraceObject object) {
|
||||
public DBTraceBreakpointSpec(DBTraceObject object) {
|
||||
this.object = object;
|
||||
TraceObjectSchema schema = object.getSchema();
|
||||
synchronized (KEYS_BY_SCHEMA) {
|
||||
keys = KEYS_BY_SCHEMA.computeIfAbsent(schema,
|
||||
s -> Set.of(schema.checkAliasedAttribute(TraceObjectBreakpointSpec.KEY_KINDS),
|
||||
schema.checkAliasedAttribute(TraceObjectTogglable.KEY_ENABLED)));
|
||||
s -> Set.of(schema.checkAliasedAttribute(KEY_KINDS),
|
||||
schema.checkAliasedAttribute(TraceTogglable.KEY_ENABLED)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,51 +63,35 @@ public class DBTraceObjectBreakpointSpec
|
|||
return object.getCanonicalPath().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(Lifespan lifespan, String name) {
|
||||
object.setValue(lifespan, KEY_DISPLAY, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(long snap, String name) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
object.setValue(Lifespan.nowOn(snap), TraceObjectInterface.KEY_DISPLAY, name);
|
||||
}
|
||||
setName(Lifespan.nowOn(snap), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(long snap) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectInterface.KEY_DISPLAY,
|
||||
String.class, "");
|
||||
return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressRange getRange(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMinAddress(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
public void setEnabled(Lifespan lifespan, boolean enabled) {
|
||||
object.setValue(lifespan, TraceTogglable.KEY_ENABLED, enabled ? true : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(long snap, boolean enabled) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
object.setValue(Lifespan.nowOn(snap), TraceObjectTogglable.KEY_ENABLED,
|
||||
enabled ? true : null);
|
||||
}
|
||||
setEnabled(Lifespan.nowOn(snap), enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(long snap) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, snap,
|
||||
TraceObjectTogglable.KEY_ENABLED, Boolean.class, false);
|
||||
TraceTogglable.KEY_ENABLED, Boolean.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,8 +99,7 @@ public class DBTraceObjectBreakpointSpec
|
|||
// TODO: More efficient encoding
|
||||
// TODO: Target-Trace mapping is implied by encoded name. Seems bad.
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
object.setValue(lifespan, TraceObjectBreakpointSpec.KEY_KINDS,
|
||||
TraceBreakpointKindSet.encode(kinds));
|
||||
object.setValue(lifespan, KEY_KINDS, TraceBreakpointKindSet.encode(kinds));
|
||||
this.kinds = TraceBreakpointKindSet.copyOf(kinds);
|
||||
}
|
||||
}
|
||||
|
@ -133,8 +113,8 @@ public class DBTraceObjectBreakpointSpec
|
|||
|
||||
@Override
|
||||
public Set<TraceBreakpointKind> getKinds(long snap) {
|
||||
String kindsStr = TraceObjectInterfaceUtils.getValue(object, snap,
|
||||
TraceObjectBreakpointSpec.KEY_KINDS, String.class, null);
|
||||
String kindsStr =
|
||||
TraceObjectInterfaceUtils.getValue(object, snap, KEY_KINDS, String.class, null);
|
||||
if (kindsStr == null) {
|
||||
return kinds;
|
||||
}
|
||||
|
@ -149,43 +129,24 @@ public class DBTraceObjectBreakpointSpec
|
|||
|
||||
@Override
|
||||
public String getExpression(long snap) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, snap,
|
||||
TraceObjectBreakpointSpec.KEY_EXPRESSION, String.class, null);
|
||||
return TraceObjectInterfaceUtils.getValue(object, snap, KEY_EXPRESSION, String.class, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceThread> getThreads(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
public void setComment(Lifespan lifespan, String comment) {
|
||||
object.setValue(lifespan, KEY_COMMENT, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(long snap, String comment) {
|
||||
throw new UnsupportedOperationException("Set on a location instead");
|
||||
setComment(Lifespan.nowOn(snap), comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuEnabled(long snap, boolean enabled) {
|
||||
throw new UnsupportedOperationException("Set on a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmuEnabled(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuSleigh(long snap, String sleigh) {
|
||||
throw new UnsupportedOperationException("Set on a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmuSleigh(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, snap, KEY_COMMENT, String.class, "");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -217,15 +178,15 @@ public class DBTraceObjectBreakpointSpec
|
|||
return object;
|
||||
}
|
||||
|
||||
protected Collection<? extends TraceObjectBreakpointLocation> getLocations(Lifespan span) {
|
||||
protected Collection<? extends TraceBreakpointLocation> getLocations(Lifespan span) {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return object.querySuccessorsInterface(span, TraceObjectBreakpointLocation.class, true)
|
||||
return object.querySuccessorsInterface(span, TraceBreakpointLocation.class, true)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends TraceObjectBreakpointLocation> getLocations(long snap) {
|
||||
public Collection<? extends TraceBreakpointLocation> getLocations(long snap) {
|
||||
return getLocations(Lifespan.at(snap));
|
||||
}
|
||||
|
||||
|
@ -243,9 +204,9 @@ public class DBTraceObjectBreakpointSpec
|
|||
if (object.getCanonicalParent(affected.getMaxSnap()) == null) {
|
||||
return null; // Incomplete object
|
||||
}
|
||||
for (TraceObjectBreakpointLocation loc : getLocations(affected.getLifespan())) {
|
||||
DBTraceObjectBreakpointLocation dbLoc = (DBTraceObjectBreakpointLocation) loc;
|
||||
TraceAddressSpace space = dbLoc.getTraceAddressSpace(affected.getMinSnap());
|
||||
for (TraceBreakpointLocation loc : getLocations(affected.getLifespan())) {
|
||||
DBTraceBreakpointLocation dbLoc = (DBTraceBreakpointLocation) loc;
|
||||
AddressSpace space = dbLoc.getAddressSpace(affected.getMinSnap());
|
||||
TraceChangeRecord<?, ?> evt =
|
||||
new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, loc, null, null);
|
||||
object.getTrace().setChanged(evt);
|
|
@ -101,14 +101,7 @@ public class DBTraceRegisterContextManager
|
|||
@Override
|
||||
protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceRegisterContextSpace(this, dbh, space, ent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 DBTraceRegisterContextSpace(this, dbh, space, ent, thread);
|
||||
return new DBTraceRegisterContextSpace(this, dbh, space, ent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,7 +198,7 @@ public class DBTraceRegisterContextManager
|
|||
@Override
|
||||
public AddressSetView getRegisterValueAddressRanges(Language language, Register register,
|
||||
long snap) {
|
||||
return delegateAddressSet(getActiveMemorySpaces(),
|
||||
return delegateAddressSet(getActiveSpaces(),
|
||||
m -> m.getRegisterValueAddressRanges(language, register, snap));
|
||||
}
|
||||
|
||||
|
@ -218,8 +211,7 @@ public class DBTraceRegisterContextManager
|
|||
|
||||
@Override
|
||||
public boolean hasRegisterValue(Language language, Register register, long snap) {
|
||||
return delegateAny(getActiveMemorySpaces(),
|
||||
m -> m.hasRegisterValue(language, register, snap));
|
||||
return delegateAny(getActiveSpaces(), m -> m.hasRegisterValue(language, register, snap));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -39,7 +39,6 @@ import ghidra.trace.database.space.DBTraceSpaceBased;
|
|||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.context.TraceRegisterContextSpace;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.database.*;
|
||||
import ghidra.util.database.annot.*;
|
||||
|
@ -79,8 +78,6 @@ 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,13 +88,10 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
|||
new HashMap<>();
|
||||
|
||||
public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh,
|
||||
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread)
|
||||
throws VersionException, IOException {
|
||||
AddressSpace space, DBTraceSpaceEntry ent) 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();
|
||||
|
@ -105,8 +99,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
|||
|
||||
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
|
||||
|
||||
registerStore = factory.getOrCreateCachedStore(
|
||||
DBTraceUtils.tableName(TABLE_NAME, space, ent.getThreadKey(), ent.getFrameLevel()),
|
||||
registerStore = factory.getOrCreateCachedStore(DBTraceUtils.tableName(TABLE_NAME, space),
|
||||
DBTraceRegisterEntry.class, DBTraceRegisterEntry::new, true);
|
||||
|
||||
loadRegisterValueMaps();
|
||||
|
@ -125,28 +118,18 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTrace getTrace() {
|
||||
return trace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressSpace getAddressSpace() {
|
||||
return space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceThread getThread() {
|
||||
return thread;
|
||||
}
|
||||
|
||||
protected long getThreadKey() {
|
||||
TraceThread thread = getThread();
|
||||
return thread == null ? -1 : thread.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameLevel() {
|
||||
return frameLevel;
|
||||
}
|
||||
|
||||
protected String tableName(Language language, Register register) {
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space, getThreadKey(), getFrameLevel()) + "_" +
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space) + "_" +
|
||||
language.getLanguageID().getIdAsString() + "_" + register.getName();
|
||||
}
|
||||
|
||||
|
@ -154,9 +137,9 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
|
|||
Pair<Language, Register> lr) throws VersionException {
|
||||
String name = tableName(lr.getLeft(), lr.getRight());
|
||||
try {
|
||||
return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(),
|
||||
lock, space, thread, frameLevel, DBTraceRegisterContextEntry.class,
|
||||
DBTraceRegisterContextEntry::new);
|
||||
return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace,
|
||||
trace.getStoreFactory(), lock, space,
|
||||
DBTraceRegisterContextEntry.class, DBTraceRegisterContextEntry::new);
|
||||
}
|
||||
catch (IOException e) {
|
||||
manager.dbError(e);
|
||||
|
|
|
@ -158,12 +158,12 @@ public class DBTraceDataSettingsAdapter
|
|||
public class DBTraceDataSettingsSpace extends
|
||||
DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
|
||||
implements DBTraceDataSettingsOperations {
|
||||
public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory,
|
||||
ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel,
|
||||
public DBTraceDataSettingsSpace(String tableName, DBTrace trace,
|
||||
DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
|
||||
Class<DBTraceSettingsEntry> dataType,
|
||||
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
|
||||
throws VersionException, IOException {
|
||||
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory);
|
||||
super(tableName, trace, storeFactory, lock, space, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -187,17 +187,8 @@ public class DBTraceDataSettingsAdapter
|
|||
@Override
|
||||
protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
|
||||
throws VersionException, IOException {
|
||||
return new DBTraceDataSettingsSpace(
|
||||
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
|
||||
lock, space, null, 0, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
return new DBTraceDataSettingsSpace(tableName(space), trace, trace.getStoreFactory(), lock,
|
||||
space, dataType, dataFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue