GP-5194: Remove Deprecated 'Legacy mode' for DBTrace.

This commit is contained in:
Dan
2025-06-27 16:00:08 +00:00
parent 8367ac7354
commit 7e7c8a5e86
312 changed files with 5925 additions and 9830 deletions
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,16 +21,16 @@ import java.util.function.BiFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
import ghidra.debug.api.breakpoint.LogicalBreakpoint; import ghidra.debug.api.breakpoint.LogicalBreakpoint;
import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener;
import ghidra.debug.api.breakpoint.LogicalBreakpoint.State; import ghidra.debug.api.breakpoint.LogicalBreakpoint.State;
import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener;
import ghidra.framework.plugintool.ServiceInfo; import ghidra.framework.plugintool.ServiceInfo;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.util.CodeUnitLocation; import ghidra.program.util.CodeUnitLocation;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
@ServiceInfo( @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 * 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. * 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 * @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. * Get the collected logical breakpoints (at present) at the given location.
@@ -297,10 +297,10 @@ public interface DebuggerLogicalBreakpointService {
* *
* <p> * <p>
* If the given location refers to a static image, this behaves as in * If the given location refers to a static image, this behaves as in
* {@link #placeBreakpointAt(Program, Address, TraceBreakpointKind)}. If it refers to a trace * {@link #placeBreakpointAt(Program, Address, long, Collection, String)}. If it refers to a
* view, this behaves as in {@link #placeBreakpointAt(Trace, Address, TraceBreakpointKind)}, * trace view, this behaves as in *
* ignoring the view's current snapshot in favor of the present. The name is only saved for a * {@link #placeBreakpointAt(Trace, Address, long, Collection, String)}, ignoring the view's
* program breakpoint. * current snapshot in favor of the present. The name is only saved for a program breakpoint.
* *
* @param loc the location * @param loc the location
* @param length size of the breakpoint, may be ignored by debugger * @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 * Disable a collection of logical breakpoints on target, if applicable
* *
* @see #enableAll(Collection) * @see #enableAll(Collection, Trace)
* @param col the collection * @param col the collection
* @param trace a trace, if the command should be limited to the given trace * @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 * @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 * Delete, if possible, a collection of logical breakpoints on target, if applicable
* *
* @see #enableAll(Collection) * @see #enableAll(Collection, Trace)
* @param col the collection * @param col the collection
* @param trace a trace, if the command should be limited to the given trace * @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 * @return a future which completes when all associated specifications have been deleted
@@ -371,7 +371,7 @@ public interface DebuggerLogicalBreakpointService {
* @param col the trace breakpoints * @param col the trace breakpoints
* @return a future which completes when the command has been processed * @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 * Disable the given locations
@@ -379,7 +379,7 @@ public interface DebuggerLogicalBreakpointService {
* @param col the trace breakpoints * @param col the trace breakpoints
* @return a future which completes when the command has been processed * @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 * Delete the given locations
@@ -387,7 +387,7 @@ public interface DebuggerLogicalBreakpointService {
* @param col the trace breakpoints * @param col the trace breakpoints
* @return a future which completes when the command has been processed * @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 * 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 * 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. * 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 * @param loc a representative location
* @return the status message, or null * @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 * Generate an informational message when toggling the breakpoints at the given location
* *
* <p> * <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, * 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 * this should return null, since the usual behavior in that case is to prompt to place a new
* breakpoint. * breakpoint.
* *
* @see #generateStatusEnable(Collection) * @see #generateStatusEnable(Collection, Trace)
* @param loc the location * @param loc the location
* @return the status message, or null * @return the status message, or null
*/ */
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,11 +18,11 @@ package ghidra.debug.api.action;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.util.TraceAddressSpace;
/** /**
* The actual tracking logic for a location tracking spec * The actual tracking logic for a location tracking spec
@@ -73,8 +73,8 @@ public interface LocationTracker {
* @param coordinates the provider's current coordinates * @param coordinates the provider's current coordinates
* @return true if re-computation and "goto" is warranted * @return true if re-computation and "goto" is warranted
*/ */
boolean affectedByBytesChange(TraceAddressSpace space, boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
TraceAddressSnapRange range, DebuggerCoordinates coordinates); DebuggerCoordinates coordinates);
/** /**
* Check if the address should be recomputed given the indicated stack change * Check if the address should be recomputed given the indicated stack change
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,9 +20,8 @@ import javax.swing.Icon;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.options.SaveState; import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec; import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.model.TraceAddressSnapRange; 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 * A specification for automatic navigation of the dynamic listing
@@ -67,21 +66,13 @@ public interface LocationTrackingSpec {
* @param current the current coordinates * @param current the current coordinates
* @return true if the change affects the tracked address for the given 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) { DebuggerCoordinates current) {
if (space == null) { if (space == null) {
return false; return false;
} }
if (!space.getAddressSpace().isMemorySpace()) { if (!space.isMemorySpace() && !current.isRegisterSpace(space)) {
if (current.getThread() == null) { return false;
return false;
}
TraceMemorySpace memSpace = current.getTrace()
.getMemoryManager()
.getMemoryRegisterSpace(current.getThread(), current.getFrame(), false);
if (memSpace == null || memSpace.getAddressSpace() != space.getAddressSpace()) {
return false;
}
} }
if (!range.getLifespan().contains(current.getSnap())) { if (!range.getLifespan().contains(current.getSnap())) {
return false; return false;
@@ -28,8 +28,8 @@ import ghidra.program.model.listing.Bookmark;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import resources.MultiIcon; import resources.MultiIcon;
/** /**
@@ -471,6 +471,8 @@ public interface LogicalBreakpoint {
*/ */
INCONSISTENT_MIXED(Mode.MIXED, Consistency.INCONSISTENT, NAME_MARKER_INCON_MIX, ICON_MARKER_INCON_MIX); 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 Mode mode;
public final Consistency consistency; public final Consistency consistency;
public final String display; public final String display;
@@ -658,7 +660,7 @@ public interface LogicalBreakpoint {
* Get the sleigh injection when emulating this breakpoint * Get the sleigh injection when emulating this breakpoint
* *
* @return the sleigh injection * @return the sleigh injection
* @see TraceBreakpoint#getEmuSleigh() * @see TraceBreakpointLocation#getEmuSleigh(long)
*/ */
String getEmuSleigh(); String getEmuSleigh();
@@ -666,7 +668,7 @@ public interface LogicalBreakpoint {
* Set the sleigh injection when emulating this breakpoint * Set the sleigh injection when emulating this breakpoint
* *
* @param sleigh the sleigh injection * @param sleigh the sleigh injection
* @see TraceBreakpoint#setEmuSleigh(String) * @see TraceBreakpointLocation#setEmuSleigh(long,String)
*/ */
void setEmuSleigh(String sleigh); void setEmuSleigh(String sleigh);
@@ -699,7 +701,7 @@ public interface LogicalBreakpoint {
* *
* @return the set of trace breakpoints * @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. * 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 * @param trace the trace
* @return the set of trace breakpoints * @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. * Get the traces for which this logical breakpoint has an address.
* *
* <p> * <p>
* Note, this does not necessarily indicate that a {@link TraceBreakpoint} is present for each * Note, this does not necessarily indicate that a {@link TraceBreakpointLocation} is present
* trace, but rather that for each returned trace, the logical breakpoint can be mapped to an * for each trace, but rather that for each returned trace, the logical breakpoint can be mapped
* address in that trace. See {@link #getParticipatingTraces()}. * to an address in that trace. See {@link #getParticipatingTraces()}.
* *
* @return a copy of the set of traces * @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. * Get the traces for which this logical breakpoint has a trace breakpoint.
* *
* <p> * <p>
* Note, unlike {@link #getMappedTraces()}, this does indicate that a {@link TraceBreakpoint} is * Note, unlike {@link #getMappedTraces()}, this does indicate that a
* present for each trace. * {@link TraceBreakpointLocation} is present for each trace.
* *
* @return the set of traces * @return the set of traces
*/ */
@@ -779,7 +781,7 @@ public interface LogicalBreakpoint {
* @param loc the location * @param loc the location
* @return the state * @return the state
*/ */
State computeStateForLocation(TraceBreakpoint loc); State computeStateForLocation(TraceBreakpointLocation loc);
/** /**
* Compute the state for all involved traces and program. * Compute the state for all involved traces and program.
@@ -17,7 +17,7 @@ package ghidra.debug.api.breakpoint;
import java.util.Collection; import java.util.Collection;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public interface LogicalBreakpointsChangeListener { public interface LogicalBreakpointsChangeListener {
default void breakpointAdded(LogicalBreakpoint added) { 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.program.model.lang.RegisterValue;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceExecutionState; import ghidra.trace.model.TraceExecutionState;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.*;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
@@ -617,12 +616,12 @@ public interface Target {
* @param breakpoint the breakpoint * @param breakpoint the breakpoint
* @return true if valid * @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 * Delete the given breakpoint from the target
@@ -633,12 +632,13 @@ public interface Target {
* *
* @param breakpoint the breakpoint to delete * @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 * Toggle the given breakpoint on the target
@@ -651,7 +651,7 @@ public interface Target {
* @param breakpoint the breakpoint to toggle * @param breakpoint the breakpoint to toggle
* @param enabled true to enable, false to disable * @param enabled true to enable, false to disable
*/ */
void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled); void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled);
/** /**
* @see #forceTerminate() * @see #forceTerminate()
@@ -27,15 +27,16 @@ import ghidra.framework.model.*;
import ghidra.framework.options.SaveState; import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.model.address.AddressSpace;
import ghidra.trace.database.DBTraceContentHandler; import ghidra.trace.database.DBTraceContentHandler;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.program.TraceProgramView; 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.TraceObject;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.thread.TraceObjectThread;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.TraceSnapshot;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
@@ -315,36 +316,34 @@ public class DebuggerCoordinates {
return thread(trace.getThreadManager().getThread(thread.getKey())); return thread(trace.getThreadManager().getThread(thread.getKey()));
} }
private static KeyPath resolvePath(TraceThread thread, Integer frameLevel, private static KeyPath resolvePath(TraceThread thread, Integer frameLevel, TraceSchedule time) {
TraceSchedule time) { if (thread == null) {
if (thread instanceof TraceObjectThread tot) { return KeyPath.of();
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();
} }
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, private static KeyPath choose(KeyPath curPath, KeyPath newPath) {
KeyPath newPath) {
if (curPath == null) { if (curPath == null) {
return newPath; return newPath;
} }
@@ -525,9 +524,7 @@ public class DebuggerCoordinates {
if (object == null) { if (object == null) {
return null; return null;
} }
return object.queryCanonicalAncestorsInterface(TraceObjectThread.class) return object.queryCanonicalAncestorsInterface(TraceThread.class).findFirst().orElse(null);
.findFirst()
.orElse(null);
} }
private static Integer resolveFrame(Trace trace, KeyPath path) { private static Integer resolveFrame(Trace trace, KeyPath path) {
@@ -535,10 +532,9 @@ public class DebuggerCoordinates {
if (object == null) { if (object == null) {
return null; return null;
} }
TraceObjectStackFrame frame = TraceStackFrame frame = object.queryCanonicalAncestorsInterface(TraceStackFrame.class)
object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class) .findFirst()
.findFirst() .orElse(null);
.orElse(null);
return frame == null ? null : frame.getLevel(); return frame == null ? null : frame.getLevel();
} }
@@ -669,6 +665,11 @@ public class DebuggerCoordinates {
return registerContainer = object.findRegisterContainer(getFrame()); 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() { public synchronized long getViewSnap() {
if (viewSnap != null) { if (viewSnap != null) {
return viewSnap; return viewSnap;
@@ -53,7 +53,6 @@ import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.thread.TraceObjectThread;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.MathUtilities; import ghidra.util.MathUtilities;
@@ -1452,11 +1451,7 @@ public interface FlatDebuggerAPI {
} }
default ActionContext createContext(TraceThread thread) { default ActionContext createContext(TraceThread thread) {
if (thread instanceof TraceObjectThread objThread) { return createContext(thread.getObject());
return createContext(objThread.getObject());
}
return new DebuggerSingleObjectPathActionContext(
KeyPath.parse(thread.getPath()));
} }
default ActionContext createContext(Trace trace) { default ActionContext createContext(Trace trace) {
@@ -21,7 +21,7 @@ import java.util.Map;
import com.sun.jdi.*; import com.sun.jdi.*;
import ghidra.app.plugin.core.debug.client.tracermi.*; 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.DebugStatus;
import ghidra.dbg.jdi.manager.impl.JdiManagerImpl; import ghidra.dbg.jdi.manager.impl.JdiManagerImpl;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@@ -144,7 +144,7 @@ public class JdiConnector {
} }
public void registerRemoteMethod(JdiMethods methods, java.lang.reflect.Method m, String name) { 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) { if (annot == null) {
return; return;
} }
File diff suppressed because it is too large Load Diff
@@ -26,7 +26,7 @@ public class RmiMethodRegistry {
*/ */
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public static @interface TraceMethod { public static @interface TraceRmiMethod {
String action() default ""; String action() default "";
String display() 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.Method;
import java.lang.reflect.Parameter; 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.*;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; 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.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.*; 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.*;
import ghidra.trace.model.target.iface.*; import ghidra.trace.model.target.iface.*;
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; 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.*;
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext; import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; 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.trace.model.time.schedule.TraceSchedule.ScheduleForm;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@@ -186,12 +188,12 @@ public class TraceRmiTarget extends AbstractTarget {
} }
protected ScheduleForm getSupportedTimeFormByAttribute(TraceObject obj, long snap) { protected ScheduleForm getSupportedTimeFormByAttribute(TraceObject obj, long snap) {
TraceObject eventScope = obj.findSuitableInterface(TraceObjectEventScope.class); TraceObject eventScope = obj.findSuitableInterface(TraceEventScope.class);
if (eventScope == null) { if (eventScope == null) {
return null; return null;
} }
TraceObjectValue timeSupportStr = TraceObjectValue timeSupportStr =
eventScope.getAttribute(snap, TraceObjectEventScope.KEY_TIME_SUPPORT); eventScope.getAttribute(snap, TraceEventScope.KEY_TIME_SUPPORT);
if (timeSupportStr == null) { if (timeSupportStr == null) {
return null; return null;
} }
@@ -213,11 +215,7 @@ public class TraceRmiTarget extends AbstractTarget {
@Override @Override
public TraceExecutionState getThreadExecutionState(TraceThread thread) { public TraceExecutionState getThreadExecutionState(TraceThread thread) {
if (!(thread instanceof TraceObjectThread tot)) { return thread.getObject().getExecutionState(getSnap());
Msg.error(this, "Non-object thread with Trace RMI!");
return TraceExecutionState.ALIVE;
}
return tot.getObject().getExecutionState(getSnap());
} }
@Override @Override
@@ -226,7 +224,7 @@ public class TraceRmiTarget extends AbstractTarget {
if (object == null) { if (object == null) {
return null; return null;
} }
return object.queryCanonicalAncestorsInterface(TraceObjectThread.class) return object.queryCanonicalAncestorsInterface(TraceThread.class)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
@@ -237,7 +235,7 @@ public class TraceRmiTarget extends AbstractTarget {
if (object == null) { if (object == null) {
return null; return null;
} }
return object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class) return object.queryCanonicalAncestorsInterface(TraceStackFrame.class)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
@@ -303,7 +301,7 @@ public class TraceRmiTarget extends AbstractTarget {
return null; return null;
} }
TraceObjectValue attrEnabled = TraceObjectValue attrEnabled =
object.getAttribute(getSnap(), TraceObjectTogglable.KEY_ENABLED); object.getAttribute(getSnap(), TraceTogglable.KEY_ENABLED);
boolean enabled = attrEnabled != null && attrEnabled.getValue() instanceof Boolean b && b; boolean enabled = attrEnabled != null && attrEnabled.getValue() instanceof Boolean b && b;
return !enabled; return !enabled;
} }
@@ -549,7 +547,7 @@ public class TraceRmiTarget extends AbstractTarget {
} }
return schema return schema
.getInterfaces() .getInterfaces()
.contains(TraceObjectFocusScope.class) && .contains(TraceFocusScope.class) &&
!connection.getMethods().getByAction(ActionName.ACTIVATE).isEmpty(); !connection.getMethods().getByAction(ActionName.ACTIVATE).isEmpty();
} }
@@ -557,7 +555,7 @@ public class TraceRmiTarget extends AbstractTarget {
public KeyPath getFocus() { public KeyPath getFocus() {
TraceObjectValue focusVal = trace.getObjectManager() TraceObjectValue focusVal = trace.getObjectManager()
.getRootObject() .getRootObject()
.getAttribute(getSnap(), TraceObjectFocusScope.KEY_FOCUS); .getAttribute(getSnap(), TraceFocusScope.KEY_FOCUS);
if (focusVal == null || !focusVal.isObject()) { if (focusVal == null || !focusVal.isObject()) {
return null; return null;
} }
@@ -740,7 +738,7 @@ public class TraceRmiTarget extends AbstractTarget {
record ReadMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record ReadMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final ReadMemMatcher HAS_PROC_RANGE = new ReadMemMatcher(2, List.of( 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))); new TypeParamSpec("range", AddressRange.class)));
static final ReadMemMatcher HAS_RANGE = new ReadMemMatcher(1, List.of( static final ReadMemMatcher HAS_RANGE = new ReadMemMatcher(1, List.of(
new TypeParamSpec("range", AddressRange.class))); new TypeParamSpec("range", AddressRange.class)));
@@ -749,7 +747,7 @@ public class TraceRmiTarget extends AbstractTarget {
record WriteMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record WriteMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final WriteMemMatcher HAS_PROC_START_DATA = new WriteMemMatcher(2, List.of( 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("start", Address.class),
new TypeParamSpec("data", byte[].class))); new TypeParamSpec("data", byte[].class)));
static final WriteMemMatcher HAS_START_DATA = new WriteMemMatcher(1, List.of( 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 { record ReadRegsMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final ReadRegsMatcher HAS_CONTAINER = new ReadRegsMatcher(3, List.of( 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( 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); static final List<ReadRegsMatcher> ALL = matchers(HAS_CONTAINER, HAS_REGISTER);
} }
record WriteRegMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record WriteRegMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final WriteRegMatcher HAS_FRAME_NAME_VALUE = new WriteRegMatcher(3, List.of( 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("name", String.class),
new TypeParamSpec("value", byte[].class))); new TypeParamSpec("value", byte[].class)));
static final WriteRegMatcher HAS_THREAD_NAME_VALUE = new WriteRegMatcher(2, List.of( 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("name", String.class),
new TypeParamSpec("value", byte[].class))); new TypeParamSpec("value", byte[].class)));
static final WriteRegMatcher HAS_REG_VALUE = new WriteRegMatcher(1, List.of( 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))); new TypeParamSpec("value", byte[].class)));
static final List<WriteRegMatcher> ALL = matchers(HAS_FRAME_NAME_VALUE, HAS_REG_VALUE); static final List<WriteRegMatcher> ALL = matchers(HAS_FRAME_NAME_VALUE, HAS_REG_VALUE);
} }
record BreakExecMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record BreakExecMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final BreakExecMatcher HAS_PROC_ADDR_COND_CMDS = new BreakExecMatcher(8, List.of( 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 TypeParamSpec("address", Address.class),
new NameParamSpec("condition", String.class), new NameParamSpec("condition", String.class),
new NameParamSpec("commands", String.class))); new NameParamSpec("commands", String.class)));
static final BreakExecMatcher HAS_PROC_ADDR_COND = new BreakExecMatcher(7, List.of( 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 TypeParamSpec("address", Address.class),
new NameParamSpec("condition", String.class))); new NameParamSpec("condition", String.class)));
static final BreakExecMatcher HAS_PROC_ADDR_CMDS = new BreakExecMatcher(6, List.of( 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 TypeParamSpec("address", Address.class),
new NameParamSpec("commands", String.class))); new NameParamSpec("commands", String.class)));
static final BreakExecMatcher HAS_PROC_ADDR = new BreakExecMatcher(5, List.of( 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))); new TypeParamSpec("address", Address.class)));
static final BreakExecMatcher HAS_ADDR_COND_CMDS = new BreakExecMatcher(4, List.of( static final BreakExecMatcher HAS_ADDR_COND_CMDS = new BreakExecMatcher(4, List.of(
new TypeParamSpec("address", Address.class), 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 // TODO: Probably need a better way to deal with optional requirements
record BreakAccMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record BreakAccMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final BreakAccMatcher HAS_PROC_RNG_COND_CMDS = new BreakAccMatcher(8, List.of( 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 TypeParamSpec("range", AddressRange.class),
new NameParamSpec("condition", String.class), new NameParamSpec("condition", String.class),
new NameParamSpec("commands", String.class))); new NameParamSpec("commands", String.class)));
static final BreakAccMatcher HAS_PROC_RNG_COND = new BreakAccMatcher(7, List.of( 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 TypeParamSpec("range", AddressRange.class),
new NameParamSpec("condition", String.class))); new NameParamSpec("condition", String.class)));
static final BreakAccMatcher HAS_PROC_RNG_CMDS = new BreakAccMatcher(6, List.of( 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 TypeParamSpec("range", AddressRange.class),
new NameParamSpec("commands", String.class))); new NameParamSpec("commands", String.class)));
static final BreakAccMatcher HAS_PROC_RNG = new BreakAccMatcher(5, List.of( 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))); new TypeParamSpec("range", AddressRange.class)));
static final BreakAccMatcher HAS_RNG_COND_CMDS = new BreakAccMatcher(4, List.of( static final BreakAccMatcher HAS_RNG_COND_CMDS = new BreakAccMatcher(4, List.of(
new TypeParamSpec("range", AddressRange.class), new TypeParamSpec("range", AddressRange.class),
@@ -852,19 +850,19 @@ public class TraceRmiTarget extends AbstractTarget {
record DelBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record DelBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final DelBreakMatcher HAS_LOC = new DelBreakMatcher(2, List.of( 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( 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> ALL = matchers(HAS_LOC, HAS_SPEC);
static final List<DelBreakMatcher> SPEC = matchers(HAS_SPEC); static final List<DelBreakMatcher> SPEC = matchers(HAS_SPEC);
} }
record ToggleBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher { record ToggleBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
static final ToggleBreakMatcher HAS_LOC = new ToggleBreakMatcher(2, List.of( 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))); new TypeParamSpec("enabled", Boolean.class)));
static final ToggleBreakMatcher HAS_SPEC = new ToggleBreakMatcher(1, List.of( 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))); new TypeParamSpec("enabled", Boolean.class)));
static final List<ToggleBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC); static final List<ToggleBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
static final List<ToggleBreakMatcher> SPEC = matchers(HAS_SPEC); static final List<ToggleBreakMatcher> SPEC = matchers(HAS_SPEC);
@@ -1079,8 +1077,8 @@ public class TraceRmiTarget extends AbstractTarget {
} }
protected TraceObject getProcessForSpace(AddressSpace space) { protected TraceObject getProcessForSpace(AddressSpace space) {
List<TraceObjectProcess> processes = trace.getObjectManager() List<TraceProcess> processes = trace.getObjectManager()
.queryAllInterface(Lifespan.at(getSnap()), TraceObjectProcess.class) .queryAllInterface(Lifespan.at(getSnap()), TraceProcess.class)
.toList(); .toList();
if (processes.size() == 1) { if (processes.size() == 1) {
return processes.get(0).getObject(); return processes.get(0).getObject();
@@ -1089,11 +1087,10 @@ public class TraceRmiTarget extends AbstractTarget {
return null; return null;
} }
for (TraceMemoryRegion region : trace.getMemoryManager() for (TraceMemoryRegion region : trace.getMemoryManager()
.getRegionsIntersecting( .getRegionsIntersecting(Lifespan.at(getSnap()),
Lifespan.at(getSnap()),
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) { new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) {
TraceObject obj = ((TraceObjectMemoryRegion) region).getObject(); TraceObject obj = region.getObject();
return obj.findCanonicalAncestorsInterface(TraceObjectProcess.class) return obj.findCanonicalAncestorsInterface(TraceProcess.class)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
@@ -1207,11 +1204,7 @@ public class TraceRmiTarget extends AbstractTarget {
if (readRegs == null) { if (readRegs == null) {
return AsyncUtils.nil(); return AsyncUtils.nil();
} }
if (!(thread instanceof TraceObjectThread tot)) { TraceObject container = thread.getObject().findRegisterContainer(frame);
Msg.error(this, "Non-object trace with TraceRmi!");
return AsyncUtils.nil();
}
TraceObject container = tot.getObject().findRegisterContainer(frame);
if (container == null) { if (container == null) {
Msg.error(this, Msg.error(this,
"Cannot find register container for thread,frame: " + thread + "," + frame); "Cannot find register container for thread,frame: " + thread + "," + frame);
@@ -1229,8 +1222,7 @@ public class TraceRmiTarget extends AbstractTarget {
keys.add("[" + lower + "]"); keys.add("[" + lower + "]");
} }
Set<TraceObject> regs = container Set<TraceObject> regs = container
.findSuccessorsInterface(Lifespan.at(getSnap()), TraceObjectRegister.class, .findSuccessorsInterface(Lifespan.at(getSnap()), TraceRegister.class, true)
true)
.filter(p -> keys.contains(p.getLastEntry().getEntryKey().toLowerCase())) .filter(p -> keys.contains(p.getLastEntry().getEntryKey().toLowerCase()))
.map(r -> r.getDestination(null)) .map(r -> r.getDestination(null))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
@@ -1303,14 +1295,13 @@ public class TraceRmiTarget extends AbstractTarget {
return findRegister(container, filter, parent); return findRegister(container, filter, parent);
} }
protected FoundRegister findRegister(TraceObjectThread thread, int frame, protected FoundRegister findRegister(TraceThread thread, int frame, Register register) {
Register register) {
TraceObject container = thread.getObject().findRegisterContainer(frame); TraceObject container = thread.getObject().findRegisterContainer(frame);
if (container == null) { if (container == null) {
Msg.error(this, "No register container for thread=" + thread + ",frame=" + frame); Msg.error(this, "No register container for thread=" + thread + ",frame=" + frame);
return null; return null;
} }
PathFilter filter = container.getSchema().searchFor(TraceObjectRegister.class, true); PathFilter filter = container.getSchema().searchFor(TraceRegister.class, true);
return findRegister(container, filter, register); return findRegister(container, filter, register);
} }
@@ -1337,11 +1328,7 @@ public class TraceRmiTarget extends AbstractTarget {
if (writeReg == null) { if (writeReg == null) {
return AsyncUtils.nil(); return AsyncUtils.nil();
} }
if (!(thread instanceof TraceObjectThread tot)) { FoundRegister found = findRegister(thread, frameLevel, value.getRegister());
Msg.error(this, "Non-object trace with TraceRmi!");
return AsyncUtils.nil();
}
FoundRegister found = findRegister(tot, frameLevel, value.getRegister());
if (found == null) { if (found == null) {
Msg.warn(this, "Could not find register " + value.getRegister() + " in object model."); 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"); RemoteParameter paramThread = writeReg.params.get("thread");
if (paramThread != null) { if (paramThread != null) {
return writeReg.method.invokeAsync(Map.ofEntries( 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("name").name(), found.name()),
Map.entry(writeReg.params.get("value").name(), getBytes(value)))) Map.entry(writeReg.params.get("value").name(), getBytes(value))))
.toCompletableFuture() .toCompletableFuture()
@@ -1363,12 +1350,8 @@ public class TraceRmiTarget extends AbstractTarget {
if (paramFrame != null) { if (paramFrame != null) {
TraceStack stack = trace.getStackManager().getLatestStack(thread, getSnap()); TraceStack stack = trace.getStackManager().getLatestStack(thread, getSnap());
TraceStackFrame frame = stack.getFrame(getSnap(), frameLevel, false); 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( 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("name").name(), found.name()),
Map.entry(writeReg.params.get("value").name(), getBytes(value)))) Map.entry(writeReg.params.get("value").name(), getBytes(value))))
.toCompletableFuture() .toCompletableFuture()
@@ -1398,11 +1381,8 @@ public class TraceRmiTarget extends AbstractTarget {
if (register == null) { if (register == null) {
return false; return false;
} }
if (!(thread instanceof TraceObjectThread tot)) {
return false;
}
// May be primitive or object // May be primitive or object
FoundRegister found = findRegister(tot, frame, register); FoundRegister found = findRegister(thread, frame, register);
if (found == null) { if (found == null) {
return false; return false;
} }
@@ -1596,7 +1576,7 @@ public class TraceRmiTarget extends AbstractTarget {
} }
@Override @Override
public boolean isBreakpointValid(TraceBreakpoint breakpoint) { public boolean isBreakpointValid(TraceBreakpointLocation breakpoint) {
long snap = getSnap(); long snap = getSnap();
if (breakpoint.getName(snap).endsWith("emu-" + breakpoint.getMinAddress(snap))) { if (breakpoint.getName(snap).endsWith("emu-" + breakpoint.getMinAddress(snap))) {
return false; return false;
@@ -1607,7 +1587,7 @@ public class TraceRmiTarget extends AbstractTarget {
return true; return true;
} }
protected CompletableFuture<Void> deleteBreakpointSpecAsync(TraceObjectBreakpointSpec spec) { protected CompletableFuture<Void> deleteBreakpointSpecAsync(TraceBreakpointSpec spec) {
KeyPath path = spec.getObject().getCanonicalPath(); KeyPath path = spec.getObject().getCanonicalPath();
MatchedMethod delBreak = MatchedMethod delBreak =
matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.SPEC); 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? // 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(); KeyPath path = loc.getObject().getCanonicalPath();
MatchedMethod delBreak = MatchedMethod delBreak =
matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.ALL); matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.ALL);
@@ -1639,18 +1619,18 @@ public class TraceRmiTarget extends AbstractTarget {
} }
@Override @Override
public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpoint breakpoint) { public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint) {
if (breakpoint instanceof TraceObjectBreakpointLocation loc) { if (breakpoint instanceof TraceBreakpointLocation loc) {
return deleteBreakpointLocAsync(loc); return deleteBreakpointLocAsync(loc);
} }
if (breakpoint instanceof TraceObjectBreakpointSpec spec) { if (breakpoint instanceof TraceBreakpointSpec spec) {
return deleteBreakpointSpecAsync(spec); return deleteBreakpointSpecAsync(spec);
} }
Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint); Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint);
return AsyncUtils.nil(); return AsyncUtils.nil();
} }
protected CompletableFuture<Void> toggleBreakpointSpecAsync(TraceObjectBreakpointSpec spec, protected CompletableFuture<Void> toggleBreakpointSpecAsync(TraceBreakpointSpec spec,
boolean enabled) { boolean enabled) {
KeyPath path = spec.getObject().getCanonicalPath(); KeyPath path = spec.getObject().getCanonicalPath();
MatchedMethod toggleBreak = MatchedMethod toggleBreak =
@@ -1667,7 +1647,7 @@ public class TraceRmiTarget extends AbstractTarget {
.thenApply(__ -> null); .thenApply(__ -> null);
} }
protected CompletableFuture<Void> toggleBreakpointLocAsync(TraceObjectBreakpointLocation loc, protected CompletableFuture<Void> toggleBreakpointLocAsync(TraceBreakpointLocation loc,
boolean enabled) { boolean enabled) {
KeyPath path = loc.getObject().getCanonicalPath(); KeyPath path = loc.getObject().getCanonicalPath();
MatchedMethod toggleBreak = MatchedMethod toggleBreak =
@@ -1690,12 +1670,12 @@ public class TraceRmiTarget extends AbstractTarget {
} }
@Override @Override
public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpoint breakpoint, public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint,
boolean enabled) { boolean enabled) {
if (breakpoint instanceof TraceObjectBreakpointLocation loc) { if (breakpoint instanceof TraceBreakpointLocation loc) {
return toggleBreakpointLocAsync(loc, enabled); return toggleBreakpointLocAsync(loc, enabled);
} }
if (breakpoint instanceof TraceObjectBreakpointSpec spec) { if (breakpoint instanceof TraceBreakpointSpec spec) {
return toggleBreakpointSpecAsync(spec, enabled); return toggleBreakpointSpecAsync(spec, enabled);
} }
Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint); 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.RemoteMethod;
import ghidra.debug.api.tracermi.RemoteParameter; import ghidra.debug.api.tracermi.RemoteParameter;
import ghidra.framework.options.PropertyBoolean; import ghidra.framework.options.PropertyBoolean;
import ghidra.trace.model.target.iface.TraceObjectMethod.Param; import ghidra.trace.model.target.iface.TraceMethod.Param;
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.*;
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext; import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
@@ -343,16 +343,16 @@ public class PopulateDemoTrace extends GhidraScript {
*/ */
mainLabel = trace.getSymbolManager() mainLabel = trace.getSymbolManager()
.labels() .labels()
.create(snap, null, addr(0x00400000), "main", global, SourceType.USER_DEFINED); .create(snap, addr(0x00400000), "main", global, SourceType.USER_DEFINED);
cloneLabel = trace.getSymbolManager() cloneLabel = trace.getSymbolManager()
.labels() .labels()
.create(snap, null, addr(0x00400060), "clone", global, SourceType.USER_DEFINED); .create(snap, addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
childLabel = trace.getSymbolManager() childLabel = trace.getSymbolManager()
.labels() .labels()
.create(snap, null, addr(0x00400034), "child", global, SourceType.USER_DEFINED); .create(snap, addr(0x00400034), "child", global, SourceType.USER_DEFINED);
exitLabel = trace.getSymbolManager() exitLabel = trace.getSymbolManager()
.labels() .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 * 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.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.TraceObjectMemoryRegion; import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.modules.TraceObjectModule; import ghidra.trace.model.modules.TraceModule;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.util.TraceEvent; import ghidra.trace.util.TraceEvent;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
@@ -76,8 +76,8 @@ public class ByModuleAutoMapSpec implements AutoMapSpec {
@Override @Override
public boolean objectHasType(TraceObjectValue value) { public boolean objectHasType(TraceObjectValue value) {
return value.getParent().queryInterface(TraceObjectModule.class) != null || return value.getParent().queryInterface(TraceModule.class) != null ||
value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null; value.getParent().queryInterface(TraceMemoryRegion.class) != null;
} }
@Override @Override
@@ -29,7 +29,7 @@ import ghidra.debug.api.modules.RegionMapProposal;
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry; import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.trace.model.Trace; 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.model.target.TraceObjectValue;
import ghidra.trace.util.TraceEvent; import ghidra.trace.util.TraceEvent;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
@@ -61,7 +61,7 @@ public class ByRegionAutoMapSpec implements AutoMapSpec {
@Override @Override
public boolean objectHasType(TraceObjectValue value) { 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) { 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;
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry; import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.trace.database.module.TraceObjectSection;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.modules.TraceSection;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.util.TraceEvent; import ghidra.trace.util.TraceEvent;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
@@ -61,7 +61,7 @@ public class BySectionAutoMapSpec implements AutoMapSpec {
@Override @Override
public boolean objectHasType(TraceObjectValue value) { public boolean objectHasType(TraceObjectValue value) {
return value.getParent().queryInterface(TraceObjectSection.class) != null; return value.getParent().queryInterface(TraceSection.class) != null;
} }
@Override @Override
@@ -40,11 +40,13 @@ import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoConfigStateField; import ghidra.framework.plugintool.annotation.AutoConfigStateField;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.stack.TraceStack; 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.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.Msg; import ghidra.util.Msg;
@@ -60,10 +62,12 @@ public class DebuggerTrackLocationTrait {
public ForTrackingListener() { public ForTrackingListener() {
listenFor(TraceEvents.BYTES_CHANGED, this::registersChanged); 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) { byte[] oldValue, byte[] newValue) {
if (current.getView() == null || spec == null) { if (current.getView() == null || spec == null) {
// Should only happen during transitional times, if at all. // Should only happen during transitional times, if at all.
@@ -85,6 +89,42 @@ public class DebuggerTrackLocationTrait {
} }
doTrack(TrackCause.DB_CHANGE); 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.... // TODO: This may already be deprecated....
@@ -297,6 +337,9 @@ public class DebuggerTrackLocationTrait {
trackedLocation = newLocation; trackedLocation = newLocation;
locationTracked(); locationTracked();
} }
catch (TraceClosedException ex) {
// Silently continue
}
catch (Throwable ex) { catch (Throwable ex) {
Msg.error(this, "Error while computing location: " + ex); Msg.error(this, "Error while computing location: " + ex);
} }
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,10 +22,10 @@ import ghidra.debug.api.action.*;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.util.TraceAddressSpace;
public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTracker { public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTracker {
INSTANCE; INSTANCE;
@@ -77,8 +77,8 @@ public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTr
} }
@Override @Override
public boolean affectedByBytesChange(TraceAddressSpace space, public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
TraceAddressSnapRange range, DebuggerCoordinates coordinates) { DebuggerCoordinates coordinates) {
return false; return false;
} }
@@ -22,13 +22,13 @@ import ghidra.debug.api.action.*;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, LocationTracker { public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, LocationTracker {
INSTANCE; INSTANCE;
@@ -124,7 +124,7 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat
} }
@Override @Override
public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range, public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
DebuggerCoordinates coordinates) { DebuggerCoordinates coordinates) {
return false; return false;
} }
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,10 +22,10 @@ import ghidra.debug.api.action.*;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.util.TraceAddressSpace;
public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTracker { public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTracker {
INSTANCE; INSTANCE;
@@ -91,7 +91,7 @@ public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTrac
} }
@Override @Override
public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range, public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
DebuggerCoordinates coordinates) { DebuggerCoordinates coordinates) {
return BY_REG.affectedByBytesChange(space, range, 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.memory.TraceMemoryState;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, LocationTracker { public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, LocationTracker {
Register computeRegister(DebuggerCoordinates coordinates); Register computeRegister(DebuggerCoordinates coordinates);
@@ -102,18 +101,17 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, Loca
} }
@Override @Override
default boolean affectedByBytesChange(TraceAddressSpace space, default boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
TraceAddressSnapRange range, DebuggerCoordinates coordinates) { DebuggerCoordinates coordinates) {
if (!LocationTrackingSpec.changeIsCurrent(space, range, coordinates)) { if (!LocationTrackingSpec.changeIsCurrent(space, range, coordinates)) {
return false; return false;
} }
Register register = computeRegister(coordinates); Register register = computeRegister(coordinates);
AddressSpace as = space.getAddressSpace(); if (register == null) {
if (register == null || register.getAddressSpace() != as) {
return false; return false;
} }
AddressRange regRng = coordinates.getPlatform() AddressRange regRng = coordinates.getPlatform()
.getConventionalRegisterRange(as.isRegisterSpace() ? as : null, register); .getConventionalRegisterRange(space.isRegisterSpace() ? space : null, register);
return range.getRange().intersects(regRng); return range.getRange().intersects(regRng);
} }
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -28,13 +28,11 @@ import ghidra.framework.plugintool.ServiceProvider;
import ghidra.pcode.exec.*; import ghidra.pcode.exec.*;
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue; import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
import ghidra.pcode.exec.SleighUtils.AddressOf; import ghidra.pcode.exec.SleighUtils.AddressOf;
import ghidra.program.model.address.Address; import ghidra.program.model.address.*;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.util.TraceAddressSpace;
/** /**
* A tracking specification for the address of a given Sleigh expression * A tracking specification for the address of a given Sleigh expression
@@ -151,7 +149,7 @@ public class WatchLocationTrackingSpec implements LocationTrackingSpec {
} }
@Override @Override
public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range, public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
DebuggerCoordinates coordinates) { DebuggerCoordinates coordinates) {
return LocationTrackingSpec.changeIsCurrent(space, range, coordinates) && return LocationTrackingSpec.changeIsCurrent(space, range, coordinates) &&
(reads == null || reads.intersects(range.getX1(), range.getX2())); (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.pcode.exec.SleighUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public class BreakpointLocationRow { public class BreakpointLocationRow {
private final DebuggerBreakpointsProvider provider; 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.provider = provider;
this.loc = loc; this.loc = loc;
} }
@@ -116,7 +117,7 @@ public class BreakpointLocationRow {
return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh(getSnap())); return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh(getSnap()));
} }
public TraceBreakpoint getTraceBreakpoint() { public TraceBreakpointLocation getTraceBreakpoint() {
return loc; return loc;
} }
} }
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,7 +19,7 @@ import java.util.Collection;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import docking.DefaultActionContext; import docking.DefaultActionContext;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public class DebuggerBreakpointLocationsActionContext extends DefaultActionContext { public class DebuggerBreakpointLocationsActionContext extends DefaultActionContext {
private final Collection<BreakpointLocationRow> selection; private final Collection<BreakpointLocationRow> selection;
@@ -32,7 +32,7 @@ public class DebuggerBreakpointLocationsActionContext extends DefaultActionConte
return selection; return selection;
} }
public Collection<TraceBreakpoint> getLocations() { public Collection<TraceBreakpointLocation> getLocations() {
return selection.stream().map(row -> row.getTraceBreakpoint()).collect(Collectors.toList()); 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.MarkerLocation;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.database.ObjectKey; import ghidra.util.database.ObjectKey;
@@ -230,11 +230,13 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
protected static class BreakpointLocationTableModel protected static class BreakpointLocationTableModel
extends RowWrappedEnumeratedColumnTableModel< // extends RowWrappedEnumeratedColumnTableModel< //
BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, TraceBreakpoint> { BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, //
TraceBreakpointLocation> {
public BreakpointLocationTableModel(DebuggerBreakpointsProvider provider) { public BreakpointLocationTableModel(DebuggerBreakpointsProvider provider) {
super(provider.getTool(), "Locations", BreakpointLocationTableColumns.class, super(provider.getTool(), "Locations", BreakpointLocationTableColumns.class,
TraceBreakpoint::getObjectKey, loc -> new BreakpointLocationRow(provider, loc), TraceBreakpointLocation::getObjectKey,
loc -> new BreakpointLocationRow(provider, loc),
BreakpointLocationRow::getTraceBreakpoint); BreakpointLocationRow::getTraceBreakpoint);
} }
@@ -376,7 +378,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
if (context instanceof DebuggerBreakpointLocationsActionContext) { if (context instanceof DebuggerBreakpointLocationsActionContext) {
DebuggerBreakpointLocationsActionContext ctx = DebuggerBreakpointLocationsActionContext ctx =
(DebuggerBreakpointLocationsActionContext) context; (DebuggerBreakpointLocationsActionContext) context;
Collection<TraceBreakpoint> sel = ctx.getLocations(); Collection<TraceBreakpointLocation> sel = ctx.getLocations();
breakpointService.enableLocs(sel).exceptionally(ex -> { breakpointService.enableLocs(sel).exceptionally(ex -> {
breakpointError("Enable Breakpoints", "Could not enable breakpoints", ex); breakpointError("Enable Breakpoints", "Could not enable breakpoints", ex);
return null; return null;
@@ -455,7 +457,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
if (context instanceof DebuggerBreakpointLocationsActionContext) { if (context instanceof DebuggerBreakpointLocationsActionContext) {
DebuggerBreakpointLocationsActionContext ctx = DebuggerBreakpointLocationsActionContext ctx =
(DebuggerBreakpointLocationsActionContext) context; (DebuggerBreakpointLocationsActionContext) context;
Collection<TraceBreakpoint> sel = ctx.getLocations(); Collection<TraceBreakpointLocation> sel = ctx.getLocations();
breakpointService.disableLocs(sel).exceptionally(ex -> { breakpointService.disableLocs(sel).exceptionally(ex -> {
breakpointError("Disable Breakpoints", "Could not disable breakpoints", ex); breakpointError("Disable Breakpoints", "Could not disable breakpoints", ex);
return null; return null;
@@ -526,7 +528,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
if (context instanceof DebuggerBreakpointLocationsActionContext) { if (context instanceof DebuggerBreakpointLocationsActionContext) {
DebuggerBreakpointLocationsActionContext ctx = DebuggerBreakpointLocationsActionContext ctx =
(DebuggerBreakpointLocationsActionContext) context; (DebuggerBreakpointLocationsActionContext) context;
Collection<TraceBreakpoint> sel = ctx.getLocations(); Collection<TraceBreakpointLocation> sel = ctx.getLocations();
breakpointService.deleteLocs(sel).exceptionally(ex -> { breakpointService.deleteLocs(sel).exceptionally(ex -> {
breakpointError("Clear Breakpoints", "Could not clear breakpoints", ex); breakpointError("Clear Breakpoints", "Could not clear breakpoints", ex);
return null; return null;
@@ -700,26 +702,26 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
reloadBreakpointLocations(trace); reloadBreakpointLocations(trace);
} }
private boolean isVisible(TraceBreakpoint location) { private boolean isVisible(TraceBreakpointLocation location) {
long snap = traceManager.getCurrentFor(trace).getSnap(); long snap = traceManager.getCurrentFor(trace).getSnap();
return location.isValid(snap); return location.isValid(snap);
} }
private void locationAdded(TraceBreakpoint location) { private void locationAdded(TraceBreakpointLocation location) {
if (!isVisible(location)) { if (!isVisible(location)) {
return; return;
} }
breakpointLocationAdded(location); breakpointLocationAdded(location);
} }
private void locationChanged(TraceBreakpoint location) { private void locationChanged(TraceBreakpointLocation location) {
if (!isVisible(location)) { if (!isVisible(location)) {
return; return;
} }
breakpointLocationUpdated(location); breakpointLocationUpdated(location);
} }
private void locationLifespanChanged(TraceBreakpoint location, Lifespan oldSpan, private void locationLifespanChanged(TraceBreakpointLocation location, Lifespan oldSpan,
Lifespan newSpan) { Lifespan newSpan) {
long snap = traceManager.getCurrentFor(trace).getSnap(); long snap = traceManager.getCurrentFor(trace).getSnap();
boolean isLiveOld = oldSpan.contains(snap); 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)) { if (!isVisible(location)) {
return; return;
} }
@@ -955,15 +957,15 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
return; return;
} }
Lifespan span = Lifespan.at(currentFor.getSnap()); Lifespan span = Lifespan.at(currentFor.getSnap());
Collection<TraceBreakpoint> visible = new ArrayList<>(); Collection<TraceBreakpointLocation> visible = new ArrayList<>();
for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) { for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) {
Collection<? extends TraceBreakpoint> breaks = Collection<? extends TraceBreakpointLocation> breaks =
trace.getBreakpointManager().getBreakpointsIntersecting(span, range); trace.getBreakpointManager().getBreakpointsIntersecting(span, range);
if (mode.useEmulatedBreakpoints()) { if (mode.useEmulatedBreakpoints()) {
visible.addAll(breaks); visible.addAll(breaks);
} }
else { else {
for (TraceBreakpoint l : breaks) { for (TraceBreakpointLocation l : breaks) {
if (target.isBreakpointValid(l)) { if (target.isBreakpointValid(l)) {
visible.add(l); visible.add(l);
} }
@@ -982,19 +984,19 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
loadBreakpointLocations(trace); loadBreakpointLocations(trace);
} }
private void breakpointLocationAdded(TraceBreakpoint location) { private void breakpointLocationAdded(TraceBreakpointLocation location) {
locationTableModel.addItem(location); locationTableModel.addItem(location);
} }
private void breakpointLocationUpdated(TraceBreakpoint location) { private void breakpointLocationUpdated(TraceBreakpointLocation location) {
locationTableModel.updateItem(location); locationTableModel.updateItem(location);
} }
private void breakpointLocationsUpdated(Collection<TraceBreakpoint> locations) { private void breakpointLocationsUpdated(Collection<TraceBreakpointLocation> locations) {
locationTableModel.updateAllItems(locations); locationTableModel.updateAllItems(locations);
} }
private void breakpointLocationRemoved(TraceBreakpoint location) { private void breakpointLocationRemoved(TraceBreakpointLocation location) {
locationTableModel.deleteItem(location); locationTableModel.deleteItem(location);
} }
@@ -1304,12 +1306,12 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
} }
} }
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
Collection<TraceBreakpoint> locations = locCtx.getLocations(); Collection<TraceBreakpointLocation> locations = locCtx.getLocations();
if (locations.isEmpty()) { if (locations.isEmpty()) {
return false; return false;
} }
for (TraceBreakpoint tb : locations) { for (TraceBreakpointLocation loc : locations) {
traces.add(tb.getTrace()); traces.add(loc.getTrace());
} }
} }
else { else {
@@ -1338,9 +1340,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
return true; return true;
} }
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
for (TraceBreakpoint tb : locCtx.getLocations()) { for (TraceBreakpointLocation loc : locCtx.getLocations()) {
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap(); long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap();
if (!EXECUTE_KINDS.containsAll(tb.getKinds(snap))) { if (!EXECUTE_KINDS.containsAll(loc.getKinds(snap))) {
return false; return false;
} }
} }
@@ -1371,9 +1373,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
return sleigh; return sleigh;
} }
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
for (TraceBreakpoint tb : locCtx.getLocations()) { for (TraceBreakpointLocation loc : locCtx.getLocations()) {
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap(); long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap();
String s = tb.getEmuSleigh(snap); String s = loc.getEmuSleigh(snap);
if (sleigh != null && !sleigh.equals(s)) { if (sleigh != null && !sleigh.equals(s)) {
return null; return null;
} }
@@ -1397,9 +1399,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
} }
} }
else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) {
for (TraceBreakpoint tb : locCtx.getLocations()) { for (TraceBreakpointLocation loc : locCtx.getLocations()) {
long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap(); long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap();
tb.setEmuSleigh(snap, sleigh); loc.setEmuSleigh(snap, sleigh);
} }
} }
else { else {
@@ -1466,7 +1468,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
breakpointTableModel, breakpointFilterPanel); breakpointTableModel, breakpointFilterPanel);
} }
public void setSelectedLocations(Set<TraceBreakpoint> sel) { public void setSelectedLocations(Set<TraceBreakpointLocation> sel) {
DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable, DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable,
locationTableModel, locationFilterPanel); locationTableModel, locationFilterPanel);
} }
@@ -28,7 +28,7 @@ import ghidra.program.model.data.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.trace.model.Lifespan; 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.TraceMemoryManager;
import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
@@ -220,7 +220,7 @@ public class DebuggerCopyPlan {
public void copy(TraceProgramView from, AddressRange fromRange, Program into, public void copy(TraceProgramView from, AddressRange fromRange, Program into,
Address intoAddress, TaskMonitor monitor) throws Exception { Address intoAddress, TaskMonitor monitor) throws Exception {
long snap = from.getSnap(); long snap = from.getSnap();
for (TraceBreakpoint bpt : from.getTrace() for (TraceBreakpointLocation bpt : from.getTrace()
.getBreakpointManager() .getBreakpointManager()
.getBreakpointsIntersecting(Lifespan.at(from.getSnap()), fromRange)) { .getBreakpointsIntersecting(Lifespan.at(from.getSnap()), fromRange)) {
monitor.checkCancelled(); monitor.checkCancelled();
@@ -32,7 +32,7 @@ import ghidra.program.model.address.*;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.TraceMemoryFlag; 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.path.KeyPath;
import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.target.schema.TraceObjectSchema;
import ghidra.util.layout.PairLayout; import ghidra.util.layout.PairLayout;
@@ -161,8 +161,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
if (rootSchema == null) { if (rootSchema == null) {
return ""; return "";
} }
KeyPath suitable = rootSchema.searchForSuitableContainer(TraceObjectMemoryRegion.class, KeyPath suitable =
current.getPath()); rootSchema.searchForSuitableContainer(TraceMemoryRegion.class, current.getPath());
if (suitable == null) { if (suitable == null) {
return ""; return "";
} }
@@ -55,8 +55,7 @@ import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoConfigStateField; import ghidra.framework.plugintool.annotation.AutoConfigStateField;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed; import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.program.model.address.Address; import ghidra.program.model.address.*;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
@@ -65,7 +64,6 @@ import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceDomainObjectListener; import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.Swing; import ghidra.util.Swing;
@@ -99,8 +97,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged); listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged);
} }
private void bytesChanged(TraceAddressSpace space) { private void bytesChanged(AddressSpace space) {
if (space.getAddressSpace().isMemorySpace()) { if (space.isMemorySpace()) {
currCache.invalidate(); currCache.invalidate();
prevCache.invalidate(); prevCache.invalidate();
} }
@@ -29,13 +29,14 @@ import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.Trace; 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.TraceObject;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.schema.TraceObjectSchema; 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 { private static class RegionKeyColumn extends TraceValueKeyColumn {
@Override @Override
@@ -66,7 +67,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class RegionStartColumn extends AbstractTraceValueObjectAddressColumn { private static class RegionStartColumn extends AbstractTraceValueObjectAddressColumn {
public RegionStartColumn() { public RegionStartColumn() {
super(TraceObjectMemoryRegion.KEY_RANGE); super(TraceMemoryRegion.KEY_RANGE);
} }
@Override @Override
@@ -82,7 +83,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class RegionEndColumn extends AbstractTraceValueObjectAddressColumn { private static class RegionEndColumn extends AbstractTraceValueObjectAddressColumn {
public RegionEndColumn() { public RegionEndColumn() {
super(TraceObjectMemoryRegion.KEY_RANGE); super(TraceMemoryRegion.KEY_RANGE);
} }
@Override @Override
@@ -98,7 +99,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class RegionLengthColumn extends AbstractTraceValueObjectLengthColumn { private static class RegionLengthColumn extends AbstractTraceValueObjectLengthColumn {
public RegionLengthColumn() { public RegionLengthColumn() {
super(TraceObjectMemoryRegion.KEY_RANGE); super(TraceMemoryRegion.KEY_RANGE);
} }
@Override @Override
@@ -120,7 +121,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
public static class RegionReadColumn extends RegionFlagColumn { public static class RegionReadColumn extends RegionFlagColumn {
public RegionReadColumn() { public RegionReadColumn() {
super(TraceObjectMemoryRegion.KEY_READABLE); super(TraceMemoryRegion.KEY_READABLE);
} }
@Override @Override
@@ -131,7 +132,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
public static class RegionWriteColumn extends RegionFlagColumn { public static class RegionWriteColumn extends RegionFlagColumn {
public RegionWriteColumn() { public RegionWriteColumn() {
super(TraceObjectMemoryRegion.KEY_WRITABLE); super(TraceMemoryRegion.KEY_WRITABLE);
} }
@Override @Override
@@ -142,7 +143,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
public static class RegionExecuteColumn extends RegionFlagColumn { public static class RegionExecuteColumn extends RegionFlagColumn {
public RegionExecuteColumn() { public RegionExecuteColumn() {
super(TraceObjectMemoryRegion.KEY_EXECUTABLE); super(TraceMemoryRegion.KEY_EXECUTABLE);
} }
@Override @Override
@@ -174,7 +175,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
protected static ModelQuery successorRegions(TraceObjectSchema rootSchema, KeyPath path) { protected static ModelQuery successorRegions(TraceObjectSchema rootSchema, KeyPath path) {
TraceObjectSchema schema = rootSchema.getSuccessorSchema(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) { protected Set<TraceMemoryRegion> getSelectedRegions(DebuggerObjectActionContext ctx) {
@@ -182,7 +183,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
} }
public DebuggerRegionsPanel(DebuggerRegionsProvider provider) { public DebuggerRegionsPanel(DebuggerRegionsProvider provider) {
super(provider.plugin, provider, TraceObjectMemoryRegion.class); super(provider.plugin, provider, TraceMemoryRegion.class);
} }
@Override @Override
@@ -194,14 +195,14 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
protected ModelQuery computeQuery(TraceObject object) { protected ModelQuery computeQuery(TraceObject object) {
TraceObjectSchema rootSchema = object.getRoot().getSchema(); TraceObjectSchema rootSchema = object.getRoot().getSchema();
KeyPath seedPath = object.getCanonicalPath(); KeyPath seedPath = object.getCanonicalPath();
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath); KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
if (processPath != null) { if (processPath != null) {
ModelQuery result = successorRegions(rootSchema, processPath); ModelQuery result = successorRegions(rootSchema, processPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return result; return result;
} }
} }
KeyPath memoryPath = rootSchema.searchForSuitable(TraceObjectMemory.class, seedPath); KeyPath memoryPath = rootSchema.searchForSuitable(TraceMemory.class, seedPath);
if (memoryPath != null) { if (memoryPath != null) {
ModelQuery result = successorRegions(rootSchema, memoryPath); ModelQuery result = successorRegions(rootSchema, memoryPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
@@ -23,15 +23,17 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.model.DomainObjectChangeRecord; import ghidra.framework.model.DomainObjectChangeRecord;
import ghidra.framework.model.DomainObjectEvent; import ghidra.framework.model.DomainObjectEvent;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.database.module.TraceObjectSection;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.memory.*; 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.modules.*;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.path.KeyPath; 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.model.time.TraceTimeManager;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.Swing; import ghidra.util.Swing;
@@ -100,7 +102,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
} }
private void threadChanged(TraceThread thread) { private void threadChanged(TraceThread thread) {
if (!trackThreads || !trackTrace || !(thread instanceof TraceObjectThread objThread)) { if (!trackThreads || !trackTrace) {
return; return;
} }
AddressFactory factory = thread.getTrace().getBaseAddressFactory(); AddressFactory factory = thread.getTrace().getBaseAddressFactory();
@@ -108,7 +110,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
Long threadId = thread.getKey(); Long threadId = thread.getKey();
AddressRange rng = rng(defaultSpace, threadId, threadId); AddressRange rng = rng(defaultSpace, threadId, threadId);
TraceObject obj = objThread.getObject(); TraceObject obj = thread.getObject();
obj.getCanonicalParents(Lifespan.ALL).forEach(p -> { obj.getCanonicalParents(Lifespan.ALL).forEach(p -> {
MemoryBox box = new MemoryBox(currentTrace, "Thread " + thread.getName(p.getMinSnap()), MemoryBox box = new MemoryBox(currentTrace, "Thread " + thread.getName(p.getMinSnap()),
MemviewBoxType.THREAD, rng, p.getLifespan()); MemviewBoxType.THREAD, rng, p.getLifespan());
@@ -118,13 +120,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
} }
private void regionChanged(TraceMemoryRegion region) { private void regionChanged(TraceMemoryRegion region) {
if (!trackRegions || !trackTrace || if (!trackRegions || !trackTrace) {
!(region instanceof TraceObjectMemoryRegion objRegion)) {
return; return;
} }
TraceObject obj = objRegion.getObject(); TraceObject obj = region.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectMemoryRegion.KEY_RANGE, true).forEach(v -> { obj.getOrderedValues(Lifespan.ALL, TraceMemoryRegion.KEY_RANGE, true).forEach(v -> {
if (region.getName(v.getMinSnap()).equals("full memory")) { if (region.getName(v.getMinSnap()).equals("full memory")) {
return; return;
} }
@@ -136,12 +137,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
} }
private void moduleChanged(TraceModule module) { private void moduleChanged(TraceModule module) {
if (!trackModules || !trackTrace || !(module instanceof TraceObjectModule objModule)) { if (!trackModules || !trackTrace) {
return; return;
} }
TraceObject obj = objModule.getObject(); TraceObject obj = module.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectModule.KEY_RANGE, true).forEach(v -> { obj.getOrderedValues(Lifespan.ALL, TraceModule.KEY_RANGE, true).forEach(v -> {
MemoryBox box = new MemoryBox(currentTrace, "Module " + module.getName(v.getMinSnap()), MemoryBox box = new MemoryBox(currentTrace, "Module " + module.getName(v.getMinSnap()),
MemviewBoxType.MODULE, v.castValue(), v.getLifespan()); MemviewBoxType.MODULE, v.castValue(), v.getLifespan());
updateList.add(box); updateList.add(box);
@@ -150,12 +151,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
} }
private void sectionChanged(TraceSection section) { private void sectionChanged(TraceSection section) {
if (!trackSections || !trackTrace || !(section instanceof TraceObjectSection objSection)) { if (!trackSections || !trackTrace) {
return; return;
} }
TraceObject obj = objSection.getObject(); TraceObject obj = section.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectSection.KEY_RANGE, true).forEach(v -> { obj.getOrderedValues(Lifespan.ALL, TraceSection.KEY_RANGE, true).forEach(v -> {
MemoryBox box = new MemoryBox(currentTrace, "Module " + section.getName(v.getMinSnap()), MemoryBox box = new MemoryBox(currentTrace, "Module " + section.getName(v.getMinSnap()),
MemviewBoxType.IMAGE, v.castValue(), v.getLifespan()); MemviewBoxType.IMAGE, v.castValue(), v.getLifespan());
updateList.add(box); updateList.add(box);
@@ -163,14 +164,13 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
updateLabelDebouncer.contact(null); updateLabelDebouncer.contact(null);
} }
private void breakpointChanged(TraceBreakpoint bpt) { private void breakpointChanged(TraceBreakpointLocation bpt) {
if (!trackBreakpoints || !trackTrace || if (!trackBreakpoints || !trackTrace) {
!(bpt instanceof TraceObjectBreakpointLocation objBpt)) {
return; return;
} }
TraceObject obj = objBpt.getObject(); TraceObject obj = bpt.getObject();
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
.forEach(v -> { .forEach(v -> {
MemoryBox box = MemoryBox box =
new MemoryBox(currentTrace, "Module " + bpt.getName(v.getMinSnap()), new MemoryBox(currentTrace, "Module " + bpt.getName(v.getMinSnap()),
@@ -301,7 +301,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener {
regionChanged(region); regionChanged(region);
} }
TraceBreakpointManager breakpointManager = trace.getBreakpointManager(); TraceBreakpointManager breakpointManager = trace.getBreakpointManager();
for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) { for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) {
breakpointChanged(bpt); breakpointChanged(bpt);
} }
updateLabelDebouncer.contact(null); updateLabelDebouncer.contact(null);
@@ -130,7 +130,7 @@ public interface ObjectDefaultActionsMixin {
default boolean performDefaultAction(TraceObject object) { default boolean performDefaultAction(TraceObject object) {
Set<Class<? extends TraceObjectInterface>> interfaces = Set<Class<? extends TraceObjectInterface>> interfaces =
object.getSchema().getInterfaces(); object.getSchema().getInterfaces();
if (interfaces.contains(TraceObjectActivatable.class)) { if (interfaces.contains(TraceActivatable.class)) {
activatePath(object.getCanonicalPath()); activatePath(object.getCanonicalPath());
return true; return true;
} }
@@ -138,7 +138,7 @@ public interface ObjectDefaultActionsMixin {
* Should I check aliveAndPresent() here? If I do, behavior changes when target is dead, * Should I check aliveAndPresent() here? If I do, behavior changes when target is dead,
* which might be unexpected. * which might be unexpected.
*/ */
if (interfaces.contains(TraceObjectTogglable.class)) { if (interfaces.contains(TraceTogglable.class)) {
toggleObject(object); toggleObject(object);
return true; return true;
} }
@@ -26,8 +26,8 @@ import generic.theme.GIcon;
import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.breakpoint.TraceObjectBreakpointSpec; import ghidra.trace.model.breakpoint.TraceBreakpointSpec;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.iface.*; import ghidra.trace.model.target.iface.*;
@@ -65,10 +65,10 @@ public class ObjectTreeModel implements DisplaysModified {
if (!value.getParent() if (!value.getParent()
.getSchema() .getSchema()
.getInterfaces() .getInterfaces()
.contains(TraceObjectEventScope.class)) { .contains(TraceEventScope.class)) {
return false; return false;
} }
if (!TraceObjectEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) { if (!TraceEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) {
return false; return false;
} }
return true; return true;
@@ -77,12 +77,12 @@ public class ObjectTreeModel implements DisplaysModified {
protected boolean isEnabledValue(TraceObjectValue value) { protected boolean isEnabledValue(TraceObjectValue value) {
Set<Class<? extends TraceObjectInterface>> interfaces = Set<Class<? extends TraceObjectInterface>> interfaces =
value.getParent().getSchema().getInterfaces(); value.getParent().getSchema().getInterfaces();
if (!interfaces.contains(TraceObjectBreakpointSpec.class) && if (!interfaces.contains(TraceBreakpointSpec.class) &&
!interfaces.contains(TraceObjectBreakpointLocation.class) && !interfaces.contains(TraceBreakpointLocation.class) &&
!interfaces.contains(TraceObjectTogglable.class)) { !interfaces.contains(TraceTogglable.class)) {
return false; return false;
} }
if (!TraceObjectTogglable.KEY_ENABLED.equals(value.getEntryKey())) { if (!TraceTogglable.KEY_ENABLED.equals(value.getEntryKey())) {
return false; return false;
} }
return true; return true;
@@ -675,7 +675,7 @@ public class ObjectTreeModel implements DisplaysModified {
protected TraceObject getEventObject(TraceObject object) { protected TraceObject getEventObject(TraceObject object) {
TraceObject scope = object TraceObject scope = object
.findCanonicalAncestorsInterface(TraceObjectEventScope.class) .findCanonicalAncestorsInterface(TraceEventScope.class)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
if (scope == null) { if (scope == null) {
@@ -685,7 +685,7 @@ public class ObjectTreeModel implements DisplaysModified {
return null; return null;
} }
TraceObjectValue eventValue = TraceObjectValue eventValue =
scope.getAttribute(snap, TraceObjectEventScope.KEY_EVENT_THREAD); scope.getAttribute(snap, TraceEventScope.KEY_EVENT_THREAD);
if (eventValue == null || !eventValue.isObject()) { if (eventValue == null || !eventValue.isObject()) {
return null; return null;
} }
@@ -712,7 +712,7 @@ public class ObjectTreeModel implements DisplaysModified {
if (type.contains("Breakpoint") || type.contains("Watchpoint")) { if (type.contains("Breakpoint") || type.contains("Watchpoint")) {
TraceObject object = edge.getChild(); TraceObject object = edge.getChild();
TraceObjectValue en = TraceObjectValue en =
object.getAttribute(snap, TraceObjectTogglable.KEY_ENABLED); object.getAttribute(snap, TraceTogglable.KEY_ENABLED);
// includes true or non-boolean values // includes true or non-boolean values
if (en == null || !Objects.equals(false, en.getValue())) { if (en == null || !Objects.equals(false, en.getValue())) {
return DebuggerResources.ICON_SET_BREAKPOINT; return DebuggerResources.ICON_SET_BREAKPOINT;
@@ -31,20 +31,20 @@ import ghidra.docking.settings.Settings;
import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.database.module.TraceObjectSection;
import ghidra.trace.model.Trace; 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.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.schema.TraceObjectSchema; 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 { private static class ModuleBaseColumn extends AbstractTraceValueObjectAddressColumn {
public ModuleBaseColumn() { public ModuleBaseColumn() {
super(TraceObjectModule.KEY_RANGE); super(TraceModule.KEY_RANGE);
} }
@Override @Override
@@ -60,7 +60,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class ModuleMaxColumn extends AbstractTraceValueObjectAddressColumn { private static class ModuleMaxColumn extends AbstractTraceValueObjectAddressColumn {
public ModuleMaxColumn() { public ModuleMaxColumn() {
super(TraceObjectModule.KEY_RANGE); super(TraceModule.KEY_RANGE);
} }
@Override @Override
@@ -76,7 +76,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class ModuleNameColumn extends TraceValueObjectAttributeColumn<String> { private static class ModuleNameColumn extends TraceValueObjectAttributeColumn<String> {
public ModuleNameColumn() { public ModuleNameColumn() {
super(TraceObjectModule.KEY_MODULE_NAME, String.class); super(TraceModule.KEY_MODULE_NAME, String.class);
} }
@Override @Override
@@ -98,7 +98,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
return ""; return "";
} }
ValueAttribute<AddressRange> attr = ValueAttribute<AddressRange> attr =
rowObject.getAttribute(TraceObjectModule.KEY_RANGE, AddressRange.class); rowObject.getAttribute(TraceModule.KEY_RANGE, AddressRange.class);
if (attr == null) { if (attr == null) {
return ""; return "";
} }
@@ -131,7 +131,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class ModuleLengthColumn extends AbstractTraceValueObjectLengthColumn { private static class ModuleLengthColumn extends AbstractTraceValueObjectLengthColumn {
public ModuleLengthColumn() { public ModuleLengthColumn() {
super(TraceObjectModule.KEY_RANGE); super(TraceModule.KEY_RANGE);
} }
@Override @Override
@@ -166,12 +166,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
continue; continue;
} }
TraceObject child = value.getChild(); TraceObject child = value.getChild();
TraceObjectModule module = child.queryInterface(TraceObjectModule.class); TraceModule module = child.queryInterface(TraceModule.class);
if (module != null) { if (module != null) {
result.add(module); result.add(module);
continue; continue;
} }
TraceObjectSection section = child.queryInterface(TraceObjectSection.class); TraceSection section = child.queryInterface(TraceSection.class);
if (section != null) { if (section != null) {
result.add(section.getModule()); result.add(section.getModule());
continue; continue;
@@ -188,12 +188,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
continue; continue;
} }
TraceObject child = value.getChild(); TraceObject child = value.getChild();
TraceObjectModule module = child.queryInterface(TraceObjectModule.class); TraceModule module = child.queryInterface(TraceModule.class);
if (module != null) { if (module != null) {
result.addAll(module.getSections(ctx.getSnap())); result.addAll(module.getSections(ctx.getSnap()));
continue; continue;
} }
TraceObjectSection section = child.queryInterface(TraceObjectSection.class); TraceSection section = child.queryInterface(TraceSection.class);
if (section != null) { if (section != null) {
result.add(section); result.add(section);
continue; continue;
@@ -206,12 +206,12 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
AddressSet result = new AddressSet(); AddressSet result = new AddressSet();
for (TraceObjectValue value : ctx.getObjectValues()) { for (TraceObjectValue value : ctx.getObjectValues()) {
TraceObject child = value.getChild(); TraceObject child = value.getChild();
TraceObjectModule module = child.queryInterface(TraceObjectModule.class); TraceModule module = child.queryInterface(TraceModule.class);
if (module != null) { if (module != null) {
result.add(module.getRange(ctx.getSnap())); result.add(module.getRange(ctx.getSnap()));
continue; continue;
} }
TraceObjectSection section = child.queryInterface(TraceObjectSection.class); TraceSection section = child.queryInterface(TraceSection.class);
if (section != null) { if (section != null) {
result.add(section.getRange(ctx.getSnap())); result.add(section.getRange(ctx.getSnap()));
continue; continue;
@@ -222,13 +222,13 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
protected static ModelQuery successorModules(TraceObjectSchema rootSchema, KeyPath path) { protected static ModelQuery successorModules(TraceObjectSchema rootSchema, KeyPath path) {
TraceObjectSchema schema = rootSchema.getSuccessorSchema(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; private final DebuggerModulesProvider provider;
public DebuggerModulesPanel(DebuggerModulesProvider provider) { public DebuggerModulesPanel(DebuggerModulesProvider provider) {
super(provider.plugin, provider, TraceObjectModule.class); super(provider.plugin, provider, TraceModule.class);
this.provider = provider; this.provider = provider;
} }
@@ -241,15 +241,14 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
protected ModelQuery computeQuery(TraceObject object) { protected ModelQuery computeQuery(TraceObject object) {
TraceObjectSchema rootSchema = object.getRoot().getSchema(); TraceObjectSchema rootSchema = object.getRoot().getSchema();
KeyPath seedPath = object.getCanonicalPath(); KeyPath seedPath = object.getCanonicalPath();
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath); KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
if (processPath != null) { if (processPath != null) {
ModelQuery result = successorModules(rootSchema, processPath); ModelQuery result = successorModules(rootSchema, processPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return result; return result;
} }
} }
KeyPath containerPath = KeyPath containerPath = rootSchema.searchForSuitableContainer(TraceModule.class, seedPath);
rootSchema.searchForSuitableContainer(TraceObjectModule.class, seedPath);
if (containerPath != null) { if (containerPath != null) {
ModelQuery result = successorModules(rootSchema, containerPath); ModelQuery result = successorModules(rootSchema, containerPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
@@ -547,7 +547,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter
DebuggerModulesPanel modulesPanel; DebuggerModulesPanel modulesPanel;
DebuggerSectionsPanel sectionsPanel; DebuggerSectionsPanel sectionsPanel;
// TODO: Lazy construction of these dialogs? // LATER?: Lazy construction of these dialogs?
private final DebuggerBlockChooserDialog blockChooserDialog; private final DebuggerBlockChooserDialog blockChooserDialog;
private final DebuggerModuleMapProposalDialog moduleProposalDialog; private final DebuggerModuleMapProposalDialog moduleProposalDialog;
private final DebuggerSectionMapProposalDialog sectionProposalDialog; private final DebuggerSectionMapProposalDialog sectionProposalDialog;
@@ -30,22 +30,21 @@ import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.database.module.TraceObjectSection;
import ghidra.trace.model.Trace; 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.modules.TraceSection;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.schema.TraceObjectSchema; 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 { private static class SectionStartColumn extends AbstractTraceValueObjectAddressColumn {
public SectionStartColumn() { public SectionStartColumn() {
super(TraceObjectSection.KEY_RANGE); super(TraceSection.KEY_RANGE);
} }
@Override @Override
@@ -61,7 +60,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
private static class SectionEndColumn extends AbstractTraceValueObjectAddressColumn { private static class SectionEndColumn extends AbstractTraceValueObjectAddressColumn {
public SectionEndColumn() { public SectionEndColumn() {
super(TraceObjectSection.KEY_RANGE); super(TraceSection.KEY_RANGE);
} }
@Override @Override
@@ -120,8 +119,8 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
if (module == null) { if (module == null) {
return ""; return "";
} }
TraceObjectValue nameEntry = module.getAttribute(row.currentSnap(), TraceObjectValue nameEntry =
TraceObjectModule.KEY_MODULE_NAME); module.getAttribute(row.currentSnap(), TraceModule.KEY_MODULE_NAME);
if (nameEntry == null) { if (nameEntry == null) {
return ""; return "";
} }
@@ -133,7 +132,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
private static class SectionLengthColumn extends AbstractTraceValueObjectLengthColumn { private static class SectionLengthColumn extends AbstractTraceValueObjectLengthColumn {
public SectionLengthColumn() { public SectionLengthColumn() {
super(TraceObjectSection.KEY_RANGE); super(TraceSection.KEY_RANGE);
} }
@Override @Override
@@ -161,21 +160,20 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
} }
private static TraceObject getModule(ValueRow row) { private static TraceObject getModule(ValueRow row) {
TraceObjectValue moduleEntry = TraceObjectValue moduleEntry = row.getAttributeEntry(TraceSection.KEY_MODULE);
row.getAttributeEntry(TraceObjectSection.KEY_MODULE);
if (moduleEntry != null && moduleEntry.isObject()) { if (moduleEntry != null && moduleEntry.isObject()) {
return moduleEntry.getChild(); return moduleEntry.getChild();
} }
return row.getValue() return row.getValue()
.getChild() .getChild()
.findCanonicalAncestorsInterface(TraceObjectModule.class) .findCanonicalAncestorsInterface(TraceModule.class)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
protected static ModelQuery successorSections(TraceObjectSchema rootSchema, KeyPath path) { protected static ModelQuery successorSections(TraceObjectSchema rootSchema, KeyPath path) {
TraceObjectSchema schema = rootSchema.getSuccessorSchema(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> { private class SectionsBySelectedModulesTableFilter implements TableFilter<ValueRow> {
@@ -201,7 +199,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
new SectionsBySelectedModulesTableFilter(); new SectionsBySelectedModulesTableFilter();
public DebuggerSectionsPanel(DebuggerModulesProvider provider) { public DebuggerSectionsPanel(DebuggerModulesProvider provider) {
super(provider.plugin, provider, TraceObjectSection.class); super(provider.plugin, provider, TraceSection.class);
this.provider = provider; this.provider = provider;
} }
@@ -214,19 +212,18 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
protected ModelQuery computeQuery(TraceObject object) { protected ModelQuery computeQuery(TraceObject object) {
TraceObjectSchema rootSchema = object.getRoot().getSchema(); TraceObjectSchema rootSchema = object.getRoot().getSchema();
KeyPath seedPath = object.getCanonicalPath(); KeyPath seedPath = object.getCanonicalPath();
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath); KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
if (processPath != null) { if (processPath != null) {
ModelQuery result = successorSections(rootSchema, processPath); ModelQuery result = successorSections(rootSchema, processPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return result; return result;
} }
} }
// Yes, anchor on the *module* container when searching for sections // Yes, anchor on the *module* container when searching for sections
KeyPath containerPath = KeyPath containerPath = rootSchema.searchForSuitableContainer(TraceModule.class, seedPath);
rootSchema.searchForSuitableContainer(TraceObjectModule.class, seedPath);
if (containerPath != null) { if (containerPath != null) {
ModelQuery result = successorSections(rootSchema, containerPath); ModelQuery result = successorSections(rootSchema, containerPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return result; return result;
} }
@@ -25,8 +25,8 @@ import ghidra.debug.api.ValStr;
import ghidra.framework.options.SaveState; import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField; import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.trace.model.target.iface.TraceObjectMethod; import ghidra.trace.model.target.iface.TraceMethod;
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription; import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription;
@Deprecated(forRemoval = true, since = "11.3") @Deprecated(forRemoval = true, since = "11.3")
public class DebuggerMethodInvocationDialog public class DebuggerMethodInvocationDialog
@@ -71,7 +71,7 @@ public class DebuggerMethodInvocationDialog
protected Map<String, ValStr<?>> validateArguments( protected Map<String, ValStr<?>> validateArguments(
Map<String, ParameterDescription<?>> parameters, Map<String, ValStr<?>> arguments) { Map<String, ParameterDescription<?>> parameters, Map<String, ValStr<?>> arguments) {
Map<String, ?> args = ValStr.toPlainMap(arguments); Map<String, ?> args = ValStr.toPlainMap(arguments);
return ValStr.fromPlainMap(TraceObjectMethod.validateArguments(parameters, args, false)); return ValStr.fromPlainMap(TraceMethod.validateArguments(parameters, args, false));
} }
@Override @Override
@@ -69,9 +69,9 @@ import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.*; import ghidra.trace.model.listing.*;
import ghidra.trace.model.memory.*; import ghidra.trace.model.memory.*;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.thread.TraceThread; 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.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher; import ghidra.util.classfinder.ClassSearcher;
@@ -283,37 +283,28 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
listenFor(TraceEvents.THREAD_LIFESPAN_CHANGED, this::threadDestroyed); listenFor(TraceEvents.THREAD_LIFESPAN_CHANGED, this::threadDestroyed);
} }
private boolean isVisibleObjectsMode(AddressSpace space) { private boolean isVisible(AddressSpace space) {
TraceObject container = current.getRegisterContainer(); if (!space.isRegisterSpace()) {
return container != null && return true; // Memory-mapped, visible no matter the active thread
container.getCanonicalPath().toString().equals(space.getName()); }
}
private boolean isVisible(TraceAddressSpace space) {
TraceThread curThread = current.getThread(); TraceThread curThread = current.getThread();
if (curThread == null) { if (curThread == null) {
return false; return false;
} }
if (space.getAddressSpace().isOverlaySpace()) { if (space.isOverlaySpace()) {
return isVisibleObjectsMode(space.getAddressSpace()); return current.isRegisterSpace(space);
} }
if (!space.getAddressSpace().isRegisterSpace()) { if (space.isRegisterSpace()) {
return true; // Memory-mapped, visible no matter the active thread throw new AssertionError();
} }
if (space.getThread() != curThread) { return false;
return false;
}
if (space.getFrameLevel() != current.getFrame()) {
return false;
}
return true;
} }
private boolean isVisible(TraceAddressSpace space, TraceAddressSnapRange range) { private boolean isVisible(AddressSpace space, TraceAddressSnapRange range) {
if (!isVisible(space)) { if (!isVisible(space)) {
return false; return false;
} }
if (space.getAddressSpace().isMemorySpace()) { if (space.isMemorySpace()) {
return current.getPlatform() return current.getPlatform()
.getLanguage() .getLanguage()
.getRegisterAddresses() .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) { byte[] oldIsNull, byte[] newVal) {
if (!isVisible(space, range)) { if (!isVisible(space, range)) {
return; return;
@@ -359,7 +350,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
refreshRange(range.getRange()); refreshRange(range.getRange());
} }
private void registerStateChanged(TraceAddressSpace space, TraceAddressSnapRange range, private void registerStateChanged(AddressSpace space, TraceAddressSnapRange range,
TraceMemoryState oldState, TraceMemoryState newState) { TraceMemoryState oldState, TraceMemoryState newState) {
if (!isVisible(space, range)) { if (!isVisible(space, range)) {
return; return;
@@ -368,7 +359,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
refreshRange(range.getRange()); refreshRange(range.getRange());
} }
private void registerTypeAdded(TraceAddressSpace space, TraceAddressSnapRange range, private void registerTypeAdded(AddressSpace space, TraceAddressSnapRange range,
TraceCodeUnit oldIsNull, TraceCodeUnit newUnit) { TraceCodeUnit oldIsNull, TraceCodeUnit newUnit) {
if (!isVisible(space, range)) { if (!isVisible(space, range)) {
return; return;
@@ -376,7 +367,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
refreshRange(range.getRange()); refreshRange(range.getRange());
} }
private void registerTypeReplaced(TraceAddressSpace space, TraceAddressSnapRange range, private void registerTypeReplaced(AddressSpace space, TraceAddressSnapRange range,
long oldTypeID, long newTypeID) { long oldTypeID, long newTypeID) {
if (!isVisible(space, range)) { if (!isVisible(space, range)) {
return; return;
@@ -384,7 +375,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
refreshRange(range.getRange()); refreshRange(range.getRange());
} }
private void registerTypeLifespanChanged(TraceAddressSpace space, TraceCodeUnit unit, private void registerTypeLifespanChanged(AddressSpace space, TraceCodeUnit unit,
Lifespan oldSpan, Lifespan newSpan) { Lifespan oldSpan, Lifespan newSpan) {
if (!isVisible(space)) { if (!isVisible(space)) {
return; return;
@@ -402,7 +393,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
refreshRange(range); // Slightly wasteful, as we already have the data unit 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) { TraceCodeUnit oldUnit, TraceCodeUnit newIsNull) {
if (!isVisible(space)) { if (!isVisible(space)) {
return; return;
@@ -34,15 +34,15 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.stack.TraceObjectStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.stack.TraceObjectStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.path.PathFilter;
import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.target.schema.TraceObjectSchema;
public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObjectStackFrame> public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceStackFrame>
implements ListSelectionListener { implements ListSelectionListener {
private static class FrameLevelColumn extends TraceValueKeyColumn { private static class FrameLevelColumn extends TraceValueKeyColumn {
@@ -59,7 +59,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
private static class FramePcColumn extends TraceValueObjectAttributeColumn<Address> { private static class FramePcColumn extends TraceValueObjectAttributeColumn<Address> {
public FramePcColumn() { public FramePcColumn() {
super(TraceObjectStackFrame.KEY_PC, Address.class); super(TraceStackFrame.KEY_PC, Address.class);
} }
@Override @Override
@@ -72,7 +72,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
if (!(row.getValue().getValue() instanceof TraceObject object)) { if (!(row.getValue().getValue() instanceof TraceObject object)) {
return null; 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)) { if (attrPc == null || !(attrPc.getValue() instanceof Address pc)) {
return null; return null;
} }
@@ -177,7 +177,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
protected DebuggerTraceManagerService traceManager; protected DebuggerTraceManagerService traceManager;
public DebuggerStackPanel(DebuggerStackProvider provider) { public DebuggerStackPanel(DebuggerStackProvider provider) {
super(provider.plugin, provider, TraceObjectStackFrame.class); super(provider.plugin, provider, TraceStackFrame.class);
this.provider = provider; this.provider = provider;
} }
@@ -190,12 +190,12 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
protected ModelQuery computeQuery(TraceObject object) { protected ModelQuery computeQuery(TraceObject object) {
TraceObjectSchema rootSchema = object.getRoot().getSchema(); TraceObjectSchema rootSchema = object.getRoot().getSchema();
KeyPath stackPath = KeyPath stackPath =
rootSchema.searchForSuitable(TraceObjectStack.class, object.getCanonicalPath()); rootSchema.searchForSuitable(TraceStack.class, object.getCanonicalPath());
if (stackPath == null) { if (stackPath == null) {
return ModelQuery.EMPTY; return ModelQuery.EMPTY;
} }
TraceObjectSchema stackSchema = rootSchema.getSuccessorSchema(stackPath); 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); return new ModelQuery(filter);
} }
@@ -27,6 +27,7 @@ import ghidra.pcode.exec.DebuggerPcodeUtils.PrettyBytes;
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue; import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
import ghidra.pcode.exec.ValueLocation; import ghidra.pcode.exec.ValueLocation;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@@ -35,8 +36,7 @@ import ghidra.program.model.pcode.Varnode;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.listing.TraceCodeUnit; import ghidra.trace.model.listing.TraceCodeUnit;
import ghidra.trace.model.memory.*; import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.HTMLUtilities; import ghidra.util.HTMLUtilities;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
@@ -366,17 +366,9 @@ public interface VariableValueRow {
* @param snap the snapshot key * @param snap the snapshot key
* @return the composite state * @return the composite state
*/ */
static TraceMemoryState computeState(Trace trace, TraceAddressSpace space, AddressRange range, static TraceMemoryState computeState(Trace trace, AddressSpace space, AddressRange range,
long snap) { long snap) {
TraceMemoryManager mem = trace.getMemoryManager(); return trace.getMemoryManager().isKnown(snap, range)
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)
? TraceMemoryState.KNOWN ? TraceMemoryState.KNOWN
: TraceMemoryState.UNKNOWN; : TraceMemoryState.UNKNOWN;
} }
@@ -387,10 +379,11 @@ public interface VariableValueRow {
* @param unit the code unit * @param unit the code unit
* @param snap the snapshot key * @param snap the snapshot key
* @return the composite state. * @return the composite state.
* @see #computeState(Trace, TraceAddressSpace, AddressRange, long) * @see #computeState(Trace, AddressSpace, AddressRange, long)
*/ */
static TraceMemoryState computeState(TraceCodeUnit unit, long snap) { 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.TraceStack;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.MathUtilities; import ghidra.util.MathUtilities;
import ghidra.util.Msg; import ghidra.util.Msg;
@@ -672,10 +671,9 @@ public enum VariableValueUtils {
listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged); listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged);
} }
private void bytesChanged(TraceAddressSpace space, TraceAddressSnapRange range) { private void bytesChanged(AddressSpace space, TraceAddressSnapRange range) {
TraceThread thread = space.getThread();
// TODO: Consider the lifespan, too? Would have to use viewport.... // TODO: Consider the lifespan, too? Would have to use viewport....
if (thread == null || thread == coordinates.getThread()) { if (space.isMemorySpace() || coordinates.isRegisterSpace(space)) {
invalidateCache(); invalidateCache();
} }
} }
@@ -38,17 +38,17 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.target.TraceObject; 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.path.KeyPath;
import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.target.schema.TraceObjectSchema;
import ghidra.trace.model.thread.TraceObjectProcess; import ghidra.trace.model.thread.TraceProcess;
import ghidra.trace.model.thread.TraceObjectThread; 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) { protected static ModelQuery successorThreads(TraceObjectSchema rootSchema, KeyPath path) {
TraceObjectSchema schema = rootSchema.getSuccessorSchema(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 { private static class ThreadPathColumn extends TraceValueKeyColumn {
@@ -246,7 +246,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class ThreadStateColumn extends TraceValueObjectAttributeColumn<String> { private static class ThreadStateColumn extends TraceValueObjectAttributeColumn<String> {
public ThreadStateColumn() { public ThreadStateColumn() {
// NB. The recorder converts enums to strings // NB. The recorder converts enums to strings
super(TraceObjectExecutionStateful.KEY_STATE, String.class); super(TraceExecutionStateful.KEY_STATE, String.class);
} }
@Override @Override
@@ -258,7 +258,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
private static class ThreadCommentColumn private static class ThreadCommentColumn
extends TraceValueObjectEditableAttributeColumn<String> { extends TraceValueObjectEditableAttributeColumn<String> {
public ThreadCommentColumn() { public ThreadCommentColumn() {
super(TraceObjectThread.KEY_COMMENT, String.class); super(TraceThread.KEY_COMMENT, String.class);
} }
@Override @Override
@@ -315,7 +315,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
}; };
public DebuggerThreadsPanel(DebuggerThreadsProvider provider) { public DebuggerThreadsPanel(DebuggerThreadsProvider provider) {
super(provider.plugin, provider, TraceObjectThread.class); super(provider.plugin, provider, TraceThread.class);
this.provider = provider; this.provider = provider;
setLimitToSnap(false); // TODO: Toggle for this? setLimitToSnap(false); // TODO: Toggle for this?
@@ -346,18 +346,18 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
protected ModelQuery computeQuery(TraceObject object) { protected ModelQuery computeQuery(TraceObject object) {
TraceObjectSchema rootSchema = object.getRoot().getSchema(); TraceObjectSchema rootSchema = object.getRoot().getSchema();
KeyPath seedPath = object.getCanonicalPath(); KeyPath seedPath = object.getCanonicalPath();
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath); KeyPath processPath = rootSchema.searchForAncestor(TraceProcess.class, seedPath);
if (processPath != null) { if (processPath != null) {
ModelQuery result = successorThreads(rootSchema, processPath); ModelQuery result = successorThreads(rootSchema, processPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return result; return result;
} }
} }
KeyPath containerPath = KeyPath containerPath =
rootSchema.searchForSuitableContainer(TraceObjectThread.class, seedPath); rootSchema.searchForSuitableContainer(TraceThread.class, seedPath);
if (containerPath != null) { if (containerPath != null) {
ModelQuery result = successorThreads(rootSchema, containerPath); ModelQuery result = successorThreads(rootSchema, containerPath);
if (!result.isEmpty()) { if (!result.isEmpty()) {
return result; return result;
} }
@@ -42,11 +42,15 @@ import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.bookmark.TraceBookmark; import ghidra.trace.model.bookmark.TraceBookmark;
import ghidra.trace.model.bookmark.TraceBookmarkManager; import ghidra.trace.model.bookmark.TraceBookmarkManager;
import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.memory.*; import ghidra.trace.model.breakpoint.TraceBreakpointManager;
import ghidra.trace.model.modules.*; 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.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.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher; import ghidra.util.classfinder.ClassSearcher;
@@ -74,7 +78,7 @@ import resources.ResourceManager;
) )
public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin { public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin {
@AutoServiceConsumed @AutoServiceConsumed
private DebuggerTraceManagerService traceManager; private DebuggerTraceManagerService traceManager;
@AutoServiceConsumed @AutoServiceConsumed
@@ -82,7 +86,6 @@ public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final AutoService.Wiring autoServiceWiring; private final AutoService.Wiring autoServiceWiring;
public static final String HELP_TOPIC = "OverviewPlugin"; public static final String HELP_TOPIC = "OverviewPlugin";
private static final String ACTIVE_SERVICES = "ActiveServices"; private static final String ACTIVE_SERVICES = "ActiveServices";
private List<TimeOverviewColorService> allServices; private List<TimeOverviewColorService> allServices;
@@ -270,27 +273,19 @@ public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin {
Trace trace = traceManager.getCurrentTrace(); Trace trace = traceManager.getCurrentTrace();
TraceThreadManager threadManager = trace.getThreadManager(); TraceThreadManager threadManager = trace.getThreadManager();
for (TraceThread thread : threadManager.getAllThreads()) { for (TraceThread thread : threadManager.getAllThreads()) {
if (thread instanceof TraceObjectThread objThread) { addObject(set, thread.getObject());
addObject(set, objThread.getObject());
}
} }
TraceModuleManager moduleManager = trace.getModuleManager(); TraceModuleManager moduleManager = trace.getModuleManager();
for (TraceModule module : moduleManager.getAllModules()) { for (TraceModule module : moduleManager.getAllModules()) {
if (module instanceof TraceObjectModule objModule) { addObject(set, module.getObject());
addObject(set, objModule.getObject());
}
} }
TraceMemoryManager memoryManager = trace.getMemoryManager(); TraceMemoryManager memoryManager = trace.getMemoryManager();
for (TraceMemoryRegion region : memoryManager.getAllRegions()) { for (TraceMemoryRegion region : memoryManager.getAllRegions()) {
if (region instanceof TraceObjectMemoryRegion objRegion) { addObject(set, region.getObject());
addObject(set, objRegion.getObject());
}
} }
TraceBreakpointManager breakpointManager = trace.getBreakpointManager(); TraceBreakpointManager breakpointManager = trace.getBreakpointManager();
for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) { for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) {
if (bpt instanceof TraceObjectBreakpointLocation objBreakpoint) { addObject(set, bpt.getObject());
addObject(set, objBreakpoint.getObject());
}
} }
TraceBookmarkManager bookmarkManager = trace.getBookmarkManager(); TraceBookmarkManager bookmarkManager = trace.getBookmarkManager();
for (TraceBookmark mark : bookmarkManager.getAllBookmarks()) { for (TraceBookmark mark : bookmarkManager.getAllBookmarks()) {
@@ -23,11 +23,15 @@ import ghidra.framework.model.DomainObjectChangeRecord;
import ghidra.framework.model.DomainObjectEvent; import ghidra.framework.model.DomainObjectEvent;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.bookmark.TraceBookmark; import ghidra.trace.model.bookmark.TraceBookmark;
import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.memory.*; import ghidra.trace.model.breakpoint.TraceBreakpointManager;
import ghidra.trace.model.modules.*; 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.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.trace.util.TraceEvents;
import ghidra.util.Swing; import ghidra.util.Swing;
@@ -118,193 +122,150 @@ public class TimeOverviewEventListener extends TraceDomainObjectListener {
regionChanged(region); regionChanged(region);
} }
TraceBreakpointManager breakpointManager = trace.getBreakpointManager(); TraceBreakpointManager breakpointManager = trace.getBreakpointManager();
for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) { for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) {
bptChanged(bpt); bptChanged(bpt);
} }
} }
private void threadAdded(TraceThread thread) {
if (!(thread instanceof TraceObjectThread objThread)) {
return;
}
TraceObject obj = objThread.getObject(); private void threadAdded(TraceThread thread) {
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) TraceObject obj = thread.getObject();
.forEach(v -> { obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
long snap = v.getMinSnap(); .forEach(v -> {
p.updateMap(snap, TimeType.BPT_ADDED, thread.getName(snap), true); long snap = v.getMinSnap();
}); p.updateMap(snap, TimeType.BPT_ADDED, thread.getName(snap), true);
});
} }
private void threadChanged(TraceThread thread) { private void threadChanged(TraceThread thread) {
if (!(thread instanceof TraceObjectThread objThread)) { TraceObject obj = thread.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceThread.KEY_TID, true).forEach(v -> {
} long snapMin = v.getMinSnap();
long snapMax = v.getMaxSnap();
TraceObject obj = objThread.getObject(); if (snapMin == snapMax) {
obj.getOrderedValues(Lifespan.ALL, TraceObjectThread.KEY_TID, true) p.updateMap(snapMin, TimeType.THREAD_CHANGED, thread.getName(snapMin),
.forEach(v -> { true);
long snapMin = v.getMinSnap(); }
long snapMax = v.getMaxSnap(); else {
if (snapMin == snapMax) { p.updateMap(snapMin, TimeType.THREAD_ADDED, thread.getName(snapMin), true);
p.updateMap(snapMin, TimeType.THREAD_CHANGED, thread.getName(snapMin), true); p.updateMap(snapMax, TimeType.THREAD_REMOVED, thread.getName(snapMax),
} 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) { private void threadDeleted(TraceThread thread) {
if (!(thread instanceof TraceObjectThread objThread)) { TraceObject obj = thread.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMaxSnap();
TraceObject obj = objThread.getObject(); p.updateMap(snap, TimeType.THREAD_REMOVED, thread.getName(snap), true);
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) });
.forEach(v -> {
long snap = v.getMaxSnap();
p.updateMap(snap, TimeType.THREAD_REMOVED, thread.getName(snap), true);
});
} }
private void moduleAdded(TraceModule module) { private void moduleAdded(TraceModule module) {
if (!(module instanceof TraceObjectModule objMod)) { TraceObject obj = module.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMinSnap();
TraceObject obj = objMod.getObject(); p.updateMap(snap, TimeType.MODULE_ADDED, module.getName(snap), true);
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) });
.forEach(v -> {
long snap = v.getMinSnap();
p.updateMap(snap, TimeType.MODULE_ADDED, module.getName(snap), true);
});
} }
private void moduleChanged(TraceModule module) { private void moduleChanged(TraceModule module) {
if (!(module instanceof TraceObjectModule objMod)) { TraceObject obj = module.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snapMin = v.getMinSnap();
TraceObject obj = objMod.getObject(); long snapMax = v.getMaxSnap();
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) if (snapMin == snapMax) {
.forEach(v -> { p.updateMap(snapMin, TimeType.MODULE_CHANGED, module.getName(snapMin),
long snapMin = v.getMinSnap(); true);
long snapMax = v.getMaxSnap(); }
if (snapMin == snapMax) { else {
p.updateMap(snapMin, TimeType.MODULE_CHANGED, module.getName(snapMin), true); p.updateMap(snapMin, TimeType.MODULE_ADDED, module.getName(snapMin), true);
} p.updateMap(snapMax, TimeType.MODULE_REMOVED, module.getName(snapMax),
else { true);
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) { private void moduleDeleted(TraceModule module) {
if (!(module instanceof TraceObjectModule objMod)) { TraceObject obj = module.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMaxSnap();
TraceObject obj = objMod.getObject(); p.updateMap(snap, TimeType.MODULE_REMOVED, module.getName(snap), true);
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) });
.forEach(v -> {
long snap = v.getMaxSnap();
p.updateMap(snap, TimeType.MODULE_REMOVED, module.getName(snap), true);
});
} }
private void regionAdded(TraceMemoryRegion region) { private void regionAdded(TraceMemoryRegion region) {
if (!(region instanceof TraceObjectMemoryRegion objReg)) { TraceObject obj = region.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMinSnap();
TraceObject obj = objReg.getObject(); p.updateMap(snap, TimeType.REGION_ADDED, region.getName(snap), true);
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) });
.forEach(v -> {
long snap = v.getMinSnap();
p.updateMap(snap, TimeType.REGION_ADDED, region.getName(snap), true);
});
} }
private void regionChanged(TraceMemoryRegion region) { private void regionChanged(TraceMemoryRegion region) {
if (!(region instanceof TraceObjectMemoryRegion objReg)) { TraceObject obj = region.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snapMin = v.getMinSnap();
TraceObject obj = objReg.getObject(); long snapMax = v.getMaxSnap();
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) if (snapMin == snapMax) {
.forEach(v -> { p.updateMap(snapMin, TimeType.REGION_CHANGED, region.getName(snapMin),
long snapMin = v.getMinSnap(); true);
long snapMax = v.getMaxSnap(); }
if (snapMin == snapMax) { else {
p.updateMap(snapMin, TimeType.REGION_CHANGED, region.getName(snapMin), true); p.updateMap(snapMin, TimeType.REGION_ADDED, region.getName(snapMin), true);
} p.updateMap(snapMax, TimeType.REGION_REMOVED, region.getName(snapMax),
else { true);
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) { private void regionDeleted(TraceMemoryRegion region) {
if (!(region instanceof TraceObjectMemoryRegion objReg)) { TraceObject obj = region.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMaxSnap();
TraceObject obj = objReg.getObject(); p.updateMap(snap, TimeType.REGION_REMOVED, region.getName(snap), true);
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) });
.forEach(v -> {
long snap = v.getMaxSnap();
p.updateMap(snap, TimeType.REGION_REMOVED, region.getName(snap), true);
});
} }
private void bptAdded(TraceBreakpoint bpt) { private void bptAdded(TraceBreakpointLocation bpt) {
if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) { TraceObject obj = bpt.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMinSnap();
TraceObject obj = objBpt.getObject(); p.updateMap(snap, TimeType.BPT_ADDED, bpt.getName(snap), true);
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 bptChanged(TraceBreakpoint bpt) { private void bptChanged(TraceBreakpointLocation bpt) {
if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) { TraceObject obj = bpt.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snapMin = v.getMinSnap();
TraceObject obj = objBpt.getObject(); long snapMax = v.getMaxSnap();
obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) if (snapMin == snapMax) {
.forEach(v -> { p.updateMap(snapMin, TimeType.BPT_CHANGED, bpt.getName(snapMin), true);
long snapMin = v.getMinSnap(); }
long snapMax = v.getMaxSnap(); else {
if (snapMin == snapMax) { p.updateMap(snapMin, TimeType.BPT_ADDED, bpt.getName(snapMin), true);
p.updateMap(snapMin, TimeType.BPT_CHANGED, bpt.getName(snapMin), true); p.updateMap(snapMax, TimeType.BPT_REMOVED, bpt.getName(snapMax), 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) { private void bptDeleted(TraceBreakpointLocation bpt) {
if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) { TraceObject obj = bpt.getObject();
return; obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true)
} .forEach(v -> {
long snap = v.getMaxSnap();
TraceObject obj = objBpt.getObject(); p.updateMap(snap, TimeType.BPT_REMOVED, bpt.getName(snap), true);
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 bookmarkAdded(TraceBookmark bookmark) { private void bookmarkAdded(TraceBookmark bookmark) {
@@ -78,7 +78,6 @@ import ghidra.trace.model.*;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
@@ -260,14 +259,14 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter
} }
} }
private void bytesChanged(TraceAddressSpace space, TraceAddressSnapRange range) { private void bytesChanged(AddressSpace space, TraceAddressSnapRange range) {
if (space.getThread() == current.getThread() || space.getThread() == null) { if (space.isMemorySpace() || current.isRegisterSpace(space)) {
addChanged(range.getRange()); addChanged(range.getRange());
} }
} }
private void stateChanged(TraceAddressSpace space, TraceAddressSnapRange range) { private void stateChanged(AddressSpace space, TraceAddressSnapRange range) {
if (space.getThread() == current.getThread() || space.getThread() == null) { if (space.isMemorySpace() || current.isRegisterSpace(space)) {
addChanged(range.getRange()); addChanged(range.getRange());
} }
} }
@@ -529,7 +529,7 @@ public class DefaultWatchRow implements WatchRow {
DebuggerCoordinates current = provider.current; DebuggerCoordinates current = provider.current;
Trace trace = current.getTrace(); Trace trace = current.getTrace();
Collection<? extends TraceLabelSymbol> labels = Collection<? extends TraceLabelSymbol> labels =
trace.getSymbolManager().labels().getAt(current.getSnap(), null, address, false); trace.getSymbolManager().labels().getAt(current.getSnap(), address, false);
if (!labels.isEmpty()) { if (!labels.isEmpty()) {
return labels.iterator().next(); return labels.iterator().next();
} }
@@ -22,7 +22,7 @@ import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObjectValue; 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.KeyPath;
import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.path.PathFilter;
import ghidra.util.Msg; import ghidra.util.Msg;
@@ -67,7 +67,7 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
} }
TraceObject root = object.getRoot(); TraceObject root = object.getRoot();
KeyPath pathToEnv = root.getSchema() KeyPath pathToEnv = root.getSchema()
.searchForSuitable(TraceObjectEnvironment.class, object.getCanonicalPath()); .searchForSuitable(TraceEnvironment.class, object.getCanonicalPath());
if (pathToEnv == null) { if (pathToEnv == null) {
return null; return null;
} }
@@ -86,15 +86,15 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
} }
static String getDebugggerFromEnv(TraceObject env, long snap) { 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) { 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) { 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 * @return the endianness, or null
*/ */
static Endian getEndianFromEnv(TraceObject env, long snap) { 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) { if (strEndian == null) {
return null; return null;
} }
@@ -20,7 +20,7 @@ import java.util.concurrent.CompletableFuture;
import ghidra.async.AsyncFence; import ghidra.async.AsyncFence;
import ghidra.debug.api.target.Target; 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 * 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 * Add an item to enable a target breakpoint
* *
* @param target the target * @param target the target
* @param bpt the target breakpoint * @param loc the target breakpoint
* @return the added item * @return the added item
*/ */
public EnableTargetBreakpointActionItem planEnableTarget(Target target, TraceBreakpoint bpt) { public EnableTargetBreakpointActionItem planEnableTarget(Target target,
EnableTargetBreakpointActionItem action = new EnableTargetBreakpointActionItem(target, bpt); TraceBreakpointLocation loc) {
EnableTargetBreakpointActionItem action = new EnableTargetBreakpointActionItem(target, loc);
add(action); add(action);
return action; return action;
} }
@@ -49,12 +50,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
/** /**
* Add an item to enable an emulated breakpoint * Add an item to enable an emulated breakpoint
* *
* @param bpt the trace breakpoint * @param loc the trace breakpoint
* @param snap the snap * @param snap the snap
* @return the added item * @return the added item
*/ */
public EnableEmuBreakpointActionItem planEnableEmu(TraceBreakpoint bpt, long snap) { public EnableEmuBreakpointActionItem planEnableEmu(TraceBreakpointLocation loc, long snap) {
EnableEmuBreakpointActionItem action = new EnableEmuBreakpointActionItem(bpt, snap); EnableEmuBreakpointActionItem action = new EnableEmuBreakpointActionItem(loc, snap);
add(action); add(action);
return action; return action;
} }
@@ -63,12 +64,13 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
* Add an item to disable a target breakpoint * Add an item to disable a target breakpoint
* *
* @param target the target * @param target the target
* @param bpt the target breakpoint * @param loc the target breakpoint
* @return the added item * @return the added item
*/ */
public DisableTargetBreakpointActionItem planDisableTarget(Target target, TraceBreakpoint bpt) { public DisableTargetBreakpointActionItem planDisableTarget(Target target,
TraceBreakpointLocation loc) {
DisableTargetBreakpointActionItem action = DisableTargetBreakpointActionItem action =
new DisableTargetBreakpointActionItem(target, bpt); new DisableTargetBreakpointActionItem(target, loc);
add(action); add(action);
return action; return action;
} }
@@ -76,12 +78,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
/** /**
* Add an item to disable an emulated breakpoint * Add an item to disable an emulated breakpoint
* *
* @param bpt the trace breakpoint * @param loc the trace breakpoint
* @param snap the snap * @param snap the snap
* @return the added item * @return the added item
*/ */
public DisableEmuBreakpointActionItem planDisableEmu(TraceBreakpoint bpt, long snap) { public DisableEmuBreakpointActionItem planDisableEmu(TraceBreakpointLocation loc, long snap) {
DisableEmuBreakpointActionItem action = new DisableEmuBreakpointActionItem(bpt, snap); DisableEmuBreakpointActionItem action = new DisableEmuBreakpointActionItem(loc, snap);
add(action); add(action);
return action; return action;
} }
@@ -90,11 +92,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
* Add an item to delete a target breakpoint * Add an item to delete a target breakpoint
* *
* @param target the target * @param target the target
* @param bpt the target breakpoint * @param loc the target breakpoint
* @return the added item * @return the added item
*/ */
public DeleteTargetBreakpointActionItem planDeleteTarget(Target target, TraceBreakpoint bpt) { public DeleteTargetBreakpointActionItem planDeleteTarget(Target target,
DeleteTargetBreakpointActionItem action = new DeleteTargetBreakpointActionItem(target, bpt); TraceBreakpointLocation loc) {
DeleteTargetBreakpointActionItem action = new DeleteTargetBreakpointActionItem(target, loc);
add(action); add(action);
return action; return action;
} }
@@ -102,12 +105,12 @@ public class BreakpointActionSet extends LinkedHashSet<BreakpointActionItem> {
/** /**
* Add an item to delete an emulated breakpoint * Add an item to delete an emulated breakpoint
* *
* @param bpt the trace breakpoint * @param loc the trace breakpoint
* @param snap the snap * @param snap the snap
* @return the added item * @return the added item
*/ */
public DeleteEmuBreakpointActionItem planDeleteEmu(TraceBreakpoint bpt, long snap) { public DeleteEmuBreakpointActionItem planDeleteEmu(TraceBreakpointLocation loc, long snap) {
DeleteEmuBreakpointActionItem action = new DeleteEmuBreakpointActionItem(bpt, snap); DeleteEmuBreakpointActionItem action = new DeleteEmuBreakpointActionItem(loc, snap);
add(action); add(action);
return action; return action;
} }
@@ -45,15 +45,13 @@ import ghidra.framework.model.*;
import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed; import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.framework.plugintool.util.PluginStatus; import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.address.Address; import ghidra.program.model.address.*;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.util.*; import ghidra.program.util.*;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
@@ -228,7 +226,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
info.reloadBreakpoints(c); info.reloadBreakpoints(c);
} }
private void breakpointAdded(TraceBreakpoint tb) { private void breakpointAdded(TraceBreakpointLocation tb) {
if (!tb.isValid(info.snap)) { if (!tb.isValid(info.snap)) {
return; 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)) { if (!tb.isValid(info.snap)) {
return; return;
} }
@@ -258,8 +256,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
} }
private void breakpointLifespanChanged(TraceAddressSpace spaceIsNull, TraceBreakpoint tb, private void breakpointLifespanChanged(AddressSpace spaceIsNull,
Lifespan oldSpan, Lifespan newSpan) { TraceBreakpointLocation tb, Lifespan oldSpan, Lifespan newSpan) {
// NOTE: User/script probably modified historical breakpoint // NOTE: User/script probably modified historical breakpoint
boolean isInOld = oldSpan.contains(info.snap); boolean isInOld = oldSpan.contains(info.snap);
boolean isInNew = newSpan.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 // Could check snap, but might as well just be sure it's gone
info.forgetTraceBreakpoint(c.r, tb); info.forgetTraceBreakpoint(c.r, tb);
} }
@@ -360,7 +358,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
long length, Collection<TraceBreakpointKind> kinds); long length, Collection<TraceBreakpointKind> kinds);
protected LogicalBreakpointInternal getOrCreateLogicalBreakpointFor(AddCollector a, protected LogicalBreakpointInternal getOrCreateLogicalBreakpointFor(AddCollector a,
Address address, TraceBreakpoint tb, long snap) throws TrackedTooSoonException { Address address, TraceBreakpointLocation tb, long snap)
throws TrackedTooSoonException {
Set<LogicalBreakpointInternal> set = Set<LogicalBreakpointInternal> set =
logicalByAddress.computeIfAbsent(address, __ -> new HashSet<>()); logicalByAddress.computeIfAbsent(address, __ -> new HashSet<>());
for (LogicalBreakpointInternal lb : set) { for (LogicalBreakpointInternal lb : set) {
@@ -377,7 +376,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
protected boolean removeLogicalBreakpoint(Address address, LogicalBreakpoint lb) { protected boolean removeLogicalBreakpoint(Address address, LogicalBreakpoint lb) {
for (TraceBreakpoint tb : lb.getTraceBreakpoints()) { for (TraceBreakpointLocation tb : lb.getTraceBreakpoints()) {
InfoPerTrace info = traceInfos.get(tb.getTrace()); InfoPerTrace info = traceInfos.get(tb.getTrace());
if (info != null) { if (info != null) {
info.logicalByBreakpoint.remove(tb); info.logicalByBreakpoint.remove(tb);
@@ -435,7 +434,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
protected class InfoPerTrace extends AbstractInfo { protected class InfoPerTrace extends AbstractInfo {
final Map<TraceBreakpoint, LogicalBreakpointInternal> logicalByBreakpoint = new HashMap<>(); final Map<TraceBreakpointLocation, LogicalBreakpointInternal> logicalByBreakpoint =
new HashMap<>();
final Trace trace; final Trace trace;
final TraceBreakpointsListener breakpointListener; final TraceBreakpointsListener breakpointListener;
@@ -486,12 +486,12 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
protected void forgetAllBreakpoints(RemoveCollector r) { protected void forgetAllBreakpoints(RemoveCollector r) {
Collection<TraceBreakpoint> toForget = new ArrayList<>(); Collection<TraceBreakpointLocation> toForget = new ArrayList<>();
for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) { for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) {
toForget.addAll( toForget.addAll(
trace.getBreakpointManager().getBreakpointsIntersecting(Lifespan.ALL, range)); trace.getBreakpointManager().getBreakpointsIntersecting(Lifespan.ALL, range));
} }
for (TraceBreakpoint tb : toForget) { for (TraceBreakpointLocation tb : toForget) {
forgetTraceBreakpoint(r, tb); forgetTraceBreakpoint(r, tb);
} }
} }
@@ -504,16 +504,16 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
*/ */
ControlMode mode = getMode(trace); ControlMode mode = getMode(trace);
for (Entry<TraceBreakpoint, LogicalBreakpointInternal> ent : Set for (Entry<TraceBreakpointLocation, LogicalBreakpointInternal> ent : Set
.copyOf(logicalByBreakpoint.entrySet())) { .copyOf(logicalByBreakpoint.entrySet())) {
TraceBreakpoint tb = ent.getKey(); TraceBreakpointLocation tb = ent.getKey();
LogicalBreakpoint lb = ent.getValue(); LogicalBreakpoint lb = ent.getValue();
if (!mode.useEmulatedBreakpoints() && if (!mode.useEmulatedBreakpoints() &&
(target == null || !target.isBreakpointValid(tb))) { (target == null || !target.isBreakpointValid(tb))) {
forgetTraceBreakpoint(r, tb); forgetTraceBreakpoint(r, tb);
continue; continue;
} }
if (!trace.getBreakpointManager().getAllBreakpoints().contains(tb)) { if (!trace.getBreakpointManager().getAllBreakpointLocations().contains(tb)) {
forgetTraceBreakpoint(r, tb); forgetTraceBreakpoint(r, tb);
continue; continue;
} }
@@ -536,7 +536,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
if (!mode.useEmulatedBreakpoints() && target == null) { if (!mode.useEmulatedBreakpoints() && target == null) {
return; return;
} }
Collection<TraceBreakpoint> visible = new ArrayList<>(); Collection<TraceBreakpointLocation> visible = new ArrayList<>();
for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) { for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) {
visible.addAll(trace.getBreakpointManager() visible.addAll(trace.getBreakpointManager()
.getBreakpointsIntersecting(Lifespan.at(snap), range)); .getBreakpointsIntersecting(Lifespan.at(snap), range));
@@ -545,8 +545,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
protected void trackTraceBreakpoints(AddCollector a, protected void trackTraceBreakpoints(AddCollector a,
Collection<TraceBreakpoint> breakpoints, ControlMode mode) { Collection<TraceBreakpointLocation> breakpoints, ControlMode mode) {
for (TraceBreakpoint tb : breakpoints) { for (TraceBreakpointLocation tb : breakpoints) {
try { try {
/** /**
* Sadly, even something as simple as toggling a breakpoint can cause so many * 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())) { if (traceManager == null || !traceManager.getOpenTraces().contains(tb.getTrace())) {
/** /**
* Mapping service will throw an exception otherwise. NB: When trace is opened, * 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)); 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 { boolean forceUpdate) throws TrackedTooSoonException {
if (!mode.useEmulatedBreakpoints() && if (!mode.useEmulatedBreakpoints() &&
(target == null || !target.isBreakpointValid(tb))) { (target == null || !target.isBreakpointValid(tb))) {
@@ -607,7 +608,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
protected LogicalBreakpointInternal removeFromLogicalBreakpoint(RemoveCollector r, protected LogicalBreakpointInternal removeFromLogicalBreakpoint(RemoveCollector r,
TraceBreakpoint tb) { TraceBreakpointLocation tb) {
LogicalBreakpointInternal lb = logicalByBreakpoint.remove(tb); LogicalBreakpointInternal lb = logicalByBreakpoint.remove(tb);
if (lb == null || !lb.untrackBreakpoint(tb)) { if (lb == null || !lb.untrackBreakpoint(tb)) {
return null; return null;
@@ -624,7 +625,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
return lb; return lb;
} }
protected void forgetTraceBreakpoint(RemoveCollector r, TraceBreakpoint tb) { protected void forgetTraceBreakpoint(RemoveCollector r, TraceBreakpointLocation tb) {
LogicalBreakpointInternal lb = removeFromLogicalBreakpoint(r, tb); LogicalBreakpointInternal lb = removeFromLogicalBreakpoint(r, tb);
if (lb == null) { if (lb == null) {
return; // Warnings already logged return; // Warnings already logged
@@ -1114,7 +1115,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
@Override @Override
public LogicalBreakpoint getBreakpoint(TraceBreakpoint bpt) { public LogicalBreakpoint getBreakpoint(TraceBreakpointLocation bpt) {
Trace trace = bpt.getTrace(); Trace trace = bpt.getTrace();
synchronized (lock) { synchronized (lock) {
InfoPerTrace info = traceInfos.get(trace); InfoPerTrace info = traceInfos.get(trace);
@@ -1271,18 +1272,18 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
interface TargetBreakpointConsumer { interface TargetBreakpointConsumer {
void accept(BreakpointActionSet actions, Target target, TraceBreakpoint tb); void accept(BreakpointActionSet actions, Target target, TraceBreakpointLocation tb);
} }
interface EmuBreakpointConsumer { interface EmuBreakpointConsumer {
void accept(BreakpointActionSet actions, TraceBreakpoint tb, long snap); void accept(BreakpointActionSet actions, TraceBreakpointLocation tb, long snap);
} }
interface ProgramBreakpointConsumer { interface ProgramBreakpointConsumer {
void accept(LogicalBreakpoint lb); void accept(LogicalBreakpoint lb);
} }
private void planActOnLoc(BreakpointActionSet actions, TraceBreakpoint tb, private void planActOnLoc(BreakpointActionSet actions, TraceBreakpointLocation tb,
TargetBreakpointConsumer targetBptConsumer, EmuBreakpointConsumer emuLocConsumer) { TargetBreakpointConsumer targetBptConsumer, EmuBreakpointConsumer emuLocConsumer) {
ControlMode mode = getMode(tb.getTrace()); ControlMode mode = getMode(tb.getTrace());
if (mode.useEmulatedBreakpoints()) { 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) { TargetBreakpointConsumer targetBptConsumer) {
Target target = targetService == null ? null : targetService.getTarget(tb.getTrace()); Target target = targetService == null ? null : targetService.getTarget(tb.getTrace());
if (target == null) { if (target == null) {
@@ -1302,7 +1303,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
targetBptConsumer.accept(actions, target, tb); targetBptConsumer.accept(actions, target, tb);
} }
private void planActOnLocEmu(BreakpointActionSet actions, TraceBreakpoint tb, private void planActOnLocEmu(BreakpointActionSet actions, TraceBreakpointLocation tb,
EmuBreakpointConsumer emuLocConsumer) { EmuBreakpointConsumer emuLocConsumer) {
InfoPerTrace info = traceInfos.get(tb.getTrace()); InfoPerTrace info = traceInfos.get(tb.getTrace());
if (info == null) { if (info == null) {
@@ -1312,12 +1313,12 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
emuLocConsumer.accept(actions, tb, info.snap); emuLocConsumer.accept(actions, tb, info.snap);
} }
protected CompletableFuture<Void> actOnLocs(Collection<TraceBreakpoint> col, protected CompletableFuture<Void> actOnLocs(Collection<TraceBreakpointLocation> col,
TargetBreakpointConsumer targetBptConsumer, TargetBreakpointConsumer targetBptConsumer,
EmuBreakpointConsumer emuLocConsumer, EmuBreakpointConsumer emuLocConsumer,
ProgramBreakpointConsumer progConsumer) { ProgramBreakpointConsumer progConsumer) {
BreakpointActionSet actions = new BreakpointActionSet(); BreakpointActionSet actions = new BreakpointActionSet();
for (TraceBreakpoint tb : col) { for (TraceBreakpointLocation tb : col) {
LogicalBreakpoint lb = getBreakpoint(tb); LogicalBreakpoint lb = getBreakpoint(tb);
if (col.containsAll(lb.getTraceBreakpoints())) { if (col.containsAll(lb.getTraceBreakpoints())) {
progConsumer.accept(lb); progConsumer.accept(lb);
@@ -1328,19 +1329,19 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
} }
@Override @Override
public CompletableFuture<Void> enableLocs(Collection<TraceBreakpoint> col) { public CompletableFuture<Void> enableLocs(Collection<TraceBreakpointLocation> col) {
return actOnLocs(col, BreakpointActionSet::planEnableTarget, return actOnLocs(col, BreakpointActionSet::planEnableTarget,
BreakpointActionSet::planEnableEmu, LogicalBreakpoint::enableForProgram); BreakpointActionSet::planEnableEmu, LogicalBreakpoint::enableForProgram);
} }
@Override @Override
public CompletableFuture<Void> disableLocs(Collection<TraceBreakpoint> col) { public CompletableFuture<Void> disableLocs(Collection<TraceBreakpointLocation> col) {
return actOnLocs(col, BreakpointActionSet::planDisableTarget, return actOnLocs(col, BreakpointActionSet::planDisableTarget,
BreakpointActionSet::planDisableEmu, LogicalBreakpoint::disableForProgram); BreakpointActionSet::planDisableEmu, LogicalBreakpoint::disableForProgram);
} }
@Override @Override
public CompletableFuture<Void> deleteLocs(Collection<TraceBreakpoint> col) { public CompletableFuture<Void> deleteLocs(Collection<TraceBreakpointLocation> col) {
return actOnLocs(col, BreakpointActionSet::planDeleteTarget, return actOnLocs(col, BreakpointActionSet::planDeleteTarget,
BreakpointActionSet::planDeleteEmu, lb -> { BreakpointActionSet::planDeleteEmu, lb -> {
// Never delete bookmark when user requests deleting locations // Never delete bookmark when user requests deleting locations

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