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

View file

@ -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
*/ */

View file

@ -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

View file

@ -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;

View file

@ -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.

View file

@ -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) {
} }
} }

View file

@ -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()

View file

@ -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;

View file

@ -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) {

View file

@ -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;
} }

View file

@ -24,11 +24,11 @@ import com.sun.jdi.*;
import com.sun.jdi.request.*; import com.sun.jdi.request.*;
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.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.rmi.trace.TraceRmi.MemoryState; import ghidra.rmi.trace.TraceRmi.MemoryState;
import ghidra.trace.model.target.iface.TraceObjectMethod.Param; import ghidra.trace.model.target.iface.TraceMethod.Param;
import ghidra.util.Msg; import ghidra.util.Msg;
public class JdiMethods implements RmiMethods { public class JdiMethods implements RmiMethods {
@ -45,14 +45,14 @@ public class JdiMethods implements RmiMethods {
public void registerMethods() { public void registerMethods() {
Class<?> cls = this.getClass(); Class<?> cls = this.getClass();
for (java.lang.reflect.Method m : cls.getMethods()) { for (java.lang.reflect.Method m : cls.getMethods()) {
TraceMethod annot = m.getAnnotation(TraceMethod.class); TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class);
if (annot != null) { if (annot != null) {
connector.registerRemoteMethod(this, m, m.getName()); connector.registerRemoteMethod(this, m, m.getName());
} }
} }
} }
@TraceMethod(action = "refresh", display = "Refresh VM") @TraceRmiMethod(action = "refresh", display = "Refresh VM")
public void refresh_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void refresh_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVM")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVM")) {
String path = obj.getPath(); String path = obj.getPath();
@ -61,7 +61,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh process") @TraceRmiMethod(action = "refresh", display = "Refresh process")
public void refresh_process( public void refresh_process(
@Param(schema = "ProcessRef", name = "process") RmiTraceObject obj) { @Param(schema = "ProcessRef", name = "process") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshProcess")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshProcess")) {
@ -71,7 +71,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh thread groups") @TraceRmiMethod(action = "refresh", display = "Refresh thread groups")
public void refresh_thread_groups( public void refresh_thread_groups(
@Param( @Param(
schema = "ThreadGroupReferenceContainer", schema = "ThreadGroupReferenceContainer",
@ -89,7 +89,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh thread group") @TraceRmiMethod(action = "refresh", display = "Refresh thread group")
public void refresh_thread_group_proxy( public void refresh_thread_group_proxy(
@Param(schema = "ThreadGroupReferenceProxy", name = "proxy") RmiTraceObject obj) { @Param(schema = "ThreadGroupReferenceProxy", name = "proxy") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) {
@ -105,7 +105,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh thread group") @TraceRmiMethod(action = "refresh", display = "Refresh thread group")
public void refresh_thread_group( public void refresh_thread_group(
@Param(schema = "ThreadGroupReference", name = "group") RmiTraceObject obj) { @Param(schema = "ThreadGroupReference", name = "group") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) {
@ -115,7 +115,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh threads") @TraceRmiMethod(action = "refresh", display = "Refresh threads")
public void refresh_threads( public void refresh_threads(
@Param(schema = "ThreadContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ThreadContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) {
@ -126,7 +126,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh threads") @TraceRmiMethod(action = "refresh", display = "Refresh threads")
public void refresh_threadrefs( public void refresh_threadrefs(
@Param(schema = "ThreadReferenceContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ThreadReferenceContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) {
@ -147,7 +147,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh thread") @TraceRmiMethod(action = "refresh", display = "Refresh thread")
public void refresh_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void refresh_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThread")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThread")) {
String path = obj.getPath(); String path = obj.getPath();
@ -156,14 +156,14 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh stack") @TraceRmiMethod(action = "refresh", display = "Refresh stack")
public void refresh_stack(@Param(schema = "Stack", name = "stack") RmiTraceObject obj) { public void refresh_stack(@Param(schema = "Stack", name = "stack") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshStack")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshStack")) {
cmds.ghidraTracePutFrames(); cmds.ghidraTracePutFrames();
} }
} }
@TraceMethod(action = "refresh", display = "Refresh registers") @TraceRmiMethod(action = "refresh", display = "Refresh registers")
public void refresh_registers( public void refresh_registers(
@Param(schema = "RegisterContainer", name = "container") RmiTraceObject obj) { @Param(schema = "RegisterContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshRegisters")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshRegisters")) {
@ -171,7 +171,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh modules") @TraceRmiMethod(action = "refresh", display = "Refresh modules")
public void refresh_modules( public void refresh_modules(
@Param(schema = "ModuleReferenceContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ModuleReferenceContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModules")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModules")) {
@ -179,7 +179,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh module") @TraceRmiMethod(action = "refresh", display = "Refresh module")
public void refresh_module( public void refresh_module(
@Param(schema = "ModuleReference", name = "module") RmiTraceObject obj) { @Param(schema = "ModuleReference", name = "module") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModule")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModule")) {
@ -189,7 +189,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh monitor info") @TraceRmiMethod(action = "refresh", display = "Refresh monitor info")
public void refresh_monitors( public void refresh_monitors(
@Param(schema = "MonitorInfoContainer", name = "container") RmiTraceObject obj) { @Param(schema = "MonitorInfoContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) {
@ -203,7 +203,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh monitor info") @TraceRmiMethod(action = "refresh", display = "Refresh monitor info")
public void refresh_monitor_info( public void refresh_monitor_info(
@Param(schema = "MonitorInfo", name = "monitor_info") RmiTraceObject obj) { @Param(schema = "MonitorInfo", name = "monitor_info") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) {
@ -213,13 +213,13 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh fields") @TraceRmiMethod(action = "refresh", display = "Refresh fields")
public void refresh_canonical_fields( public void refresh_canonical_fields(
@Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) { @Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) {
refresh_fields(obj); refresh_fields(obj);
} }
@TraceMethod(action = "refresh", display = "Refresh fields") @TraceRmiMethod(action = "refresh", display = "Refresh fields")
public void refresh_fields( public void refresh_fields(
@Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) { @Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshFields")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshFields")) {
@ -235,7 +235,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh objects") @TraceRmiMethod(action = "refresh", display = "Refresh objects")
public void refresh_objects( public void refresh_objects(
@Param(schema = "ObjectReferenceContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ObjectReferenceContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObjects")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObjects")) {
@ -261,7 +261,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh object") @TraceRmiMethod(action = "refresh", display = "Refresh object")
public void refresh_object_proxy( public void refresh_object_proxy(
@Param(schema = "ObjectReferenceProxy", name = "proxy") RmiTraceObject obj) { @Param(schema = "ObjectReferenceProxy", name = "proxy") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObject")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObject")) {
@ -283,7 +283,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh object") @TraceRmiMethod(action = "refresh", display = "Refresh object")
public void refresh_object( public void refresh_object(
@Param(schema = "ObjectReference", name = "object") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "object") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshInstance")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshInstance")) {
@ -293,13 +293,13 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh methods") @TraceRmiMethod(action = "refresh", display = "Refresh methods")
public void refresh_canonical_methods( public void refresh_canonical_methods(
@Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) { @Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) {
refresh_methods(obj); refresh_methods(obj);
} }
@TraceMethod(action = "refresh", display = "Refresh methods") @TraceRmiMethod(action = "refresh", display = "Refresh methods")
public void refresh_methods( public void refresh_methods(
@Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) { @Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethods")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethods")) {
@ -310,7 +310,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh method") @TraceRmiMethod(action = "refresh", display = "Refresh method")
public void refresh_method(@Param(schema = "Method", name = "method") RmiTraceObject obj) { public void refresh_method(@Param(schema = "Method", name = "method") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethod")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethod")) {
String path = obj.getPath(); String path = obj.getPath();
@ -319,7 +319,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh arguments") @TraceRmiMethod(action = "refresh", display = "Refresh arguments")
public void refresh_arguments( public void refresh_arguments(
@Param(schema = "ArgumentContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ArgumentContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshArguments")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshArguments")) {
@ -330,7 +330,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Load class") @TraceRmiMethod(display = "Load class")
public boolean find_canonical_class( public boolean find_canonical_class(
@Param( @Param(
schema = "CanonicalReferenceTypeContainer", schema = "CanonicalReferenceTypeContainer",
@ -344,7 +344,7 @@ public class JdiMethods implements RmiMethods {
return find_class(obj, targetClass); return find_class(obj, targetClass);
} }
@TraceMethod(display = "Load class") @TraceRmiMethod(display = "Load class")
public boolean find_class( public boolean find_class(
@Param( @Param(
schema = "ReferenceTypeContainer", schema = "ReferenceTypeContainer",
@ -370,12 +370,12 @@ public class JdiMethods implements RmiMethods {
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action * NB. Did not assign action="refresh" because this method is expensive. Assigning that action
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want. * name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
*/ */
@TraceMethod(display = "Refresh memory") @TraceRmiMethod(display = "Refresh memory")
public void refresh_memory(@Param(schema = "Memory", name = "memory") RmiTraceObject obj) { public void refresh_memory(@Param(schema = "Memory", name = "memory") RmiTraceObject obj) {
refresh_reference_types(obj); refresh_reference_types(obj);
} }
@TraceMethod(display = "Refresh reference types") @TraceRmiMethod(display = "Refresh reference types")
public void refresh_canonical_reference_types( public void refresh_canonical_reference_types(
@Param( @Param(
schema = "CanonicalReferenceTypeContainer", schema = "CanonicalReferenceTypeContainer",
@ -387,7 +387,7 @@ public class JdiMethods implements RmiMethods {
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action * NB. Did not assign action="refresh" because this method is expensive. Assigning that action
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want. * name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
*/ */
@TraceMethod(display = "Refresh reference types") @TraceRmiMethod(display = "Refresh reference types")
public void refresh_reference_types( public void refresh_reference_types(
@Param(schema = "ReferenceTypeContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ReferenceTypeContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceTypes")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceTypes")) {
@ -430,7 +430,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh reference type") @TraceRmiMethod(action = "refresh", display = "Refresh reference type")
public void refresh_reference_type_proxy( public void refresh_reference_type_proxy(
@Param(schema = "ReferenceTypeProxy", name = "proxy") RmiTraceObject obj) { @Param(schema = "ReferenceTypeProxy", name = "proxy") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
@ -452,13 +452,13 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh reference type") @TraceRmiMethod(action = "refresh", display = "Refresh reference type")
public void refresh_canonical_reference_type( public void refresh_canonical_reference_type(
@Param(schema = "CanonicalReferenceType", name = "container") RmiTraceObject obj) { @Param(schema = "CanonicalReferenceType", name = "container") RmiTraceObject obj) {
refresh_reference_type(obj); refresh_reference_type(obj);
} }
@TraceMethod(action = "refresh", display = "Refresh reference type") @TraceRmiMethod(action = "refresh", display = "Refresh reference type")
public void refresh_reference_type( public void refresh_reference_type(
@Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
@ -468,7 +468,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Load reference type") @TraceRmiMethod(display = "Load reference type")
public void load_reftype( public void load_reftype(
@Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
@ -480,13 +480,13 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh variables") @TraceRmiMethod(action = "refresh", display = "Refresh variables")
public void refresh_canonical_variables( public void refresh_canonical_variables(
@Param(schema = "CanonicalVariableContainer", name = "container") RmiTraceObject obj) { @Param(schema = "CanonicalVariableContainer", name = "container") RmiTraceObject obj) {
refresh_variables(obj); refresh_variables(obj);
} }
@TraceMethod(action = "refresh", display = "Refresh variables") @TraceRmiMethod(action = "refresh", display = "Refresh variables")
public void refresh_variables( public void refresh_variables(
@Param(schema = "VariableContainer", name = "container") RmiTraceObject obj) { @Param(schema = "VariableContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariables")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariables")) {
@ -513,7 +513,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh variable") @TraceRmiMethod(action = "refresh", display = "Refresh variable")
public void refresh_variable( public void refresh_variable(
@Param(schema = "Variable", name = "variable") RmiTraceObject obj) { @Param(schema = "Variable", name = "variable") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariable")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariable")) {
@ -525,7 +525,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh locations") @TraceRmiMethod(action = "refresh", display = "Refresh locations")
public void refresh_locations( public void refresh_locations(
@Param(schema = "LocationContainer", name = "container") RmiTraceObject obj) { @Param(schema = "LocationContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocations")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocations")) {
@ -543,7 +543,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh location") @TraceRmiMethod(action = "refresh", display = "Refresh location")
public void refresh_location( public void refresh_location(
@Param(schema = "Location", name = "location") RmiTraceObject obj) { @Param(schema = "Location", name = "location") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) {
@ -553,7 +553,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh breakpoints") @TraceRmiMethod(action = "refresh", display = "Refresh breakpoints")
public void refresh_breakpoints( public void refresh_breakpoints(
@Param(schema = "BreakpointContainer", name = "container") RmiTraceObject obj) { @Param(schema = "BreakpointContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshBreakpoints")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshBreakpoints")) {
@ -561,7 +561,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh events") @TraceRmiMethod(action = "refresh", display = "Refresh events")
public void refresh_events( public void refresh_events(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshEvents")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshEvents")) {
@ -569,7 +569,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh values") @TraceRmiMethod(action = "refresh", display = "Refresh values")
public void refresh_values( public void refresh_values(
@Param(schema = "ValueContainer", name = "container") RmiTraceObject obj) { @Param(schema = "ValueContainer", name = "container") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshValues")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshValues")) {
@ -582,7 +582,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "refresh", display = "Refresh value") @TraceRmiMethod(action = "refresh", display = "Refresh value")
public void refresh_value(@Param(schema = "Value", name = "value") RmiTraceObject obj) { public void refresh_value(@Param(schema = "Value", name = "value") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) {
String path = obj.getPath(); String path = obj.getPath();
@ -591,7 +591,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Set value") @TraceRmiMethod(display = "Set value")
public void set_value_lvar( public void set_value_lvar(
@Param( @Param(
schema = "Variable", schema = "Variable",
@ -609,7 +609,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Set value") @TraceRmiMethod(display = "Set value")
public void set_value_field( public void set_value_field(
@Param( @Param(
schema = "Field", schema = "Field",
@ -627,7 +627,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "activate", display = "Activate") @TraceRmiMethod(action = "activate", display = "Activate")
public void activate(@Param(schema = "OBJECT", name = "object") RmiTraceObject obj) { public void activate(@Param(schema = "OBJECT", name = "object") RmiTraceObject obj) {
try (RmiTransaction tx = cmds.state.trace.openTx("Activate")) { try (RmiTransaction tx = cmds.state.trace.openTx("Activate")) {
String path = obj.getPath(); String path = obj.getPath();
@ -635,7 +635,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "kill", display = "Terminate") @TraceRmiMethod(action = "kill", display = "Terminate")
public void kill(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void kill(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath()); VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
vm.exit(143); vm.exit(143);
@ -647,28 +647,28 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "resume", display = "Resume") @TraceRmiMethod(action = "resume", display = "Resume")
public void resume_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void resume_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath()); VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
vm.resume(); vm.resume();
connector.getHooks().setState(vm); connector.getHooks().setState(vm);
} }
@TraceMethod(action = "resume", display = "Resume") @TraceRmiMethod(action = "resume", display = "Resume")
public void resume_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void resume_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
thread.resume(); thread.resume();
connector.getHooks().setState(thread.virtualMachine()); connector.getHooks().setState(thread.virtualMachine());
} }
@TraceMethod(action = "interrupt", display = "Suspend") @TraceRmiMethod(action = "interrupt", display = "Suspend")
public void suspend_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void suspend_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath()); VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
vm.suspend(); vm.suspend();
connector.getHooks().setState(vm); connector.getHooks().setState(vm);
} }
@TraceMethod(action = "interrupt", display = "Suspend") @TraceRmiMethod(action = "interrupt", display = "Suspend")
public void suspend_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void suspend_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
thread.suspend(); thread.suspend();
@ -679,7 +679,7 @@ public class JdiMethods implements RmiMethods {
* NB: For the VirtualMachine, the step methods add requests for break-on-step for all threads. * NB: For the VirtualMachine, the step methods add requests for break-on-step for all threads.
* These requests will remain pending until the VM is resumed. * These requests will remain pending until the VM is resumed.
*/ */
@TraceMethod(action = "step_into", display = "Step into") @TraceRmiMethod(action = "step_into", display = "Step into")
public void step_vm_into(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void step_vm_into(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
List<ThreadReference> threads = getThreadsFromValue(obj); List<ThreadReference> threads = getThreadsFromValue(obj);
@ -697,7 +697,7 @@ public class JdiMethods implements RmiMethods {
vm.resume(); vm.resume();
} }
@TraceMethod(action = "step_over", display = "Step over") @TraceRmiMethod(action = "step_over", display = "Step over")
public void step_vm_over(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void step_vm_over(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
List<ThreadReference> threads = getThreadsFromValue(obj); List<ThreadReference> threads = getThreadsFromValue(obj);
@ -715,7 +715,7 @@ public class JdiMethods implements RmiMethods {
vm.resume(); vm.resume();
} }
@TraceMethod(action = "step_out", display = "Step out") @TraceRmiMethod(action = "step_out", display = "Step out")
public void step_vm_out(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void step_vm_out(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
List<ThreadReference> threads = getThreadsFromValue(obj); List<ThreadReference> threads = getThreadsFromValue(obj);
@ -733,7 +733,7 @@ public class JdiMethods implements RmiMethods {
vm.resume(); vm.resume();
} }
@TraceMethod(action = "step_into", display = "Step into") @TraceRmiMethod(action = "step_into", display = "Step into")
public void step_into(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void step_into(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
@ -744,7 +744,7 @@ public class JdiMethods implements RmiMethods {
vm.resume(); vm.resume();
} }
@TraceMethod(action = "step_over", display = "Step over") @TraceRmiMethod(action = "step_over", display = "Step over")
public void step_over(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void step_over(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
@ -755,7 +755,7 @@ public class JdiMethods implements RmiMethods {
vm.resume(); vm.resume();
} }
@TraceMethod(action = "step_out", display = "Step out") @TraceRmiMethod(action = "step_out", display = "Step out")
public void step_out(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void step_out(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
@ -766,7 +766,7 @@ public class JdiMethods implements RmiMethods {
vm.resume(); vm.resume();
} }
@TraceMethod(display = "Thread Interrupt") @TraceRmiMethod(display = "Thread Interrupt")
public void thread_interrupt(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void thread_interrupt(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
Object object = getObjectFromPath(obj.getPath()); Object object = getObjectFromPath(obj.getPath());
if (object instanceof ThreadReference thread) { if (object instanceof ThreadReference thread) {
@ -775,7 +775,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "step_ext", display = "Pop stack") @TraceRmiMethod(action = "step_ext", display = "Pop stack")
public void pop_stack(@Param(schema = "StackFrame", name = "frame") RmiTraceObject obj) { public void pop_stack(@Param(schema = "StackFrame", name = "frame") RmiTraceObject obj) {
StackFrame frame = (StackFrame) getObjectFromPath(obj.getPath()); StackFrame frame = (StackFrame) getObjectFromPath(obj.getPath());
ThreadReference thread = frame.thread(); ThreadReference thread = frame.thread();
@ -787,7 +787,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Break on execute") @TraceRmiMethod(display = "Break on execute")
public void break_location(@Param(schema = "Location", name = "location") RmiTraceObject obj) { public void break_location(@Param(schema = "Location", name = "location") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
Object ctxt = getObjectFromPath(obj.getPath()); Object ctxt = getObjectFromPath(obj.getPath());
@ -799,7 +799,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Break on access") @TraceRmiMethod(display = "Break on access")
public void break_access(@Param(schema = "Field", name = "field") RmiTraceObject obj) { public void break_access(@Param(schema = "Field", name = "field") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
Object ctxt = getObjectFromPath(obj.getPath()); Object ctxt = getObjectFromPath(obj.getPath());
@ -811,7 +811,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Break on modify") @TraceRmiMethod(display = "Break on modify")
public void break_modify(@Param(schema = "Field", name = "field") RmiTraceObject obj) { public void break_modify(@Param(schema = "Field", name = "field") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
Object ctxt = getObjectFromPath(obj.getPath()); Object ctxt = getObjectFromPath(obj.getPath());
@ -823,7 +823,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Break on exception") @TraceRmiMethod(display = "Break on exception")
public void break_exception( public void break_exception(
@Param( @Param(
schema = "ReferenceType", schema = "ReferenceType",
@ -861,13 +861,13 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on thread start") @TraceRmiMethod(display = "Break on thread start")
public void break_started_container( public void break_started_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_started(obj); break_started(obj);
} }
@TraceMethod(display = "Break on thread start") @TraceRmiMethod(display = "Break on thread start")
public void break_started_thread( public void break_started_thread(
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { @Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_started(obj); break_started(obj);
@ -886,18 +886,18 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on thread exit") @TraceRmiMethod(display = "Break on thread exit")
public void break_death_container( public void break_death_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_death(obj); break_death(obj);
} }
@TraceMethod(display = "Break on thread exit") @TraceRmiMethod(display = "Break on thread exit")
public void break_death_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void break_death_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_death(obj); break_death(obj);
} }
@TraceMethod(display = "Break on VM death") @TraceRmiMethod(display = "Break on VM death")
public void break_vm_death(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { public void break_vm_death(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
VMDeathRequest brkReq = vm.eventRequestManager() VMDeathRequest brkReq = vm.eventRequestManager()
@ -927,25 +927,25 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on method enter") @TraceRmiMethod(display = "Break on method enter")
public void break_enter_container( public void break_enter_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_enter(obj); break_enter(obj);
} }
@TraceMethod(display = "Break on method enter") @TraceRmiMethod(display = "Break on method enter")
public void break_enter_reftype( public void break_enter_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_enter(obj); break_enter(obj);
} }
@TraceMethod(display = "Break on method enter") @TraceRmiMethod(display = "Break on method enter")
public void break_enter_instance( public void break_enter_instance(
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
break_enter(obj); break_enter(obj);
} }
@TraceMethod(display = "Break on method enter") @TraceRmiMethod(display = "Break on method enter")
public void break_enter_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void break_enter_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_enter(obj); break_enter(obj);
} }
@ -971,25 +971,25 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on method exit") @TraceRmiMethod(display = "Break on method exit")
public void break_exit_container( public void break_exit_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_exit(obj); break_exit(obj);
} }
@TraceMethod(display = "Break on method exit") @TraceRmiMethod(display = "Break on method exit")
public void break_exit_reftype( public void break_exit_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_exit(obj); break_exit(obj);
} }
@TraceMethod(display = "Break on method exit") @TraceRmiMethod(display = "Break on method exit")
public void break_exit_instance( public void break_exit_instance(
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
break_exit(obj); break_exit(obj);
} }
@TraceMethod(display = "Break on method exit") @TraceRmiMethod(display = "Break on method exit")
public void break_exit_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { public void break_exit_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_exit(obj); break_exit(obj);
} }
@ -1007,13 +1007,13 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on class load") @TraceRmiMethod(display = "Break on class load")
public void break_load_container( public void break_load_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_load(obj); break_load(obj);
} }
@TraceMethod(display = "Break on class load") @TraceRmiMethod(display = "Break on class load")
public void break_load_reftype( public void break_load_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_load(obj); break_load(obj);
@ -1027,7 +1027,7 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on class unload") @TraceRmiMethod(display = "Break on class unload")
public void break_unload_container( public void break_unload_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_unload(obj); break_unload(obj);
@ -1054,25 +1054,25 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on monitor contended enter") @TraceRmiMethod(display = "Break on monitor contended enter")
public void break_mon_enter_contention_container( public void break_mon_enter_contention_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_mon_enter_contention(obj); break_mon_enter_contention(obj);
} }
@TraceMethod(display = "Break on monitor contended enter") @TraceRmiMethod(display = "Break on monitor contended enter")
public void break_mon_enter_contention_reftype( public void break_mon_enter_contention_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_mon_enter_contention(obj); break_mon_enter_contention(obj);
} }
@TraceMethod(display = "Break on monitor contended enter") @TraceRmiMethod(display = "Break on monitor contended enter")
public void break_mon_enter_contention_instance( public void break_mon_enter_contention_instance(
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
break_mon_enter_contention(obj); break_mon_enter_contention(obj);
} }
@TraceMethod(display = "Break on monitor contended enter") @TraceRmiMethod(display = "Break on monitor contended enter")
public void break_mon_enter_contention_thread( public void break_mon_enter_contention_thread(
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { @Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_mon_enter_contention(obj); break_mon_enter_contention(obj);
@ -1099,25 +1099,25 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on monitor contented entered") @TraceRmiMethod(display = "Break on monitor contented entered")
public void break_mon_entered_contention_container( public void break_mon_entered_contention_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_mon_entered_contention(obj); break_mon_entered_contention(obj);
} }
@TraceMethod(display = "Break on monitor contented entered") @TraceRmiMethod(display = "Break on monitor contented entered")
public void break_mon_entered_contention_reftype( public void break_mon_entered_contention_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_mon_entered_contention(obj); break_mon_entered_contention(obj);
} }
@TraceMethod(display = "Break on monitor contented entered") @TraceRmiMethod(display = "Break on monitor contented entered")
public void break_mon_entered_contention_instance( public void break_mon_entered_contention_instance(
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
break_mon_entered_contention(obj); break_mon_entered_contention(obj);
} }
@TraceMethod(display = "Break on monitor contented entered") @TraceRmiMethod(display = "Break on monitor contented entered")
public void break_mon_entered_contention_thread( public void break_mon_entered_contention_thread(
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { @Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_mon_entered_contention(obj); break_mon_entered_contention(obj);
@ -1144,25 +1144,25 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on monitor wait") @TraceRmiMethod(display = "Break on monitor wait")
public void break_mon_wait_container( public void break_mon_wait_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_mon_wait(obj); break_mon_wait(obj);
} }
@TraceMethod(display = "Break on monitor wait") @TraceRmiMethod(display = "Break on monitor wait")
public void break_mon_wait_reftype( public void break_mon_wait_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_mon_wait(obj); break_mon_wait(obj);
} }
@TraceMethod(display = "Break on monitor wait") @TraceRmiMethod(display = "Break on monitor wait")
public void break_mon_wait_instance( public void break_mon_wait_instance(
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
break_mon_wait(obj); break_mon_wait(obj);
} }
@TraceMethod(display = "Break on monitor wait") @TraceRmiMethod(display = "Break on monitor wait")
public void break_mon_wait_thread( public void break_mon_wait_thread(
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { @Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_mon_wait(obj); break_mon_wait(obj);
@ -1189,31 +1189,31 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Break on monitor waited") @TraceRmiMethod(display = "Break on monitor waited")
public void break_mon_waited_container( public void break_mon_waited_container(
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
break_mon_waited(obj); break_mon_waited(obj);
} }
@TraceMethod(display = "Break on monitor waited") @TraceRmiMethod(display = "Break on monitor waited")
public void break_mon_waited_reftype( public void break_mon_waited_reftype(
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
break_mon_waited(obj); break_mon_waited(obj);
} }
@TraceMethod(display = "Break on monitor waited") @TraceRmiMethod(display = "Break on monitor waited")
public void break_mon_waited_instance( public void break_mon_waited_instance(
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
break_mon_waited(obj); break_mon_waited(obj);
} }
@TraceMethod(display = "Break on monitor waited") @TraceRmiMethod(display = "Break on monitor waited")
public void break_mon_waited_thread( public void break_mon_waited_thread(
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { @Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
break_mon_waited(obj); break_mon_waited(obj);
} }
@TraceMethod(display = "Add count filter") @TraceRmiMethod(display = "Add count filter")
public void add_count_filter( public void add_count_filter(
@Param( @Param(
schema = "Event", schema = "Event",
@ -1234,7 +1234,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Set class filter") @TraceRmiMethod(display = "Set class filter")
public void set_class_filter( public void set_class_filter(
@Param( @Param(
schema = "Event", schema = "Event",
@ -1349,7 +1349,7 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Set source filter") @TraceRmiMethod(display = "Set source filter")
public void set_source_filter( public void set_source_filter(
@Param( @Param(
schema = "Event", schema = "Event",
@ -1370,7 +1370,7 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(display = "Set platform filter") @TraceRmiMethod(display = "Set platform filter")
public void set_platform_filter(@Param(schema = "Event", name = "event") RmiTraceObject obj) { public void set_platform_filter(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
Object ctxt = getObjectFromPath(obj.getPath()); Object ctxt = getObjectFromPath(obj.getPath());
if (ctxt instanceof ThreadStartRequest req) { if (ctxt instanceof ThreadStartRequest req) {
@ -1388,7 +1388,7 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(action = "toggle", display = "Toggle breakpoint") @TraceRmiMethod(action = "toggle", display = "Toggle breakpoint")
public void toggle_breakpoint( public void toggle_breakpoint(
@Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) { @Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
@ -1409,7 +1409,7 @@ public class JdiMethods implements RmiMethods {
cmds.putBreakpoints(); cmds.putBreakpoints();
} }
@TraceMethod(action = "delete", display = "Delete breakpoint") @TraceRmiMethod(action = "delete", display = "Delete breakpoint")
public void delete_breakpoint( public void delete_breakpoint(
@Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) { @Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
@ -1420,7 +1420,7 @@ public class JdiMethods implements RmiMethods {
cmds.putBreakpoints(); cmds.putBreakpoints();
} }
@TraceMethod(action = "toggle", display = "Toggle event") @TraceRmiMethod(action = "toggle", display = "Toggle event")
public void toggle_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) { public void toggle_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
Object ctxt = getObjectFromPath(obj.getPath()); Object ctxt = getObjectFromPath(obj.getPath());
if (ctxt instanceof EventRequest req) { if (ctxt instanceof EventRequest req) {
@ -1434,7 +1434,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "delete", display = "Delete Event") @TraceRmiMethod(action = "delete", display = "Delete Event")
public void delete_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) { public void delete_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
VirtualMachine vm = connector.getJdi().getCurrentVM(); VirtualMachine vm = connector.getJdi().getCurrentVM();
Object ctxt = getObjectFromPath(obj.getPath()); Object ctxt = getObjectFromPath(obj.getPath());
@ -1444,13 +1444,13 @@ public class JdiMethods implements RmiMethods {
cmds.putEvents(); cmds.putEvents();
} }
@TraceMethod(action = "toggle", display = "Toggle scope") @TraceRmiMethod(action = "toggle", display = "Toggle scope")
public void toggle_scope_canonical_methods( public void toggle_scope_canonical_methods(
@Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) { @Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) {
toggle_scope_methods(obj); toggle_scope_methods(obj);
} }
@TraceMethod(action = "toggle", display = "Toggle scope") @TraceRmiMethod(action = "toggle", display = "Toggle scope")
public void toggle_scope_methods( public void toggle_scope_methods(
@Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) { @Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) {
String ppath = cmds.getParentPath(obj.getPath()); String ppath = cmds.getParentPath(obj.getPath());
@ -1459,13 +1459,13 @@ public class JdiMethods implements RmiMethods {
refresh_methods(obj); refresh_methods(obj);
} }
@TraceMethod(action = "toggle", display = "Toggle scope") @TraceRmiMethod(action = "toggle", display = "Toggle scope")
public void toggle_scope_canonical_fields( public void toggle_scope_canonical_fields(
@Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) { @Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) {
toggle_scope_fields(obj); toggle_scope_fields(obj);
} }
@TraceMethod(action = "toggle", display = "Toggle scope") @TraceRmiMethod(action = "toggle", display = "Toggle scope")
public void toggle_scope_fields( public void toggle_scope_fields(
@Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) { @Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) {
String ppath = cmds.getParentPath(obj.getPath()); String ppath = cmds.getParentPath(obj.getPath());
@ -1479,7 +1479,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(action = "read_mem", display = "Read Memory") @TraceRmiMethod(action = "read_mem", display = "Read Memory")
public long read_mem( public long read_mem(
@Param( @Param(
schema = "VirtualMachine", schema = "VirtualMachine",
@ -1503,7 +1503,7 @@ public class JdiMethods implements RmiMethods {
return range.getLength(); return range.getLength();
} }
@TraceMethod(display = "Invoke method (no args)") @TraceRmiMethod(display = "Invoke method (no args)")
public void execute_on_instance( public void execute_on_instance(
@Param( @Param(
schema = "ObjectReference", schema = "ObjectReference",
@ -1531,7 +1531,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Invoke static method (no args)") @TraceRmiMethod(display = "Invoke static method (no args)")
public void execute_on_class( public void execute_on_class(
@Param( @Param(
schema = "ReferenceType", schema = "ReferenceType",
@ -1565,7 +1565,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Invoke method (no args)") @TraceRmiMethod(display = "Invoke method (no args)")
public void execute_method( public void execute_method(
@Param( @Param(
schema = "Method", schema = "Method",
@ -1596,7 +1596,7 @@ public class JdiMethods implements RmiMethods {
} }
} }
@TraceMethod(display = "Invoke static method (no args)") @TraceRmiMethod(display = "Invoke static method (no args)")
public void execute_static_method( public void execute_static_method(
@Param( @Param(
schema = "Method", schema = "Method",

View file

@ -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 "";

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -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);
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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()));

View file

@ -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;
} }
} }

View file

@ -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());
} }
} }

View file

@ -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);
} }

View file

@ -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();

View file

@ -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 "";
} }

View file

@ -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();
} }

View file

@ -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()) {

View file

@ -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);

View file

@ -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;
} }

View file

@ -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;

View file

@ -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()) {

View file

@ -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;

View file

@ -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;
} }

View file

@ -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

View file

@ -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;

View file

@ -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);
} }

View file

@ -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);
} }
/** /**

View file

@ -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();
} }
} }

View file

@ -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;
} }

View file

@ -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()) {

View file

@ -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) {

View file

@ -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());
} }
} }

View file

@ -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();
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -19,20 +19,20 @@ import java.util.concurrent.CompletableFuture;
import db.Transaction; import db.Transaction;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public record DeleteEmuBreakpointActionItem(TraceBreakpoint bpt, long snap) public record DeleteEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap)
implements BreakpointActionItem { implements BreakpointActionItem {
@Override @Override
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
try (Transaction tx = try (Transaction tx =
bpt.getTrace().openTransaction("Delete Emulated Breakpoint")) { loc.getTrace().openTransaction("Delete Emulated Breakpoint")) {
String emuName = PlaceEmuBreakpointActionItem.createName(bpt.getMinAddress(snap)); String emuName = PlaceEmuBreakpointActionItem.createName(loc.getMinAddress(snap));
if (bpt.getPath().contains(emuName)) { if (loc.getPath().contains(emuName)) {
bpt.delete(); loc.delete();
} }
else { else {
bpt.setEmuEnabled(snap, false); loc.setEmuEnabled(snap, false);
} }
} }
return AsyncUtils.nil(); return AsyncUtils.nil();

View file

@ -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,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import ghidra.debug.api.target.Target; import ghidra.debug.api.target.Target;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public record DeleteTargetBreakpointActionItem(Target target, TraceBreakpoint bpt) public record DeleteTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc)
implements BreakpointActionItem { implements BreakpointActionItem {
@Override @Override
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
return target.deleteBreakpointAsync(bpt); return target.deleteBreakpointAsync(loc);
} }
} }

View file

@ -19,15 +19,15 @@ import java.util.concurrent.CompletableFuture;
import db.Transaction; import db.Transaction;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public record DisableEmuBreakpointActionItem(TraceBreakpoint bpt, long snap) public record DisableEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap)
implements BreakpointActionItem { implements BreakpointActionItem {
@Override @Override
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
try (Transaction tx = try (Transaction tx =
bpt.getTrace().openTransaction("Disable Emulated Breakpoint")) { loc.getTrace().openTransaction("Disable Emulated Breakpoint")) {
bpt.setEmuEnabled(snap, false); loc.setEmuEnabled(snap, false);
} }
return AsyncUtils.nil(); return AsyncUtils.nil();
} }

View file

@ -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,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import ghidra.debug.api.target.Target; import ghidra.debug.api.target.Target;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public record DisableTargetBreakpointActionItem(Target target, TraceBreakpoint bpt) public record DisableTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc)
implements BreakpointActionItem { implements BreakpointActionItem {
@Override @Override
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
return target.toggleBreakpointAsync(bpt, false); return target.toggleBreakpointAsync(loc, false);
} }
} }

View file

@ -19,15 +19,15 @@ import java.util.concurrent.CompletableFuture;
import db.Transaction; import db.Transaction;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public record EnableEmuBreakpointActionItem(TraceBreakpoint bpt, long snap) public record EnableEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap)
implements BreakpointActionItem { implements BreakpointActionItem {
@Override @Override
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
try (Transaction tx = try (Transaction tx =
bpt.getTrace().openTransaction("Enable Emulated Breakpoint")) { loc.getTrace().openTransaction("Enable Emulated Breakpoint")) {
bpt.setEmuEnabled(snap, true); loc.setEmuEnabled(snap, true);
} }
return AsyncUtils.nil(); return AsyncUtils.nil();
} }

View file

@ -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,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import ghidra.debug.api.target.Target; import ghidra.debug.api.target.Target;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public record EnableTargetBreakpointActionItem(Target target, TraceBreakpoint bpt) public record EnableTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc)
implements BreakpointActionItem { implements BreakpointActionItem {
@Override @Override
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
return target.toggleBreakpointAsync(bpt, true); return target.toggleBreakpointAsync(loc, true);
} }
} }

View file

@ -21,7 +21,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Bookmark; import ghidra.program.model.listing.Bookmark;
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.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
public interface LogicalBreakpointInternal extends LogicalBreakpoint { public interface LogicalBreakpointInternal extends LogicalBreakpoint {
/** /**
@ -60,13 +60,13 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint {
* @return true if it can be aggregated. * @return true if it can be aggregated.
* @throws TrackedTooSoonException if the containing trace is still being added to the manager * @throws TrackedTooSoonException if the containing trace is still being added to the manager
*/ */
boolean canMerge(TraceBreakpoint breakpoint, long snap) throws TrackedTooSoonException; boolean canMerge(TraceBreakpointLocation breakpoint, long snap) throws TrackedTooSoonException;
boolean trackBreakpoint(Bookmark bookmark); boolean trackBreakpoint(Bookmark bookmark);
boolean trackBreakpoint(TraceBreakpoint breakpoint); boolean trackBreakpoint(TraceBreakpointLocation breakpoint);
boolean untrackBreakpoint(TraceBreakpoint breakpoint); boolean untrackBreakpoint(TraceBreakpointLocation breakpoint);
boolean untrackBreakpoint(Program program, Bookmark bookmark); boolean untrackBreakpoint(Program program, Bookmark bookmark);

View file

@ -27,8 +27,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;
public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
private final Set<Trace> justThisTrace; private final Set<Trace> justThisTrace;
@ -111,12 +111,12 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public Set<TraceBreakpoint> getTraceBreakpoints() { public Set<TraceBreakpointLocation> getTraceBreakpoints() {
return breaks.getBreakpoints(); return breaks.getBreakpoints();
} }
@Override @Override
public Set<TraceBreakpoint> getTraceBreakpoints(Trace trace) { public Set<TraceBreakpointLocation> getTraceBreakpoints(Trace trace) {
return breaks.getTrace() != trace ? Set.of() : getTraceBreakpoints(); return breaks.getTrace() != trace ? Set.of() : getTraceBreakpoints();
} }
@ -165,7 +165,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public State computeStateForLocation(TraceBreakpoint loc) { public State computeStateForLocation(TraceBreakpointLocation loc) {
if (!breaks.getBreakpoints().contains(loc)) { if (!breaks.getBreakpoints().contains(loc)) {
return State.NONE; return State.NONE;
} }
@ -278,7 +278,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public boolean canMerge(TraceBreakpoint breakpoint, long snap) { public boolean canMerge(TraceBreakpointLocation breakpoint, long snap) {
if (!Objects.equals(kinds, breakpoint.getKinds(snap))) { if (!Objects.equals(kinds, breakpoint.getKinds(snap))) {
return false; return false;
} }
@ -291,7 +291,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public boolean trackBreakpoint(TraceBreakpoint breakpoint) { public boolean trackBreakpoint(TraceBreakpointLocation breakpoint) {
return breaks.add(breakpoint); return breaks.add(breakpoint);
} }
@ -301,7 +301,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public boolean untrackBreakpoint(TraceBreakpoint breakpoint) { public boolean untrackBreakpoint(TraceBreakpointLocation breakpoint) {
return breaks.remove(breakpoint); return breaks.remove(breakpoint);
} }
} }

View file

@ -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;
public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
@ -309,8 +309,8 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public Set<TraceBreakpoint> getTraceBreakpoints() { public Set<TraceBreakpointLocation> getTraceBreakpoints() {
Set<TraceBreakpoint> result = new HashSet<>(); Set<TraceBreakpointLocation> result = new HashSet<>();
synchronized (traceBreaks) { synchronized (traceBreaks) {
for (TraceBreakpointSet breaks : traceBreaks.values()) { for (TraceBreakpointSet breaks : traceBreaks.values()) {
result.addAll(breaks.getBreakpoints()); result.addAll(breaks.getBreakpoints());
@ -320,7 +320,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public Set<TraceBreakpoint> getTraceBreakpoints(Trace trace) { public Set<TraceBreakpointLocation> getTraceBreakpoints(Trace trace) {
TraceBreakpointSet breaks; TraceBreakpointSet breaks;
synchronized (traceBreaks) { synchronized (traceBreaks) {
breaks = traceBreaks.get(trace); breaks = traceBreaks.get(trace);
@ -400,7 +400,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
return progMode.combineTrace(traceMode, Perspective.TRACE); return progMode.combineTrace(traceMode, Perspective.TRACE);
} }
protected TraceMode computeTraceModeForLocation(TraceBreakpoint loc) { protected TraceMode computeTraceModeForLocation(TraceBreakpointLocation loc) {
TraceBreakpointSet breaks; TraceBreakpointSet breaks;
synchronized (traceBreaks) { synchronized (traceBreaks) {
breaks = traceBreaks.get(loc.getTrace()); breaks = traceBreaks.get(loc.getTrace());
@ -412,7 +412,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public State computeStateForLocation(TraceBreakpoint loc) { public State computeStateForLocation(TraceBreakpointLocation loc) {
ProgramMode progMode = progBreak.computeMode(); ProgramMode progMode = progBreak.computeMode();
TraceMode traceMode = computeTraceModeForLocation(loc); TraceMode traceMode = computeTraceModeForLocation(loc);
return progMode.combineTrace(traceMode, Perspective.TRACE); return progMode.combineTrace(traceMode, Perspective.TRACE);
@ -478,7 +478,8 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public boolean canMerge(TraceBreakpoint breakpoint, long snap) throws TrackedTooSoonException { public boolean canMerge(TraceBreakpointLocation breakpoint, long snap)
throws TrackedTooSoonException {
TraceBreakpointSet breaks; TraceBreakpointSet breaks;
synchronized (traceBreaks) { synchronized (traceBreaks) {
breaks = traceBreaks.get(breakpoint.getTrace()); breaks = traceBreaks.get(breakpoint.getTrace());
@ -530,7 +531,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public boolean trackBreakpoint(TraceBreakpoint breakpoint) { public boolean trackBreakpoint(TraceBreakpointLocation breakpoint) {
TraceBreakpointSet breaks; TraceBreakpointSet breaks;
synchronized (traceBreaks) { synchronized (traceBreaks) {
breaks = traceBreaks.get(breakpoint.getTrace()); breaks = traceBreaks.get(breakpoint.getTrace());
@ -556,7 +557,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal {
} }
@Override @Override
public boolean untrackBreakpoint(TraceBreakpoint breakpoint) { public boolean untrackBreakpoint(TraceBreakpointLocation breakpoint) {
TraceBreakpointSet breaks; TraceBreakpointSet breaks;
synchronized (traceBreaks) { synchronized (traceBreaks) {
breaks = traceBreaks.get(breakpoint.getTrace()); breaks = traceBreaks.get(breakpoint.getTrace());

View file

@ -26,7 +26,6 @@ import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.*;
import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
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.path.PathFilter; import ghidra.trace.model.target.path.PathFilter;
@ -49,42 +48,37 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
this.emuSleigh = emuSleigh; this.emuSleigh = emuSleigh;
} }
private TraceObjectMemoryRegion findRegion() { private TraceMemoryRegion findRegion() {
TraceMemoryRegion region = trace.getMemoryManager().getRegionContaining(snap, address); TraceMemoryRegion region = trace.getMemoryManager().getRegionContaining(snap, address);
if (region != null) { if (region != null) {
return (TraceObjectMemoryRegion) region; return region;
} }
AddressSpace space = address.getAddressSpace(); AddressSpace space = address.getAddressSpace();
Collection<? extends TraceMemoryRegion> regionsInSpace = trace.getMemoryManager() Collection<? extends TraceMemoryRegion> regionsInSpace = trace.getMemoryManager()
.getRegionsIntersecting(Lifespan.at(snap), .getRegionsIntersecting(Lifespan.at(snap),
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress())); new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()));
if (!regionsInSpace.isEmpty()) { if (!regionsInSpace.isEmpty()) {
return (TraceObjectMemoryRegion) regionsInSpace.iterator().next(); return regionsInSpace.iterator().next();
} }
return null; return null;
} }
private TraceObject findBreakpointContainer() { private TraceObject findBreakpointContainer() {
TraceObjectMemoryRegion region = findRegion(); TraceMemoryRegion region = findRegion();
if (region == null) { if (region == null) {
throw new IllegalArgumentException("Address does not belong to a memory in the trace"); throw new IllegalArgumentException("Address does not belong to a memory in the trace");
} }
return region.getObject() return region.getObject().findSuitableContainerInterface(TraceBreakpointSpec.class);
.findSuitableContainerInterface(TraceObjectBreakpointSpec.class);
} }
private String computePath() { private String computePath() {
String name = createName(address); String name = createName(address);
if (Trace.isLegacy(trace)) {
return "Breakpoints[" + name + "]";
}
TraceObject container = findBreakpointContainer(); TraceObject container = findBreakpointContainer();
if (container == null) { if (container == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Address is not associated with a breakpoint container"); "Address is not associated with a breakpoint container");
} }
PathFilter specFilter = PathFilter specFilter = container.getSchema().searchFor(TraceBreakpointSpec.class, true);
container.getSchema().searchFor(TraceObjectBreakpointSpec.class, true);
if (specFilter == null) { if (specFilter == null) {
throw new IllegalArgumentException("Cannot find path to breakpoint specifications"); throw new IllegalArgumentException("Cannot find path to breakpoint specifications");
} }
@ -94,7 +88,7 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
} }
PathFilter locFilter = container.getSchema() PathFilter locFilter = container.getSchema()
.getSuccessorSchema(specRelPath) .getSuccessorSchema(specRelPath)
.searchFor(TraceObjectBreakpointLocation.class, true); .searchFor(TraceBreakpointLocation.class, true);
if (locFilter == null) { if (locFilter == null) {
throw new IllegalArgumentException("Cannot find path to breakpoint locations"); throw new IllegalArgumentException("Cannot find path to breakpoint locations");
} }
@ -109,11 +103,11 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
public CompletableFuture<Void> execute() { public CompletableFuture<Void> execute() {
try (Transaction tx = trace.openTransaction("Place Emulated Breakpoint")) { try (Transaction tx = trace.openTransaction("Place Emulated Breakpoint")) {
// Defaults with emuEnable=true // Defaults with emuEnable=true
TraceBreakpoint bpt = trace.getBreakpointManager() TraceBreakpointLocation loc = trace.getBreakpointManager()
.addBreakpoint(computePath(), Lifespan.at(snap), .addBreakpoint(computePath(), Lifespan.at(snap),
BreakpointActionItem.range(address, length), Set.of(), kinds, false, null); BreakpointActionItem.range(address, length), Set.of(), kinds, false, null);
bpt.setName(snap, createName(address)); loc.setName(snap, createName(address));
bpt.setEmuSleigh(snap, emuSleigh); loc.setEmuSleigh(snap, emuSleigh);
return AsyncUtils.nil(); return AsyncUtils.nil();
} }
catch (DuplicateNameException e) { catch (DuplicateNameException e) {

View file

@ -28,8 +28,8 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.pcode.exec.SleighUtils; import ghidra.pcode.exec.SleighUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
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 utilities.util.IDHashed; import utilities.util.IDHashed;
/** /**
@ -45,7 +45,7 @@ class TraceBreakpointSet {
private final Trace trace; private final Trace trace;
private final Address address; private final Address address;
private final Set<IDHashed<TraceBreakpoint>> breakpoints = new HashSet<>(); private final Set<IDHashed<TraceBreakpointLocation>> breakpoints = new HashSet<>();
private Target target; private Target target;
private String emuSleigh; private String emuSleigh;
@ -120,8 +120,8 @@ class TraceBreakpointSet {
* *
* <p> * <p>
* In most cases, there is 0 or 1 trace breakpoints that "fit" the logical breakpoint. The mode * In most cases, there is 0 or 1 trace breakpoints that "fit" the logical breakpoint. The mode
* is derived from one of {@link TraceBreakpoint#isEnabled(long)} or * is derived from one of {@link TraceBreakpointLocation#isEnabled(long)} or
* {@link TraceBreakpoint#isEmuEnabled(long)}, depending on the UI's control mode for this * {@link TraceBreakpointLocation#isEmuEnabled(long)}, depending on the UI's control mode for this
* trace. * trace.
* *
* @return the mode * @return the mode
@ -130,7 +130,7 @@ class TraceBreakpointSet {
TraceMode mode = TraceMode.NONE; TraceMode mode = TraceMode.NONE;
synchronized (breakpoints) { synchronized (breakpoints) {
if (getControlMode().useEmulatedBreakpoints()) { if (getControlMode().useEmulatedBreakpoints()) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
mode = mode.combine(computeEmuMode(bpt.obj)); mode = mode.combine(computeEmuMode(bpt.obj));
if (mode == TraceMode.MISSING) { if (mode == TraceMode.MISSING) {
return mode; return mode;
@ -138,7 +138,7 @@ class TraceBreakpointSet {
} }
return mode; return mode;
} }
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
mode = mode.combine(computeTargetMode(bpt.obj)); mode = mode.combine(computeTargetMode(bpt.obj));
if (mode == TraceMode.MISSING) { if (mode == TraceMode.MISSING) {
return mode; return mode;
@ -152,14 +152,14 @@ class TraceBreakpointSet {
* Compute the mode (enablement) of the given breakpoint * Compute the mode (enablement) of the given breakpoint
* *
* <p> * <p>
* The mode is derived from one of {@link TraceBreakpoint#isEnabled(long)} or * The mode is derived from one of {@link TraceBreakpointLocation#isEnabled(long)} or
* {@link TraceBreakpoint#isEmuEnabled(long)}, depending on the UI's control mode for this * {@link TraceBreakpointLocation#isEmuEnabled(long)}, depending on the UI's control mode for this
* trace. * trace.
* *
* @param bpt the breakpoint * @param bpt the breakpoint
* @return the mode * @return the mode
*/ */
public TraceMode computeMode(TraceBreakpoint bpt) { public TraceMode computeMode(TraceBreakpointLocation bpt) {
return getControlMode().useEmulatedBreakpoints() return getControlMode().useEmulatedBreakpoints()
? computeEmuMode(bpt) ? computeEmuMode(bpt)
: computeTargetMode(bpt); : computeTargetMode(bpt);
@ -171,7 +171,7 @@ class TraceBreakpointSet {
* @param bpt the breakpoint * @param bpt the breakpoint
* @return the mode * @return the mode
*/ */
public TraceMode computeTargetMode(TraceBreakpoint bpt) { public TraceMode computeTargetMode(TraceBreakpointLocation bpt) {
return TraceMode.fromBool(bpt.isEnabled(getSnap())); return TraceMode.fromBool(bpt.isEnabled(getSnap()));
} }
@ -181,7 +181,7 @@ class TraceBreakpointSet {
* @param bpt the breakpoint * @param bpt the breakpoint
* @return the mode * @return the mode
*/ */
public TraceMode computeEmuMode(TraceBreakpoint bpt) { public TraceMode computeEmuMode(TraceBreakpointLocation bpt) {
return TraceMode.fromBool(bpt.isEmuEnabled(getSnap())); return TraceMode.fromBool(bpt.isEmuEnabled(getSnap()));
} }
@ -194,7 +194,7 @@ class TraceBreakpointSet {
String sleigh = null; String sleigh = null;
long snap = getSnap(); long snap = getSnap();
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
String s = bpt.obj.getEmuSleigh(snap); String s = bpt.obj.getEmuSleigh(snap);
if (sleigh != null && !sleigh.equals(s)) { if (sleigh != null && !sleigh.equals(s)) {
return null; return null;
@ -215,7 +215,7 @@ class TraceBreakpointSet {
long snap = getSnap(); long snap = getSnap();
try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) { try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
bpt.obj.setEmuSleigh(snap, emuSleigh); bpt.obj.setEmuSleigh(snap, emuSleigh);
} }
} }
@ -238,7 +238,7 @@ class TraceBreakpointSet {
* *
* @return the breakpoints * @return the breakpoints
*/ */
public Set<TraceBreakpoint> getBreakpoints() { public Set<TraceBreakpointLocation> getBreakpoints() {
synchronized (breakpoints) { synchronized (breakpoints) {
return breakpoints.stream().map(e -> e.obj).collect(Collectors.toUnmodifiableSet()); return breakpoints.stream().map(e -> e.obj).collect(Collectors.toUnmodifiableSet());
} }
@ -248,13 +248,13 @@ class TraceBreakpointSet {
* Add a breakpoint to this set * Add a breakpoint to this set
* *
* <p> * <p>
* The caller should first call {@link #canMerge(TraceBreakpoint)} to check if the breakpoint * The caller should first call {@link #canMerge(TraceBreakpointLocation)} to check if the breakpoint
* "fits." * "fits."
* *
* @param bpt the breakpoint * @param bpt the breakpoint
* @return true if the set actually changed as a result * @return true if the set actually changed as a result
*/ */
public boolean add(TraceBreakpoint bpt) { public boolean add(TraceBreakpointLocation bpt) {
long snap = getSnap(); long snap = getSnap();
if (SleighUtils.UNCONDITIONAL_BREAK.equals(bpt.getEmuSleigh(snap)) && emuSleigh != null) { if (SleighUtils.UNCONDITIONAL_BREAK.equals(bpt.getEmuSleigh(snap)) && emuSleigh != null) {
try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) { try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) {
@ -275,7 +275,7 @@ class TraceBreakpointSet {
* @param bpt the breakpoint * @param bpt the breakpoint
* @return true if it fits * @return true if it fits
*/ */
public boolean canMerge(TraceBreakpoint bpt) { public boolean canMerge(TraceBreakpointLocation bpt) {
if (trace != bpt.getTrace()) { if (trace != bpt.getTrace()) {
return false; return false;
} }
@ -291,7 +291,7 @@ class TraceBreakpointSet {
* @param bpt the breakpoint * @param bpt the breakpoint
* @return true if the set actually changes as a result * @return true if the set actually changes as a result
*/ */
public boolean remove(TraceBreakpoint bpt) { public boolean remove(TraceBreakpointLocation bpt) {
synchronized (breakpoints) { synchronized (breakpoints) {
return breakpoints.remove(new IDHashed<>(bpt)); return breakpoints.remove(new IDHashed<>(bpt));
} }
@ -359,7 +359,7 @@ class TraceBreakpointSet {
private void planEnableTarget(BreakpointActionSet actions) { private void planEnableTarget(BreakpointActionSet actions) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
actions.planEnableTarget(target, bpt.obj); actions.planEnableTarget(target, bpt.obj);
} }
} }
@ -367,7 +367,7 @@ class TraceBreakpointSet {
private void planEnableEmu(BreakpointActionSet actions) { private void planEnableEmu(BreakpointActionSet actions) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
actions.planEnableEmu(bpt.obj, getSnap()); actions.planEnableEmu(bpt.obj, getSnap());
} }
} }
@ -393,7 +393,7 @@ class TraceBreakpointSet {
private void planDisableTarget(BreakpointActionSet actions, long length, private void planDisableTarget(BreakpointActionSet actions, long length,
Collection<TraceBreakpointKind> kinds) { Collection<TraceBreakpointKind> kinds) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
actions.planDisableTarget(target, bpt.obj); actions.planDisableTarget(target, bpt.obj);
} }
} }
@ -401,7 +401,7 @@ class TraceBreakpointSet {
private void planDisableEmu(BreakpointActionSet actions) { private void planDisableEmu(BreakpointActionSet actions) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
actions.planDisableEmu(bpt.obj, getSnap()); actions.planDisableEmu(bpt.obj, getSnap());
} }
} }
@ -427,7 +427,7 @@ class TraceBreakpointSet {
private void planDeleteTarget(BreakpointActionSet actions, long length, private void planDeleteTarget(BreakpointActionSet actions, long length,
Set<TraceBreakpointKind> kinds) { Set<TraceBreakpointKind> kinds) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
actions.planDeleteTarget(target, bpt.obj); actions.planDeleteTarget(target, bpt.obj);
} }
} }
@ -435,7 +435,7 @@ class TraceBreakpointSet {
private void planDeleteEmu(BreakpointActionSet actions) { private void planDeleteEmu(BreakpointActionSet actions) {
synchronized (breakpoints) { synchronized (breakpoints) {
for (IDHashed<TraceBreakpoint> bpt : breakpoints) { for (IDHashed<TraceBreakpointLocation> bpt : breakpoints) {
actions.planDeleteEmu(bpt.obj, getSnap()); actions.planDeleteEmu(bpt.obj, getSnap());
} }
} }

View file

@ -18,7 +18,7 @@ package ghidra.app.plugin.core.debug.service.emulation;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.swing.Icon; import javax.swing.Icon;
@ -45,6 +45,7 @@ import ghidra.async.AsyncLazyMap;
import ghidra.debug.api.control.ControlMode; import ghidra.debug.api.control.ControlMode;
import ghidra.debug.api.emulation.DebuggerPcodeEmulatorFactory; import ghidra.debug.api.emulation.DebuggerPcodeEmulatorFactory;
import ghidra.debug.api.emulation.DebuggerPcodeMachine; import ghidra.debug.api.emulation.DebuggerPcodeMachine;
import ghidra.debug.api.modules.DebuggerStaticMappingChangeListener;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed; import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
@ -638,7 +639,7 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm
Lifespan span = Lifespan.at(snap); Lifespan span = Lifespan.at(snap);
TraceBreakpointManager bm = trace.getBreakpointManager(); TraceBreakpointManager bm = trace.getBreakpointManager();
for (AddressSpace as : trace.getBaseAddressFactory().getAddressSpaces()) { for (AddressSpace as : trace.getBaseAddressFactory().getAddressSpaces()) {
for (TraceBreakpoint bpt : bm.getBreakpointsIntersecting(span, for (TraceBreakpointLocation bpt : bm.getBreakpointsIntersecting(span,
new AddressRangeImpl(as.getMinAddress(), as.getMaxAddress()))) { new AddressRangeImpl(as.getMinAddress(), as.getMaxAddress()))) {
if (!bpt.isEmuEnabled(snap)) { if (!bpt.isEmuEnabled(snap)) {
continue; continue;
@ -797,14 +798,43 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm
} }
} }
class TraceMappingWaiter extends CompletableFuture<Void>
implements DebuggerStaticMappingChangeListener {
private final Trace trace;
public TraceMappingWaiter(Trace trace) {
this.trace = trace;
}
@Override
public void mappingsChanged(Set<Trace> affectedTraces, Set<Program> affectedPrograms) {
if (affectedTraces.contains(trace)) {
complete(null);
}
}
public void softWait() {
try {
get(1, TimeUnit.SECONDS);
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
Msg.warn(this, "Mappings not reported by service after 1 second");
}
}
}
@Override @Override
public Trace launchProgram(Program program, Address address) throws IOException { public Trace launchProgram(Program program, Address address) throws IOException {
Trace trace = null; Trace trace = null;
try { try {
trace = ProgramEmulationUtils.launchEmulationTrace(program, address, this); trace = ProgramEmulationUtils.launchEmulationTrace(program, address, this);
trace.flushEvents();
TraceMappingWaiter waiter = new TraceMappingWaiter(trace);
staticMappings.addChangeListener(waiter);
traceManager.openTrace(trace); traceManager.openTrace(trace);
traceManager.activateTrace(trace); traceManager.activateTrace(trace);
Swing.allowSwingToProcessEvents(); waiter.softWait();
} }
finally { finally {
if (trace != null) { if (trace != null) {

View file

@ -45,7 +45,8 @@ import ghidra.trace.model.target.iface.TraceObjectInterface;
import ghidra.trace.model.target.path.*; import ghidra.trace.model.target.path.*;
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;
import ghidra.trace.model.thread.*; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.thread.TraceThreadManager;
import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.TraceSnapshot;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -290,19 +291,13 @@ public class ProgramEmulationUtils {
} }
public static PathPattern computePatternRegion(Trace trace) { public static PathPattern computePatternRegion(Trace trace) {
TraceObjectSchema root = trace.getObjectManager().getRootSchema(); TraceObjectSchema root = trace.getObjectManager().requireRootSchema();
if (root == null) { return computePattern(root, trace, TraceMemoryRegion.class);
return PathFilter.parse("Memory[]");
}
return computePattern(root, trace, TraceObjectMemoryRegion.class);
} }
public static PathPattern computePatternThread(Trace trace) { public static PathPattern computePatternThread(Trace trace) {
TraceObjectSchema root = trace.getObjectManager().getRootSchema(); TraceObjectSchema root = trace.getObjectManager().requireRootSchema();
if (root == null) { return computePattern(root, trace, TraceThread.class);
return PathFilter.parse("Threads[]");
}
return computePattern(root, trace, TraceObjectThread.class);
} }
/** /**
@ -347,18 +342,16 @@ public class ProgramEmulationUtils {
public static void initializeRegisters(Trace trace, long snap, TraceThread thread, public static void initializeRegisters(Trace trace, long snap, TraceThread thread,
Program program, Address tracePc, Address programPc, AddressRange stack) { Program program, Address tracePc, Address programPc, AddressRange stack) {
TraceMemoryManager memory = trace.getMemoryManager(); TraceMemoryManager memory = trace.getMemoryManager();
if (thread instanceof TraceObjectThread ot) { TraceObject object = thread.getObject();
TraceObject object = ot.getObject(); PathFilter regsFilter = object.getRoot()
PathFilter regsFilter = object.getRoot() .getSchema()
.getSchema() .searchForRegisterContainer(0, object.getCanonicalPath());
.searchForRegisterContainer(0, object.getCanonicalPath()); if (regsFilter.isNone()) {
if (regsFilter.isNone()) { throw new IllegalArgumentException("Cannot create register container");
throw new IllegalArgumentException("Cannot create register container"); }
} for (PathPattern regsPattern : regsFilter.getPatterns()) {
for (PathPattern regsPattern : regsFilter.getPatterns()) { trace.getObjectManager().createObject(regsPattern.getSingletonPath());
trace.getObjectManager().createObject(regsPattern.getSingletonPath()); break;
break;
}
} }
TraceMemorySpace regSpace = memory.getMemoryRegisterSpace(thread, true); TraceMemorySpace regSpace = memory.getMemoryRegisterSpace(thread, true);
if (program != null) { if (program != null) {
@ -606,7 +599,12 @@ public class ProgramEmulationUtils {
throw new EmulatorOutOfMemoryException(); throw new EmulatorOutOfMemoryException();
} }
protected static void createObjects(Trace trace) { /**
* Initialize a given emulation trace with some required/expected objects
*
* @param trace the trace
*/
public static void createObjects(Trace trace) {
TraceObjectManager om = trace.getObjectManager(); TraceObjectManager om = trace.getObjectManager();
om.createRootObject(EMU_SESSION_SCHEMA); om.createRootObject(EMU_SESSION_SCHEMA);

View file

@ -36,7 +36,7 @@ import ghidra.program.model.lang.RegisterValue;
import ghidra.program.util.MarkerLocation; import ghidra.program.util.MarkerLocation;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.TraceSpan; import ghidra.trace.model.TraceSpan;
import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointCommon;
import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
@ -321,12 +321,12 @@ public abstract class AbstractTarget implements Target {
} }
@Override @Override
public void deleteBreakpoint(TraceBreakpoint breakpoint) { public void deleteBreakpoint(TraceBreakpointCommon breakpoint) {
runSync("delete breakpoint", () -> deleteBreakpointAsync(breakpoint)); runSync("delete breakpoint", () -> deleteBreakpointAsync(breakpoint));
} }
@Override @Override
public void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled) { public void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled) {
String msg = enabled ? "enable breakpoint" : "disable breakpoint"; String msg = enabled ? "enable breakpoint" : "disable breakpoint";
runSync(msg, () -> toggleBreakpointAsync(breakpoint, enabled)); runSync(msg, () -> toggleBreakpointAsync(breakpoint, enabled));
} }

View file

@ -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.
@ -70,24 +70,16 @@ public class DebuggerListingPluginScreenShots extends GhidraScreenShotGenerator
TraceSymbolManager symbolManager = tb.trace.getSymbolManager(); TraceSymbolManager symbolManager = tb.trace.getSymbolManager();
TraceNamespaceSymbol global = symbolManager.getGlobalNamespace(); TraceNamespaceSymbol global = symbolManager.getGlobalNamespace();
TraceSymbol mainLabel = symbolManager TraceSymbol mainLabel = symbolManager.labels()
.labels() .create(snap, tb.addr(0x00400000), "main", global, SourceType.USER_DEFINED);
.create(snap, null, tb.addr(0x00400000),
"main", global, SourceType.USER_DEFINED);
@SuppressWarnings("unused") @SuppressWarnings("unused")
TraceSymbol cloneLabel = symbolManager TraceSymbol cloneLabel = symbolManager.labels()
.labels() .create(snap, tb.addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
.create(snap, null, tb.addr(0x00400060), TraceSymbol childLabel = symbolManager.labels()
"clone", global, SourceType.USER_DEFINED); .create(snap, tb.addr(0x00400032), "child", global, SourceType.USER_DEFINED);
TraceSymbol childLabel = symbolManager
.labels()
.create(snap, null, tb.addr(0x00400032),
"child", global, SourceType.USER_DEFINED);
@SuppressWarnings("unused") @SuppressWarnings("unused")
TraceSymbol exitLabel = symbolManager TraceSymbol exitLabel = symbolManager.labels()
.labels() .create(snap, tb.addr(0x00400061), "exit", global, SourceType.USER_DEFINED);
.create(snap, null, tb.addr(0x00400061),
"exit", global, SourceType.USER_DEFINED);
Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView()); Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView());

View file

@ -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.
@ -72,24 +72,16 @@ public class DebuggerMemoryBytesPluginScreenShots extends GhidraScreenShotGenera
TraceSymbolManager symbolManager = tb.trace.getSymbolManager(); TraceSymbolManager symbolManager = tb.trace.getSymbolManager();
TraceNamespaceSymbol global = symbolManager.getGlobalNamespace(); TraceNamespaceSymbol global = symbolManager.getGlobalNamespace();
TraceSymbol mainLabel = symbolManager TraceSymbol mainLabel = symbolManager.labels()
.labels() .create(snap, tb.addr(0x00400000), "main", global, SourceType.USER_DEFINED);
.create(snap, null, tb.addr(0x00400000),
"main", global, SourceType.USER_DEFINED);
@SuppressWarnings("unused") @SuppressWarnings("unused")
TraceSymbol cloneLabel = symbolManager TraceSymbol cloneLabel = symbolManager.labels()
.labels() .create(snap, tb.addr(0x00400060), "clone", global, SourceType.USER_DEFINED);
.create(snap, null, tb.addr(0x00400060), TraceSymbol childLabel = symbolManager.labels()
"clone", global, SourceType.USER_DEFINED); .create(snap, tb.addr(0x00400034), "child", global, SourceType.USER_DEFINED);
TraceSymbol childLabel = symbolManager
.labels()
.create(snap, null, tb.addr(0x00400034),
"child", global, SourceType.USER_DEFINED);
@SuppressWarnings("unused") @SuppressWarnings("unused")
TraceSymbol exitLabel = symbolManager TraceSymbol exitLabel = symbolManager.labels()
.labels() .create(snap, tb.addr(0x00400061), "exit", global, SourceType.USER_DEFINED);
.create(snap, null, tb.addr(0x00400061),
"exit", global, SourceType.USER_DEFINED);
Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView()); Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView());

View file

@ -33,7 +33,7 @@ import ghidra.trace.database.target.DBTraceObjectValue;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.iface.TraceObjectEventScope; import ghidra.trace.model.target.iface.TraceEventScope;
import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
@ -180,7 +180,7 @@ public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
proc.child("Modules"); proc.child("Modules");
} }
} }
root.value(TraceObjectEventScope.KEY_EVENT_THREAD, l.thread); root.value(TraceEventScope.KEY_EVENT_THREAD, l.thread);
} }
traceManager.openTrace(tb.trace); traceManager.openTrace(tb.trace);

View file

@ -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.
@ -29,7 +29,7 @@ import ghidra.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule;
import help.screenshot.GhidraScreenShotGenerator; import help.screenshot.GhidraScreenShotGenerator;
@ -66,7 +66,7 @@ public class DebuggerPcodeStepperPluginScreenShots extends GhidraScreenShotGener
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ,
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.EXECUTE);
TraceObjectThread thread = (TraceObjectThread) tb.getOrAddThread("Threads[1]", snap0); TraceThread thread = tb.getOrAddThread("Threads[1]", snap0);
tb.trace.getObjectManager() tb.trace.getObjectManager()
.createObject(thread.getObject().getCanonicalPath().key("Registers")); .createObject(thread.getObject().getCanonicalPath().key("Registers"));

View file

@ -22,10 +22,6 @@ import db.Transaction;
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin; import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
import ghidra.app.services.DebuggerTraceManagerService; import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.database.target.DBTraceObjectManagerTest;
import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
import help.screenshot.GhidraScreenShotGenerator; import help.screenshot.GhidraScreenShotGenerator;
public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator { public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator {
@ -41,11 +37,9 @@ public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator
@Test @Test
public void testCaptureDebuggerSelectPlatformOfferDialog() throws Throwable { public void testCaptureDebuggerSelectPlatformOfferDialog() throws Throwable {
SchemaContext ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX);
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("echo", "DATA:BE:64:default")) { try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("echo", "DATA:BE:64:default")) {
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.trace.getObjectManager() tb.createRootObject();
.createRootObject(ctx.getSchema(new SchemaName("Session")));
} }
traceManager.openTrace(tb.trace); traceManager.openTrace(tb.trace);
traceManager.activateTrace(tb.trace); traceManager.activateTrace(tb.trace);

View file

@ -45,7 +45,7 @@ import ghidra.trace.model.DefaultTraceLocation;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
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.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import help.screenshot.GhidraScreenShotGenerator; import help.screenshot.GhidraScreenShotGenerator;
@ -103,14 +103,10 @@ public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator
sm.getSnapshot(13, true); sm.getSnapshot(13, true);
DBTraceThreadManager tm = tb.trace.getThreadManager(); DBTraceThreadManager tm = tb.trace.getThreadManager();
TraceObjectThread t1 = TraceThread t1 = tm.addThread("Threads[1]", "main", Lifespan.nowOn(0));
(TraceObjectThread) tm.addThread("Threads[1]", "main", Lifespan.nowOn(0)); TraceThread t2 = tm.addThread("Threads[2]", "server", Lifespan.nowOn(2));
TraceObjectThread t2 = TraceThread t3 = tm.addThread("Threads[3]", "handler 1", Lifespan.span(5, 10));
(TraceObjectThread) tm.addThread("Threads[2]", "server", Lifespan.nowOn(2)); TraceThread t4 = tm.addThread("Threads[4]", "handler 2", Lifespan.span(8, 13));
TraceObjectThread t3 =
(TraceObjectThread) tm.addThread("Threads[3]", "handler 1", Lifespan.span(5, 10));
TraceObjectThread t4 =
(TraceObjectThread) tm.addThread("Threads[4]", "handler 2", Lifespan.span(8, 13));
t1.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED"); t1.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED");
t2.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED"); t2.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED");

View file

@ -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.
@ -62,7 +62,7 @@ public class DebuggerWatchesPluginScreenShots extends GhidraScreenShotGenerator
tb.trace.getSymbolManager() tb.trace.getSymbolManager()
.labels() .labels()
.create(snap1, null, tb.addr(0x7fff0004), "fiveUp", .create(snap1, tb.addr(0x7fff0004), "fiveUp",
tb.trace.getSymbolManager().getGlobalNamespace(), SourceType.USER_DEFINED); tb.trace.getSymbolManager().getGlobalNamespace(), SourceType.USER_DEFINED);
thread = tb.getOrAddThread("[1]", snap0); thread = tb.getOrAddThread("[1]", snap0);

View file

@ -48,6 +48,7 @@ import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Instruction; import ghidra.program.model.listing.Instruction;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder;
import ghidra.trace.database.listing.DBTraceInstruction; import ghidra.trace.database.listing.DBTraceInstruction;
import ghidra.trace.database.listing.DBTraceInstructionsMemoryView; import ghidra.trace.database.listing.DBTraceInstructionsMemoryView;
import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.database.memory.DBTraceMemoryManager;
@ -59,16 +60,16 @@ import ghidra.trace.model.Lifespan;
import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TraceGuestPlatform;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
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.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.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.iface.TraceObjectEnvironment; import ghidra.trace.model.target.iface.TraceEnvironment;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.target.schema.XmlSchemaContext;
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.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -162,12 +163,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
sel, null); sel, null);
} }
protected TraceObjectThread createPolyglotTrace(String arch, long offset, protected TraceThread createPolyglotTrace(String arch, long offset,
Supplier<ByteBuffer> byteSupplier) throws Exception { Supplier<ByteBuffer> byteSupplier) throws Exception {
return createPolyglotTrace(arch, offset, byteSupplier, true); return createPolyglotTrace(arch, offset, byteSupplier, true);
} }
protected TraceObjectThread createPolyglotTrace(String arch, long offset, protected TraceThread createPolyglotTrace(String arch, long offset,
Supplier<ByteBuffer> byteSupplier, boolean pcInStack) throws Exception { Supplier<ByteBuffer> byteSupplier, boolean pcInStack) throws Exception {
createAndOpenTrace("DATA:BE:64:default"); createAndOpenTrace("DATA:BE:64:default");
@ -179,13 +180,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
assertEquals(ctx.getSchema(new SchemaName("Environment")), env.getSchema()); assertEquals(ctx.getSchema(new SchemaName("Environment")), env.getSchema());
Lifespan zeroOn = Lifespan.nowOn(0); Lifespan zeroOn = Lifespan.nowOn(0);
env.insert(zeroOn, ConflictResolution.DENY); env.insert(zeroOn, ConflictResolution.DENY);
env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_DEBUGGER, "test"); env.setAttribute(zeroOn, TraceEnvironment.KEY_DEBUGGER, "test");
env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_ARCH, arch); env.setAttribute(zeroOn, TraceEnvironment.KEY_ARCH, arch);
DBTraceObject objBinText = DBTraceObject objBinText =
objects.createObject(KeyPath.parse("Targets[0].Memory[bin:.text]")); objects.createObject(KeyPath.parse("Targets[0].Memory[bin:.text]"));
TraceObjectMemoryRegion binText = TraceMemoryRegion binText = objBinText.queryInterface(TraceMemoryRegion.class);
objBinText.queryInterface(TraceObjectMemoryRegion.class);
binText.addFlags(zeroOn, Set.of(TraceMemoryFlag.EXECUTE)); binText.addFlags(zeroOn, Set.of(TraceMemoryFlag.EXECUTE));
binText.setRange(zeroOn, tb.range(offset, offset + 0xffff)); binText.setRange(zeroOn, tb.range(offset, offset + 0xffff));
// TODO: Why doesn't setRange work after insert? // TODO: Why doesn't setRange work after insert?
@ -196,16 +196,16 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
DBTraceObject objFrame = objects DBTraceObject objFrame = objects
.createObject(KeyPath.parse("Targets[0].Threads[0].Stack[0]")); .createObject(KeyPath.parse("Targets[0].Threads[0].Stack[0]"));
objFrame.insert(zeroOn, ConflictResolution.DENY); objFrame.insert(zeroOn, ConflictResolution.DENY);
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class); TraceStackFrame frame = objFrame.queryInterface(TraceStackFrame.class);
frame.setProgramCounter(zeroOn, tb.addr(offset)); frame.setProgramCounter(zeroOn, tb.addr(offset));
} }
else { else {
objects.createObject( objects.createObject(
KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers")) KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
.insert(zeroOn, ConflictResolution.DENY); .insert(zeroOn, ConflictResolution.DENY);
TraceObjectThread thread = objects TraceThread thread =
.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]")) objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
.queryInterface(TraceObjectThread.class); .queryInterface(TraceThread.class);
traceManager.activateThread(thread); traceManager.activateThread(thread);
DBTraceMemorySpace regs = DBTraceMemorySpace regs =
Objects.requireNonNull(memory.getMemoryRegisterSpace(thread, true)); Objects.requireNonNull(memory.getMemoryRegisterSpace(thread, true));
@ -218,14 +218,14 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
ByteBuffer bytes = byteSupplier.get(); ByteBuffer bytes = byteSupplier.get();
assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes)); assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes));
} }
TraceObjectThread thread = TraceThread thread =
objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]")) objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
.queryInterface(TraceObjectThread.class); .queryInterface(TraceThread.class);
traceManager.activateThread(thread); traceManager.activateThread(thread);
return thread; return thread;
} }
protected void setLegacyProgramCounterInStack(long offset, TraceThread thread, long snap) { protected void setProgramCounterInStack(long offset, TraceThread thread, long snap) {
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
DBTraceStackManager manager = tb.trace.getStackManager(); DBTraceStackManager manager = tb.trace.getStackManager();
TraceStack stack = manager.getStack(thread, snap, true); TraceStack stack = manager.getStack(thread, snap, true);
@ -234,7 +234,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
} }
} }
protected void setLegacyProgramCounterInRegs(long offset, TraceThread thread, long snap) { protected void setProgramCounterInRegs(long offset, TraceThread thread, long snap) {
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true);
@ -243,11 +243,19 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
} }
} }
protected void createLegacyTrace(String langID, long offset, Supplier<ByteBuffer> byteSupplier) protected SchemaContext buildContext() {
return new ToySchemaBuilder()
.noRegisterGroups()
.useRegistersPerFrame()
.build();
}
protected void createTrace(String langID, long offset, Supplier<ByteBuffer> byteSupplier)
throws Throwable { throws Throwable {
createAndOpenTrace(langID); createAndOpenTrace(langID);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject(buildContext(), "Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion("Memory[bin:.text]", 0, tb.range(offset, offset + 0xffff), memory.createRegion("Memory[bin:.text]", 0, tb.range(offset, offset + 0xffff),
Set.of(TraceMemoryFlag.EXECUTE, TraceMemoryFlag.READ)); Set.of(TraceMemoryFlag.EXECUTE, TraceMemoryFlag.READ));
@ -275,27 +283,27 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testAutoDisasembleReDisasembleX8664Offcut() throws Throwable { public void testAutoDisasembleReDisasembleX8664Offcut() throws Throwable {
enableAutoDisassembly(); enableAutoDisassembly();
createLegacyTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0)); createTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0));
TraceThread thread; TraceThread thread;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
thread = tb.getOrAddThread("Thread 1", 0); thread = tb.getOrAddThread("Threads[1]", 0);
} }
setLegacyProgramCounterInStack(0x00400000, thread, 0); setProgramCounterInStack(0x00400000, thread, 0);
waitForPass(() -> { waitForPass(() -> {
DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions(); DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions();
assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000))); assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000)));
/** /**
* Depending on preference for branch or fall-through, the disassembler may or may not * Depending on preference for branch or fall-through, the disassembler may or may not
* proceed to the following instructions. I don't really care, since the test is that the * proceed to the following instructions. I don't really care, since the test is that
* JMP gets deleted after the update to PC. * the JMP gets deleted after the update to PC.
*/ */
}); });
// The jump will advance one byte. Just simulate that by updating the stack and/or regs // The jump will advance one byte. Just simulate that by updating the stack and/or regs
setLegacyProgramCounterInStack(0x00400001, thread, 1); setProgramCounterInStack(0x00400001, thread, 1);
traceManager.activateSnap(1); traceManager.activateSnap(1);
waitForPass(() -> { waitForPass(() -> {
@ -310,22 +318,23 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
public void testAutoDisassembleReDisassembleX8664OffcutByEmulation() throws Throwable { public void testAutoDisassembleReDisassembleX8664OffcutByEmulation() throws Throwable {
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class); DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
enableAutoDisassembly(); enableAutoDisassembly();
createLegacyTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0)); createTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0));
TraceThread thread; TraceThread thread;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
thread = tb.getOrAddThread("Thread 1", 0); thread = tb.getOrAddThread("Threads[1]", 0);
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
} }
setLegacyProgramCounterInRegs(0x00400000, thread, 0); setProgramCounterInRegs(0x00400000, thread, 0);
waitForPass(() -> { waitForPass(() -> {
DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions(); DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions();
assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000))); assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000)));
/** /**
* Depending on preference for branch or fall-through, the disassembler may or may not * Depending on preference for branch or fall-through, the disassembler may or may not
* proceed to the following instructions. I don't really care, since the test is that the * proceed to the following instructions. I don't really care, since the test is that
* JMP gets deleted after the update to PC. * the JMP gets deleted after the update to PC.
*/ */
}); });
@ -374,8 +383,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000))); assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000)));
/** /**
* Depending on preference for branch or fall-through, the disassembler may or may not * Depending on preference for branch or fall-through, the disassembler may or may not
* proceed to the following instructions. I don't really care, since the test is that the * proceed to the following instructions. I don't really care, since the test is that
* JMP gets deleted after the update to PC. * the JMP gets deleted after the update to PC.
*/ */
}); });
@ -411,12 +420,13 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testCurrentDisassembleActionHostArm() throws Throwable { public void testCurrentDisassembleActionHostArm() throws Throwable {
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
// Fabricate the cpsr so that ARM is used. Otherwise, it will assume Cortex-M, so THUMB // Fabricate the cpsr so that ARM is used. Otherwise, it will assume Cortex-M, so THUMB
TraceThread thread; TraceThread thread;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
thread = tb.getOrAddThread("Threads[0]", 0); thread = tb.getOrAddThread("Threads[0]", 0);
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
DBTraceMemorySpace regs = DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO)); regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO));
@ -442,12 +452,13 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testCurrentDisassembleActionHostThumb() throws Throwable { public void testCurrentDisassembleActionHostThumb() throws Throwable {
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x70, 0x47)); createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x70, 0x47));
// Fabricate the cpsr so that THUMB is used, even though we could omit as in Cortex-M // Fabricate the cpsr so that THUMB is used, even though we could omit as in Cortex-M
TraceThread thread; TraceThread thread;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
thread = tb.getOrAddThread("Threads[0]", 0); thread = tb.getOrAddThread("Threads[0]", 0);
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
DBTraceMemorySpace regs = DBTraceMemorySpace regs =
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, regs.setValue(0,
@ -474,7 +485,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testCurrentDisassembleActionGuestArm() throws Throwable { public void testCurrentDisassembleActionGuestArm() throws Throwable {
TraceObjectThread thread = TraceThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
traceManager.activateThread(thread); traceManager.activateThread(thread);
waitForSwing(); waitForSwing();
@ -510,7 +521,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testCurrentDisassembleActionGuestThumb() throws Throwable { public void testCurrentDisassembleActionGuestThumb() throws Throwable {
TraceObjectThread thread = TraceThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47));
traceManager.activateThread(thread); traceManager.activateThread(thread);
waitForSwing(); waitForSwing();
@ -557,7 +568,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testFixedDisassembleActionsHostArm() throws Throwable { public void testFixedDisassembleActionsHostArm() throws Throwable {
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
// Ensure the mapper is added to the trace // Ensure the mapper is added to the trace
@ -573,7 +584,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testFixedDisassembleActionsGuestArm() throws Throwable { public void testFixedDisassembleActionsGuestArm() throws Throwable {
TraceObjectThread thread = TraceThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
@ -590,7 +601,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
@Test @Test
public void testFixedDisassembleActionsGuestThumb() throws Throwable { public void testFixedDisassembleActionsGuestThumb() throws Throwable {
TraceObjectThread thread = TraceThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
@ -610,7 +621,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// Assemble actions will think read-only otherwise // Assemble actions will think read-only otherwise
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00)); createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
@ -638,7 +649,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
// Don't cheat here and choose v8T! // Don't cheat here and choose v8T!
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00)); createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
@ -669,7 +680,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// Assemble actions will think read-only otherwise // Assemble actions will think read-only otherwise
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
TraceObjectThread thread = TraceThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
@ -699,7 +710,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// Assemble actions will think read-only otherwise // Assemble actions will think read-only otherwise
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
TraceObjectThread thread = TraceThread thread =
createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00)); createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00));
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
@ -749,7 +760,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// Assemble actions will think read-only otherwise // Assemble actions will think read-only otherwise
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf()); createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf());
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
@ -768,7 +779,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// Assemble actions will think read-only otherwise // Assemble actions will think read-only otherwise
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
TraceObjectThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf()); TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf());
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);
@ -787,7 +798,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
// Assemble actions will think read-only otherwise // Assemble actions will think read-only otherwise
DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class);
TraceObjectThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf()); TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf());
Address start = tb.addr(0x00400000); Address start = tb.addr(0x00400000);
controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE);

View file

@ -34,8 +34,6 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyPlan.AllCopiers; import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyPlan.AllCopiers;
import ghidra.app.util.viewer.listingpanel.PropertyBasedBackgroundColorModel; import ghidra.app.util.viewer.listingpanel.PropertyBasedBackgroundColorModel;
import ghidra.program.database.IntRangeMap; import ghidra.program.database.IntRangeMap;
import ghidra.program.disassemble.Disassembler;
import ghidra.program.disassemble.DisassemblerMessageListener;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
@ -75,9 +73,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
byte src[] = new byte[0x10000]; byte src[] = new byte[0x10000];
r.nextBytes(src); r.nextBytes(src);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.wrap(src)); memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.wrap(src));
} }
@ -107,9 +106,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.STATE.isAvailable(view, program)); assertTrue(AllCopiers.STATE.isAvailable(view, program));
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.allocate(4096)); memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.allocate(4096));
memory.setState(0, tb.addr(0x55551000), TraceMemoryState.ERROR); memory.setState(0, tb.addr(0x55551000), TraceMemoryState.ERROR);
} }
@ -182,10 +182,14 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
AddressRange trng = tb.range(0x55550000, 0x5555ffff); AddressRange trng = tb.range(0x55550000, 0x5555ffff);
Assembler asm = Assemblers.getAssembler(view); Assembler asm = Assemblers.getAssembler(view);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.createRegion("Memory[.text]", 0, trng,
InstructionIterator iit = TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
asm.assemble(tb.addr(0x55550000), "imm r0, #123", "imm r1, #234", "add r0, r1"); InstructionIterator iit = asm.assemble(tb.addr(0x55550000),
"imm r0, #123",
"imm r1, #234",
"add r0, r1");
assertTrue(iit.hasNext()); assertTrue(iit.hasNext());
} }
@ -228,10 +232,14 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
AddressRange trng = tb.range(0x55550000, 0x5555ffff); AddressRange trng = tb.range(0x55550000, 0x5555ffff);
Assembler asm = Assemblers.getAssembler(view); Assembler asm = Assemblers.getAssembler(view);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.createRegion("Memory[.text]", 0, trng,
InstructionIterator iit = TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
asm.assemble(tb.addr(0x55550000), "MOV RAX, 1234", "MOV RCX, 2345", "ADD RAX, RCX"); InstructionIterator iit = asm.assemble(tb.addr(0x55550000),
"MOV RAX, 1234",
"MOV RCX, 2345",
"ADD RAX, RCX");
assertTrue(iit.hasNext()); assertTrue(iit.hasNext());
} }
@ -272,7 +280,7 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.INSTRUCTIONS.isAvailable(view, program)); assertTrue(AllCopiers.INSTRUCTIONS.isAvailable(view, program));
AddressRange trng = tb.range(0x55550000, 0x5555ffff); AddressRange trng = tb.range(0x55550000, 0x5555ffff);
// Assembler asm = Assemblers.getAssembler(view); Assembler asm = Assemblers.getAssembler(view);
Register contextReg = tb.language.getContextBaseRegister(); Register contextReg = tb.language.getContextBaseRegister();
Register longMode = tb.language.getRegister("longMode"); Register longMode = tb.language.getRegister("longMode");
@ -281,26 +289,17 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
rv = rv.assign(longMode, BigInteger.ZERO); rv = rv.assign(longMode, BigInteger.ZERO);
Instruction checkCtx; Instruction checkCtx;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.createRegion("Memory[.text]", 0, trng,
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
tb.trace.getRegisterContextManager().setValue(tb.language, rv, Lifespan.nowOn(0), trng); tb.trace.getRegisterContextManager().setValue(tb.language, rv, Lifespan.nowOn(0), trng);
// TODO: Once GP-1426 is resolved, use the assembler
/*
InstructionIterator iit = asm.assemble(tb.addr(0x55550000), InstructionIterator iit = asm.assemble(tb.addr(0x55550000),
"MOV EAX, 1234", "MOV EAX, 1234",
"MOV ECX, 2345", "MOV ECX, 2345",
"ADD EAX, ECX"); "ADD EAX, ECX");
checkCtx = iit.next(); checkCtx = iit.next();
*/
memory.putBytes(0, tb.addr(0x55550000), tb.buf(0xb8, 0xd2, 0x04, 0x00, 0x00, // MOV EAX,1234
0xb9, 0x29, 0x09, 0x00, 0x00, // MOV ECX,2345
0x01, 0xc8 // ADD EAX,ECX
));
Disassembler
.getDisassembler(view, TaskMonitor.DUMMY, DisassemblerMessageListener.IGNORE)
.disassemble(tb.addr(0x55550000), tb.set(tb.range(0x55550000, 0x5555000b)));
checkCtx = tb.trace.getCodeManager().instructions().getAt(0, tb.addr(0x55550000));
} }
// Sanity pre-check // Sanity pre-check
RegisterValue insCtx = checkCtx.getRegisterValue(contextReg); RegisterValue insCtx = checkCtx.getRegisterValue(contextReg);
@ -352,8 +351,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
AddressRange trng = tb.range(0x55560000, 0x5556ffff); AddressRange trng = tb.range(0x55560000, 0x5556ffff);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".data", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); memory.createRegion("Memory[.data]", 0, trng,
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12)); tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12));
tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34)); tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34));
tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType, tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType,
@ -412,8 +413,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
AddressRange trng = tb.range(0x55560000, 0x5556ffff); AddressRange trng = tb.range(0x55560000, 0x5556ffff);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".data", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); memory.createRegion("Memory[.data]", 0, trng,
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12)); tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12));
tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34)); tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34));
tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType, tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType,
@ -479,21 +482,20 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.LABELS.isAvailable(view, program)); assertTrue(AllCopiers.LABELS.isAvailable(view, program));
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
DBTraceNamespaceSymbol global = tb.trace.getSymbolManager().getGlobalNamespace(); DBTraceNamespaceSymbol global = tb.trace.getSymbolManager().getGlobalNamespace();
DBTraceLabelSymbolView labels = tb.trace.getSymbolManager().labels(); DBTraceLabelSymbolView labels = tb.trace.getSymbolManager().labels();
labels.create(0, null, tb.addr(0x55550000), "test_label1", global, SourceType.IMPORTED); labels.create(0, tb.addr(0x55550000), "test_label1", global, SourceType.IMPORTED);
labels.create(0, null, tb.addr(0x55550005), "test_label2", global, labels.create(0, tb.addr(0x55550005), "test_label2", global, SourceType.USER_DEFINED);
SourceType.USER_DEFINED);
DBTraceNamespaceSymbolView namespaces = tb.trace.getSymbolManager().namespaces(); DBTraceNamespaceSymbolView namespaces = tb.trace.getSymbolManager().namespaces();
DBTraceNamespaceSymbol testNs = namespaces.add("test_ns", global, SourceType.ANALYSIS); DBTraceNamespaceSymbol testNs = namespaces.add("test_ns", global, SourceType.ANALYSIS);
DBTraceNamespaceSymbol testNsChild = DBTraceNamespaceSymbol testNsChild =
namespaces.add("test_ns_child", testNs, SourceType.USER_DEFINED); namespaces.add("test_ns_child", testNs, SourceType.USER_DEFINED);
labels.create(0, null, tb.addr(0x55550800), "test_label3", testNsChild, labels.create(0, tb.addr(0x55550800), "test_label3", testNsChild, SourceType.ANALYSIS);
SourceType.ANALYSIS);
} }
Address paddr = tb.addr(stSpace, 0x00400000); Address paddr = tb.addr(stSpace, 0x00400000);
@ -550,14 +552,15 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.BREAKPOINTS.isAvailable(view, program)); assertTrue(AllCopiers.BREAKPOINTS.isAvailable(view, program));
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
DBTraceBreakpointManager breakpoints = tb.trace.getBreakpointManager(); DBTraceBreakpointManager breakpoints = tb.trace.getBreakpointManager();
breakpoints.placeBreakpoint("[1]", 0, tb.addr(0x55550123), List.of(), breakpoints.placeBreakpoint("Breakpoints[1]", 0, tb.addr(0x55550123), List.of(),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "Test-1"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "Test-1");
breakpoints.placeBreakpoint("[2]", 0, tb.addr(0x55550321), List.of(), breakpoints.placeBreakpoint("Breakpoints[2]", 0, tb.addr(0x55550321), List.of(),
Set.of(TraceBreakpointKind.SW_EXECUTE), false, "Test-2"); Set.of(TraceBreakpointKind.SW_EXECUTE), false, "Test-2");
} }
@ -603,9 +606,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.BOOKMARKS.isAvailable(view, program)); assertTrue(AllCopiers.BOOKMARKS.isAvailable(view, program));
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
BookmarkManager bookmarks = view.getBookmarkManager(); BookmarkManager bookmarks = view.getBookmarkManager();
bookmarks.defineType("TestType", DebuggerResources.ICON_DEBUGGER, Palette.BLUE, 1); bookmarks.defineType("TestType", DebuggerResources.ICON_DEBUGGER, Palette.BLUE, 1);
@ -651,11 +655,12 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.REFERENCES.isAvailable(view, program)); assertTrue(AllCopiers.REFERENCES.isAvailable(view, program));
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
memory.createRegion(".data", 0, tb.range(0x55560000, 0x5556ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.data]", 0, tb.range(0x55560000, 0x5556ffff),
TraceMemoryFlag.WRITE); TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
ReferenceManager references = view.getReferenceManager(); ReferenceManager references = view.getReferenceManager();
references.addMemoryReference(tb.addr(0x55550123), tb.addr(0x55550321), references.addMemoryReference(tb.addr(0x55550123), tb.addr(0x55550321),
@ -702,9 +707,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest {
assertTrue(AllCopiers.COMMENTS.isAvailable(view, program)); assertTrue(AllCopiers.COMMENTS.isAvailable(view, program));
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemoryManager memory = tb.trace.getMemoryManager();
memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff),
TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
Listing listing = view.getListing(); Listing listing = view.getListing();
listing.setComment(tb.addr(0x55550123), CommentType.EOL, "Test EOL Comment"); listing.setComment(tb.addr(0x55550123), CommentType.EOL, "Test EOL Comment");

View file

@ -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.
@ -129,8 +129,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge
public void testColorsDiffBytes() throws Throwable { public void testColorsDiffBytes() throws Throwable {
createAndOpenTrace(); createAndOpenTrace();
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager mm = tb.trace.getMemoryManager(); DBTraceMemoryManager mm = tb.trace.getMemoryManager();
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text
@ -164,8 +165,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge
public void testActionPrevDiff() throws Throwable { public void testActionPrevDiff() throws Throwable {
createAndOpenTrace(); createAndOpenTrace();
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager mm = tb.trace.getMemoryManager(); DBTraceMemoryManager mm = tb.trace.getMemoryManager();
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text
@ -201,8 +203,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge
public void testActionNextDiff() throws Throwable { public void testActionNextDiff() throws Throwable {
createAndOpenTrace(); createAndOpenTrace();
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
DBTraceMemoryManager mm = tb.trace.getMemoryManager(); DBTraceMemoryManager mm = tb.trace.getMemoryManager();
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text

View file

@ -45,7 +45,6 @@ import ghidra.program.util.ProgramSelection;
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.TraceMemoryRegion; import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
import ghidra.trace.model.modules.TraceStaticMapping; import ghidra.trace.model.modules.TraceStaticMapping;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
@ -80,10 +79,10 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
DebuggerRegionsProvider provider; DebuggerRegionsProvider provider;
TraceObjectMemoryRegion regionExeText; TraceMemoryRegion regionExeText;
TraceObjectMemoryRegion regionExeData; TraceMemoryRegion regionExeData;
TraceObjectMemoryRegion regionLibText; TraceMemoryRegion regionLibText;
TraceObjectMemoryRegion regionLibData; TraceMemoryRegion regionLibData;
MemoryBlock blockExeText; MemoryBlock blockExeText;
MemoryBlock blockExeData; MemoryBlock blockExeData;
@ -109,21 +108,21 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
} }
} }
protected TraceObjectMemoryRegion addRegion(String name, long loaded, AddressRange range) { protected TraceMemoryRegion addRegion(String name, long loaded, AddressRange range) {
boolean isData = name.endsWith(".data"); boolean isData = name.endsWith(".data");
TraceObjectManager om = tb.trace.getObjectManager(); TraceObjectManager om = tb.trace.getObjectManager();
KeyPath memPath = KeyPath.parse("Memory"); KeyPath memPath = KeyPath.parse("Memory");
Lifespan span = Lifespan.nowOn(loaded); Lifespan span = Lifespan.nowOn(loaded);
TraceObjectMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name)) TraceMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name))
.insert(span, ConflictResolution.TRUNCATE) .insert(span, ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectMemoryRegion.class)); .queryInterface(TraceMemoryRegion.class));
TraceObject obj = region.getObject(); TraceObject obj = region.getObject();
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_DISPLAY, name); obj.setAttribute(span, TraceMemoryRegion.KEY_DISPLAY, name);
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE, range); obj.setAttribute(span, TraceMemoryRegion.KEY_RANGE, range);
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true); obj.setAttribute(span, TraceMemoryRegion.KEY_READABLE, true);
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE, isData); obj.setAttribute(span, TraceMemoryRegion.KEY_WRITABLE, isData);
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE, !isData); obj.setAttribute(span, TraceMemoryRegion.KEY_EXECUTABLE, !isData);
return region; return region;
} }
@ -218,7 +217,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
public void testAddThenActivateTracePopulates() throws Exception { public void testAddThenActivateTracePopulates() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }
@ -240,7 +239,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
waitForPass(() -> assertTableSize(0)); waitForPass(() -> assertTableSize(0));
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }
@ -257,7 +256,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
public void testRemoveRegionRemovesFromTable() throws Exception { public void testRemoveRegionRemovesFromTable() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }
@ -284,7 +283,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
public void testUndoRedo() throws Exception { public void testUndoRedo() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }
@ -320,7 +319,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
createAndOpenTrace(); createAndOpenTrace();
traceManager.activateTrace(tb.trace); traceManager.activateTrace(tb.trace);
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -346,7 +345,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
createAndOpenTrace(); createAndOpenTrace();
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }
@ -465,7 +464,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
createAndOpenTrace(); createAndOpenTrace();
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }
@ -514,7 +513,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
createAndOpenTrace(); createAndOpenTrace();
TraceObjectMemoryRegion region; TraceMemoryRegion region;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff));
} }

View file

@ -43,13 +43,12 @@ import ghidra.trace.database.ToyDBTraceBuilder.EventSuspension;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.target.*; import ghidra.trace.model.target.*;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.iface.TraceObjectEventScope; import ghidra.trace.model.target.iface.TraceEventScope;
import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.iface.TraceObjectInterface;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.thread.TraceObjectThread;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest { public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest {
@ -164,7 +163,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
prevThread.setAttribute(Lifespan.nowOn(i), "_next", thread); prevThread.setAttribute(Lifespan.nowOn(i), "_next", thread);
} }
objects.getRootObject() objects.getRootObject()
.setAttribute(Lifespan.nowOn(i), TraceObjectEventScope.KEY_EVENT_THREAD, .setAttribute(Lifespan.nowOn(i), TraceEventScope.KEY_EVENT_THREAD,
thread); thread);
return thread; return thread;
} }
@ -700,6 +699,8 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
* sufficient events to overload the queue, the event support with clear them and just issue an * sufficient events to overload the queue, the event support with clear them and just issue an
* OBJ_RESTORED event instead. This test ensures we update attributes in the tree when that * OBJ_RESTORED event instead. This test ensures we update attributes in the tree when that
* happens. * happens.
*
* @throws Throwable because
*/ */
@Test @Test
public void testTreeTracksChangeAttributeWithEventsSuspended() throws Throwable { public void testTreeTracksChangeAttributeWithEventsSuspended() throws Throwable {
@ -998,7 +999,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
TraceObjectManager objects = tb.trace.getObjectManager(); TraceObjectManager objects = tb.trace.getObjectManager();
TraceObject threadObj0 = TraceObject threadObj0 =
objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[0]")); objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[0]"));
TraceThread thread0 = threadObj0.queryInterface(TraceObjectThread.class); TraceThread thread0 = threadObj0.queryInterface(TraceThread.class);
createStack(threadObj0); createStack(threadObj0);
return thread0; return thread0;
} }

View file

@ -51,12 +51,10 @@ import ghidra.framework.main.DataTreeDialog;
import ghidra.plugin.importer.ImporterPlugin; import ghidra.plugin.importer.ImporterPlugin;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
import ghidra.trace.database.module.TraceObjectSection;
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.TraceObjectMemoryRegion; import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.modules.TraceObjectModule; import ghidra.trace.model.modules.*;
import ghidra.trace.model.modules.TraceStaticMapping;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.TraceObjectManager; import ghidra.trace.model.target.TraceObjectManager;
@ -109,13 +107,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
DebuggerModulesProvider provider; DebuggerModulesProvider provider;
protected TraceObjectModule modExe; protected TraceModule modExe;
protected TraceObjectSection secExeText; protected TraceSection secExeText;
protected TraceObjectSection secExeData; protected TraceSection secExeData;
protected TraceObjectModule modLib; protected TraceModule modLib;
protected TraceObjectSection secLibText; protected TraceSection secLibText;
protected TraceObjectSection secLibData; protected TraceSection secLibData;
protected SchemaContext ctx; protected SchemaContext ctx;
@ -145,13 +143,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
TraceObject root = om.getRootObject(); TraceObject root = om.getRootObject();
for (TraceObject module : (Iterable<TraceObject>) () -> root for (TraceObject module : (Iterable<TraceObject>) () -> root
.findSuccessorsInterface(Lifespan.at(0), TraceObjectModule.class, true) .findSuccessorsInterface(Lifespan.at(0), TraceModule.class, true)
.map(p -> p.getDestination(root)) .map(p -> p.getDestination(root))
.iterator()) { .iterator()) {
String moduleName = module.getCanonicalPath().index(); String moduleName = module.getCanonicalPath().index();
Lifespan span = module.getLife().bound(); Lifespan span = module.getLife().bound();
for (TraceObject section : (Iterable<TraceObject>) () -> module for (TraceObject section : (Iterable<TraceObject>) () -> module
.findSuccessorsInterface(Lifespan.at(0), TraceObjectSection.class, .findSuccessorsInterface(Lifespan.at(0), TraceSection.class,
true) true)
.map(p -> p.getDestination(root)) .map(p -> p.getDestination(root))
.iterator()) { .iterator()) {
@ -161,42 +159,42 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
.getSingletonPath()) .getSingletonPath())
.insert(span, ConflictResolution.TRUNCATE) .insert(span, ConflictResolution.TRUNCATE)
.getDestination(root); .getDestination(root);
region.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE, region.setAttribute(span, TraceMemoryRegion.KEY_RANGE,
section.getAttribute(0, TraceObjectSection.KEY_RANGE).getValue()); section.getAttribute(0, TraceSection.KEY_RANGE).getValue());
region.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true); region.setAttribute(span, TraceMemoryRegion.KEY_READABLE, true);
region.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE, region.setAttribute(span, TraceMemoryRegion.KEY_WRITABLE,
".data".equals(sectionName)); ".data".equals(sectionName));
region.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE, region.setAttribute(span, TraceMemoryRegion.KEY_EXECUTABLE,
".text".equals(sectionName)); ".text".equals(sectionName));
} }
} }
} }
} }
protected TraceObjectModule addModule(String name, AddressRange range, Lifespan span) { protected TraceModule addModule(String name, AddressRange range, Lifespan span) {
PathPattern modulePattern = PathFilter.parse("Processes[1].Modules[]"); PathPattern modulePattern = PathFilter.parse("Processes[1].Modules[]");
TraceObjectManager om = tb.trace.getObjectManager(); TraceObjectManager om = tb.trace.getObjectManager();
TraceObjectModule module = Objects.requireNonNull( TraceModule module = Objects.requireNonNull(
om.createObject(modulePattern.applyKeys(name).getSingletonPath()) om.createObject(modulePattern.applyKeys(name).getSingletonPath())
.insert(span, ConflictResolution.TRUNCATE) .insert(span, ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectModule.class)); .queryInterface(TraceModule.class));
module.getObject().setAttribute(span, TraceObjectModule.KEY_MODULE_NAME, name); module.getObject().setAttribute(span, TraceModule.KEY_MODULE_NAME, name);
module.getObject().setAttribute(span, TraceObjectModule.KEY_RANGE, range); module.getObject().setAttribute(span, TraceModule.KEY_RANGE, range);
return module; return module;
} }
protected TraceObjectSection addSection(TraceObjectModule module, String name, protected TraceSection addSection(TraceModule module, String name,
AddressRange range) { AddressRange range) {
TraceObjectManager om = tb.trace.getObjectManager(); TraceObjectManager om = tb.trace.getObjectManager();
Lifespan span = module.getObject().getLife().bound(); Lifespan span = module.getObject().getLife().bound();
TraceObjectSection section = Objects.requireNonNull(om TraceSection section = Objects.requireNonNull(om
.createObject( .createObject(
module.getObject().getCanonicalPath().key("Sections").index(name)) module.getObject().getCanonicalPath().key("Sections").index(name))
.insert(span, ConflictResolution.TRUNCATE) .insert(span, ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectSection.class)); .queryInterface(TraceSection.class));
section.getObject().setAttribute(span, TraceObjectSection.KEY_RANGE, range); section.getObject().setAttribute(span, TraceSection.KEY_RANGE, range);
return section; return section;
} }
@ -719,7 +717,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
for (ValueRow row : visibleSections()) { for (ValueRow row : visibleSections()) {
assertEquals(modExe.getObject(), row.getValue() assertEquals(modExe.getObject(), row.getValue()
.getChild() .getChild()
.findCanonicalAncestorsInterface(TraceObjectModule.class) .findCanonicalAncestorsInterface(TraceModule.class)
.findFirst() .findFirst()
.orElse(null)); .orElse(null));
} }

View file

@ -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.
@ -115,8 +115,9 @@ public class DebuggerStaticMappingProviderTest extends AbstractGhidraHeadedDebug
intoProject(program); intoProject(program);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject("Target");
tb.trace.getMemoryManager() tb.trace.getMemoryManager()
.addRegion(".text", Lifespan.nowOn(0), .addRegion("Memory[.text]", Lifespan.nowOn(0),
tb.range(0xdeadbeefL, 0xdeadbeefL + 0xff), tb.range(0xdeadbeefL, 0xdeadbeefL + 0xff),
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE));
} }

View file

@ -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.
@ -26,7 +26,8 @@ import org.junit.Test;
import db.Transaction; import db.Transaction;
import generic.Unique; import generic.Unique;
import generic.theme.*; import generic.theme.ApplicationThemeManager;
import generic.theme.ThemeManager;
import ghidra.app.plugin.assembler.Assembler; import ghidra.app.plugin.assembler.Assembler;
import ghidra.app.plugin.assembler.Assemblers; import ghidra.app.plugin.assembler.Assemblers;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
@ -46,8 +47,10 @@ import ghidra.pcode.exec.trace.TraceSleighUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Instruction; import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.InstructionIterator; import ghidra.program.model.listing.InstructionIterator;
import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.target.schema.SchemaContext;
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;
@ -79,15 +82,25 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
createTrace(); createTrace();
} }
SchemaContext buildContext() {
return new ToySchemaBuilder()
.useRegistersPerFrame()
.noRegisterGroups()
.build();
}
protected void populateTrace() throws Exception { protected void populateTrace() throws Exception {
start = tb.addr(0x00400000); start = tb.addr(0x00400000);
InstructionIterator iit; InstructionIterator iit;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject(buildContext(), "Target");
tb.trace.getMemoryManager() tb.trace.getMemoryManager()
.addRegion("echo:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), .addRegion("Memory[echo:.text]", Lifespan.nowOn(0),
tb.range(0x00400000, 0x0040ffff),
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
thread = tb.getOrAddThread("1", 0); thread = tb.getOrAddThread("Threads[1]", 0);
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
PcodeExecutor<byte[]> init = TraceSleighUtils.buildByteExecutor(tb.trace, 0, thread, 0); PcodeExecutor<byte[]> init = TraceSleighUtils.buildByteExecutor(tb.trace, 0, thread, 0);
init.executeSleigh("pc = 0x00400000;"); init.executeSleigh("pc = 0x00400000;");
@ -124,7 +137,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
public void testCloseCurrentTraceEmpty() throws Exception { public void testCloseCurrentTraceEmpty() throws Exception {
populateTrace(); populateTrace();
TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1"); TraceSchedule schedule1 = TraceSchedule.parse("0:.t%d-1".formatted(thread.getKey()));
traceManager.openTrace(tb.trace); traceManager.openTrace(tb.trace);
traceManager.activateThread(thread); traceManager.activateThread(thread);
waitForPass(() -> assertDecodeStep()); waitForPass(() -> assertDecodeStep());
@ -166,13 +179,13 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
}); });
// Just one p-code step to load injection (decode step) // Just one p-code step to load injection (decode step)
TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1"); TraceSchedule schedule1 = TraceSchedule.parse("0:.t%d-1".formatted(thread.getKey()));
traceManager.openTrace(tb.trace); traceManager.openTrace(tb.trace);
traceManager.activateThread(thread); traceManager.activateThread(thread);
traceManager.activateTime(schedule1); traceManager.activateTime(schedule1);
waitForPass(() -> assertEquals(schedule1, pcodeProvider.current.getTime())); waitForPass(() -> assertEquals(schedule1, pcodeProvider.current.getTime()));
waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.getModelData() waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.copyModelData()
.stream() .stream()
.anyMatch(r -> r.getCode().contains("stepper_test_userop")))); .anyMatch(r -> r.getCode().contains("stepper_test_userop"))));
} }

View file

@ -41,9 +41,9 @@ import ghidra.program.model.listing.Function;
import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SourceType;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.memory.TraceObjectMemoryRegion; import ghidra.trace.model.memory.TraceMemoryRegion;
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.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.TraceObjectManager; import ghidra.trace.model.target.TraceObjectManager;
@ -51,7 +51,7 @@ import ghidra.trace.model.target.path.*;
import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTable;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -167,7 +167,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
} }
} }
protected TraceObjectThread addThread(int n) { protected TraceThread addThread(int n) {
PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]"); PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]");
KeyPath threadPath = threadPattern.applyIntKeys(n).getSingletonPath(); KeyPath threadPath = threadPattern.applyIntKeys(n).getSingletonPath();
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
@ -175,26 +175,26 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
.createObject(threadPath) .createObject(threadPath)
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectThread.class)); .queryInterface(TraceThread.class));
} }
} }
protected TraceObjectStack addStack(TraceObjectThread thread) { protected TraceStack addStack(TraceThread thread) {
KeyPath stackPath = thread.getObject().getCanonicalPath().extend("Stack"); KeyPath stackPath = thread.getObject().getCanonicalPath().extend("Stack");
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
return Objects.requireNonNull(tb.trace.getObjectManager() return Objects.requireNonNull(tb.trace.getObjectManager()
.createObject(stackPath) .createObject(stackPath)
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectStack.class)); .queryInterface(TraceStack.class));
} }
} }
protected void addStackFrames(TraceObjectStack stack) { protected void addStackFrames(TraceStack stack) {
addStackFrames(stack, 2); addStackFrames(stack, 2);
} }
protected void addStackFrames(TraceObjectStack stack, int count) { protected void addStackFrames(TraceStack stack, int count) {
KeyPath stackPath = stack.getObject().getCanonicalPath(); KeyPath stackPath = stack.getObject().getCanonicalPath();
TraceObjectManager om = tb.trace.getObjectManager(); TraceObjectManager om = tb.trace.getObjectManager();
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
@ -202,7 +202,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
TraceObject frame = om.createObject(stackPath.index(i)) TraceObject frame = om.createObject(stackPath.index(i))
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
.getDestination(null); .getDestination(null);
frame.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC, frame.setAttribute(Lifespan.nowOn(0), TraceStackFrame.KEY_PC,
tb.addr(0x00400100 + 0x100 * i)); tb.addr(0x00400100 + 0x100 * i));
} }
} }
@ -262,7 +262,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testActivateThreadNoStackEmpty() throws Exception { public void testActivateThreadNoStackEmpty() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
traceManager.activateObject(thread.getObject()); traceManager.activateObject(thread.getObject());
@ -275,7 +275,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testActivateThreadThenAddEmptyStackEmpty() throws Exception { public void testActivateThreadThenAddEmptyStackEmpty() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
addStack(thread); addStack(thread);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -289,9 +289,9 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testActivateThreadThenAddStackPopulatesProvider() throws Exception { public void testActivateThreadThenAddStackPopulatesProvider() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
traceManager.activateObject(thread.getObject()); traceManager.activateObject(thread.getObject());
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
waitForTasks(); waitForTasks();
@ -303,8 +303,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testAddStackThenActivateThreadPopulatesProvider() throws Exception { public void testAddStackThenActivateThreadPopulatesProvider() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -316,12 +316,14 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
/** /**
* Because keys are strings, we need to ensure they get sorted numerically * Because keys are strings, we need to ensure they get sorted numerically
*
* @throws Exception because
*/ */
@Test @Test
public void testTableSortedCorrectly() throws Exception { public void testTableSortedCorrectly() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack, 15); addStackFrames(stack, 15);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -341,8 +343,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testAppendStackUpdatesProvider() throws Exception { public void testAppendStackUpdatesProvider() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -356,7 +358,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
.createObject(stack.getObject().getCanonicalPath().index(2)) .createObject(stack.getObject().getCanonicalPath().index(2))
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
.getDestination(null); .getDestination(null);
frame2.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC, frame2.setAttribute(Lifespan.nowOn(0), TraceStackFrame.KEY_PC,
tb.addr(0x00400300)); tb.addr(0x00400300));
} }
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -374,8 +376,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testRemoveFrameUpdatesProvider() throws Exception { public void testRemoveFrameUpdatesProvider() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -400,8 +402,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testRemoveStackUpdatesProvider() throws Exception { public void testRemoveStackUpdatesProvider() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -423,9 +425,9 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testActivateOtherThreadEmptiesProvider() throws Exception { public void testActivateOtherThreadEmptiesProvider() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread1 = addThread(1); TraceThread thread1 = addThread(1);
TraceObjectThread thread2 = addThread(2); TraceThread thread2 = addThread(2);
TraceObjectStack stack1 = addStack(thread1); TraceStack stack1 = addStack(thread1);
addStackFrames(stack1); addStackFrames(stack1);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -444,8 +446,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testActivateSnap() throws Exception { public void testActivateSnap() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -477,8 +479,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testCloseCurrentTraceEmpty() throws Exception { public void testCloseCurrentTraceEmpty() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -497,8 +499,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testActivateFrameSelectsRow() throws Exception { public void testActivateFrameSelectsRow() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -524,8 +526,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
public void testDoubleClickRowActivateFrame() throws Exception { public void testDoubleClickRowActivateFrame() throws Exception {
createAndOpenTrace(); createAndOpenTrace();
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -557,8 +559,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
traceManager.openTrace(tb.trace); traceManager.openTrace(tb.trace);
programManager.openProgram(program); programManager.openProgram(program);
TraceObjectThread thread = addThread(1); TraceThread thread = addThread(1);
TraceObjectStack stack = addStack(thread); TraceStack stack = addStack(thread);
addStackFrames(stack); addStackFrames(stack);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
@ -580,13 +582,13 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
waitForDomainObject(program); waitForDomainObject(program);
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
TraceObjectMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager() TraceMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager()
.createObject(KeyPath.parse("Processes[1].Memory[bin:.text]")) .createObject(KeyPath.parse("Processes[1].Memory[bin:.text]"))
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectMemoryRegion.class)); .queryInterface(TraceMemoryRegion.class));
region.getObject() region.getObject()
.setAttribute(Lifespan.nowOn(0), TraceObjectMemoryRegion.KEY_RANGE, .setAttribute(Lifespan.nowOn(0), TraceMemoryRegion.KEY_RANGE,
tb.drng(0x00400000, 0x00400fff)); tb.drng(0x00400000, 0x00400fff));
TraceLocation dloc = TraceLocation dloc =

View file

@ -34,13 +34,13 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.TraceObjectManager; import ghidra.trace.model.target.TraceObjectManager;
import ghidra.trace.model.target.iface.TraceObjectExecutionStateful; import ghidra.trace.model.target.iface.TraceExecutionStateful;
import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.path.PathFilter;
import ghidra.trace.model.target.path.PathPattern; import ghidra.trace.model.target.path.PathPattern;
import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.TraceTimeManager; import ghidra.trace.model.time.TraceTimeManager;
import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTable;
@ -71,8 +71,8 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
DebuggerThreadsProvider provider; DebuggerThreadsProvider provider;
protected TraceObjectThread thread1; protected TraceThread thread1;
protected TraceObjectThread thread2; protected TraceThread thread2;
protected SchemaContext ctx; protected SchemaContext ctx;
@ -95,18 +95,18 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
} }
} }
protected TraceObjectThread addThread(int index, Lifespan lifespan, String comment) { protected TraceThread addThread(int index, Lifespan lifespan, String comment) {
TraceObjectManager om = tb.trace.getObjectManager(); TraceObjectManager om = tb.trace.getObjectManager();
PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]"); PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]");
TraceObjectThread thread = Objects.requireNonNull(om.createObject( TraceThread thread = Objects.requireNonNull(om.createObject(
threadPattern.applyIntKeys(index).getSingletonPath()) threadPattern.applyIntKeys(index).getSingletonPath())
.insert(lifespan, ConflictResolution.TRUNCATE) .insert(lifespan, ConflictResolution.TRUNCATE)
.getDestination(null) .getDestination(null)
.queryInterface(TraceObjectThread.class)); .queryInterface(TraceThread.class));
thread.getObject() thread.getObject()
.setAttribute(lifespan, TraceObjectExecutionStateful.KEY_STATE, .setAttribute(lifespan, TraceExecutionStateful.KEY_STATE,
TraceExecutionState.STOPPED.name()); TraceExecutionState.STOPPED.name());
thread.getObject().setAttribute(lifespan, TraceObjectThread.KEY_COMMENT, comment); thread.getObject().setAttribute(lifespan, TraceThread.KEY_COMMENT, comment);
return thread; return thread;
} }
@ -160,7 +160,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
assertNull(provider.panel.getSelectedItem()); assertNull(provider.panel.getSelectedItem());
} }
protected void assertThreadSelected(TraceObjectThread thread) { protected void assertThreadSelected(TraceThread thread) {
ValueRow row = provider.panel.getSelectedItem(); ValueRow row = provider.panel.getSelectedItem();
assertNotNull(row); assertNotNull(row);
assertEquals(thread.getObject(), row.getValue().getChild()); assertEquals(thread.getObject(), row.getValue().getChild());
@ -329,7 +329,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
waitForTasks(); waitForTasks();
waitForPass(() -> assertEquals("A different comment", waitForPass(() -> assertEquals("A different comment",
thread1.getObject().getAttribute(0, TraceObjectThread.KEY_COMMENT).getValue())); thread1.getObject().getAttribute(0, TraceThread.KEY_COMMENT).getValue()));
} }
// @Test // Not gonna with write-behind cache // @Test // Not gonna with write-behind cache

View file

@ -92,7 +92,7 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest {
// Timestamp is left unchecked, since default is current time // Timestamp is left unchecked, since default is current time
} }
@Test // TODO: Technically, this is a plugin action.... Different test case? @Test // Technically, this is a plugin action.... Different test case?
public void testActionRenameSnapshot() throws Exception { public void testActionRenameSnapshot() throws Exception {
// More often than not, this action will be used from the dynamic listing // More often than not, this action will be used from the dynamic listing
addPlugin(tool, DebuggerListingPlugin.class); addPlugin(tool, DebuggerListingPlugin.class);
@ -125,7 +125,7 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest {
DBTraceSnapshot snapshot = tb.trace.getTimeManager().getSnapshot(10, false); DBTraceSnapshot snapshot = tb.trace.getTimeManager().getSnapshot(10, false);
assertEquals("My Snapshot", snapshot.getDescription()); assertEquals("My Snapshot", snapshot.getDescription());
// TODO: Test cancelled has no effect // LATER?: Test cancelled has no effect
} }
@Test @Test
@ -153,7 +153,8 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest {
createSnaplessTrace(); createSnaplessTrace();
TraceThread thread; TraceThread thread;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
thread = tb.trace.getThreadManager().createThread("Thread 1", 0); tb.createRootObject("Target");
thread = tb.trace.getThreadManager().createThread("Threads[1]", 0);
} }
traceManager.openTrace(tb.trace); traceManager.openTrace(tb.trace);
traceManager.activateThread(thread); traceManager.activateThread(thread);

View file

@ -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.stack.TraceStackFrame; import ghidra.trace.model.stack.TraceStackFrame;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
@ -233,27 +232,27 @@ public class MockTarget implements Target {
} }
@Override @Override
public boolean isBreakpointValid(TraceBreakpoint breakpoint) { public boolean isBreakpointValid(TraceBreakpointLocation breakpoint) {
return true; return true;
} }
@Override @Override
public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpoint breakpoint) { public CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint) {
return AsyncUtils.nil(); return AsyncUtils.nil();
} }
@Override @Override
public void deleteBreakpoint(TraceBreakpoint breakpoint) { public void deleteBreakpoint(TraceBreakpointCommon breakpoint) {
} }
@Override @Override
public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpoint breakpoint, public CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint,
boolean enabled) { boolean enabled) {
return AsyncUtils.nil(); return AsyncUtils.nil();
} }
@Override @Override
public void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled) { public void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled) {
} }
@Override @Override

View file

@ -52,16 +52,18 @@ import ghidra.program.model.listing.ProgramContext;
import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder;
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.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemoryManager; import ghidra.trace.model.memory.TraceMemoryManager;
import ghidra.trace.model.memory.TraceMemorySpace; import ghidra.trace.model.memory.TraceMemorySpace;
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.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.SchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.target.schema.TraceObjectSchema;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.TraceSnapshot;
@ -249,6 +251,13 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
mem.getViewValue(scratch, regW1).getUnsignedValue()); mem.getViewValue(scratch, regW1).getUnsignedValue());
} }
protected SchemaContext buildContext() {
return new ToySchemaBuilder()
.noRegisterGroups()
.useRegistersPerFrame()
.build();
}
@Test @Test
public void testPureEmulationRelocated() throws Throwable { public void testPureEmulationRelocated() throws Throwable {
createAndOpenTrace("x86:LE:64:default"); createAndOpenTrace("x86:LE:64:default");
@ -282,7 +291,9 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
TraceThread thread; TraceThread thread;
TraceMemorySpace regs; TraceMemorySpace regs;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject(buildContext(), "Target");
thread = tb.getOrAddThread("Threads[0]", 0); thread = tb.getOrAddThread("Threads[0]", 0);
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true);
regs.setValue(0, new RegisterValue(program.getLanguage().getProgramCounter(), regs.setValue(0, new RegisterValue(program.getLanguage().getProgramCounter(),
BigInteger.valueOf(0x55550000))); BigInteger.valueOf(0x55550000)));
@ -295,8 +306,8 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
waitForSwing(); waitForSwing();
waitOn(settled); waitOn(settled);
long scratch = long scratch = emulationPlugin.emulate(tb.trace,
emulationPlugin.emulate(tb.trace, TraceSchedule.parse("0:t0-1"), TaskMonitor.DUMMY); TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), TaskMonitor.DUMMY);
assertEquals("deadbeefcafebabe", assertEquals("deadbeefcafebabe",
regs.getViewValue(scratch, tb.reg("RAX")).getUnsignedValue().toString(16)); regs.getViewValue(scratch, tb.reg("RAX")).getUnsignedValue().toString(16));
@ -315,7 +326,9 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
TraceMemoryManager mem = tb.trace.getMemoryManager(); TraceMemoryManager mem = tb.trace.getMemoryManager();
TraceThread thread; TraceThread thread;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
tb.createRootObject(buildContext(), "Target");
thread = tb.getOrAddThread("Threads[0]", 0); thread = tb.getOrAddThread("Threads[0]", 0);
tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1);
buf.assemble("MOV RAX, qword ptr [0x00600800]"); buf.assemble("MOV RAX, qword ptr [0x00600800]");
mem.putBytes(0, tb.addr(0x00400000), ByteBuffer.wrap(buf.getBytes())); mem.putBytes(0, tb.addr(0x00400000), ByteBuffer.wrap(buf.getBytes()));
mem.putBytes(0, tb.addr(0x00600800), mem.putBytes(0, tb.addr(0x00600800),
@ -344,8 +357,8 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
tb.exec(platform, 0, thread, 0, "RIP = 0x00400000;"); tb.exec(platform, 0, thread, 0, "RIP = 0x00400000;");
} }
long scratch = long scratch = emulationPlugin.emulate(platform,
emulationPlugin.emulate(platform, TraceSchedule.parse("0:t0-1"), TaskMonitor.DUMMY); TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), TaskMonitor.DUMMY);
TraceMemorySpace regs = mem.getMemoryRegisterSpace(thread, false); TraceMemorySpace regs = mem.getMemoryRegisterSpace(thread, false);
assertEquals("deadbeefcafebabe", assertEquals("deadbeefcafebabe",
regs.getViewValue(platform, scratch, tb.reg(platform, "RAX")) regs.getViewValue(platform, scratch, tb.reg(platform, "RAX"))
@ -494,7 +507,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
trace.getBreakpointManager() trace.getBreakpointManager()
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread), .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
TraceBreakpoint tb = trace.getBreakpointManager() TraceBreakpointLocation tb = trace.getBreakpointManager()
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread), .addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
// Force "partial instruction" // Force "partial instruction"
@ -568,7 +581,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
trace.getBreakpointManager() trace.getBreakpointManager()
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread), .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
TraceBreakpoint tb = trace.getBreakpointManager() TraceBreakpointLocation tb = trace.getBreakpointManager()
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread), .addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
// Force "partial instruction" // Force "partial instruction"
@ -634,7 +647,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads()); TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads());
try (Transaction tx = trace.openTransaction("Add breakpoint")) { try (Transaction tx = trace.openTransaction("Add breakpoint")) {
TraceBreakpoint tb = trace.getBreakpointManager() TraceBreakpointLocation tb = trace.getBreakpointManager()
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread), .addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
// Force "partial instruction" // Force "partial instruction"
@ -709,7 +722,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false); TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false);
try (Transaction tx = trace.openTransaction("Add breakpoint")) { try (Transaction tx = trace.openTransaction("Add breakpoint")) {
TraceBreakpoint tb = trace.getBreakpointManager() TraceBreakpointLocation tb = trace.getBreakpointManager()
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread), .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
tb.setEmuSleigh(0, """ tb.setEmuSleigh(0, """
@ -854,7 +867,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
// Inject some logic that would require a cache refresh to materialize // Inject some logic that would require a cache refresh to materialize
try (Transaction tx = trace.openTransaction("Add breakpoint")) { try (Transaction tx = trace.openTransaction("Add breakpoint")) {
TraceBreakpoint tb = trace.getBreakpointManager() TraceBreakpointLocation tb = trace.getBreakpointManager()
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread), .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test");
tb.setEmuSleigh(0, """ tb.setEmuSleigh(0, """
@ -986,10 +999,10 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe
public void testEmuSchemaHasWorkingStackFrames() throws Exception { public void testEmuSchemaHasWorkingStackFrames() throws Exception {
TraceObjectSchema rootSchema = ProgramEmulationUtils.EMU_SESSION_SCHEMA; TraceObjectSchema rootSchema = ProgramEmulationUtils.EMU_SESSION_SCHEMA;
TraceObjectSchema threadSchema = rootSchema.getSuccessorSchema(KeyPath.parse("Threads[1]")); TraceObjectSchema threadSchema = rootSchema.getSuccessorSchema(KeyPath.parse("Threads[1]"));
KeyPath found = threadSchema.searchForCanonicalContainer(TraceObjectStackFrame.class); KeyPath found = threadSchema.searchForCanonicalContainer(TraceStackFrame.class);
assertEquals(KeyPath.parse("Stack"), found); assertEquals(KeyPath.parse("Stack"), found);
PathFilter stackFilter = threadSchema.searchFor(TraceObjectStack.class, false); PathFilter stackFilter = threadSchema.searchFor(TraceStack.class, false);
assertNotNull("Non-unique Stack", stackFilter.getSingletonPath()); assertNotNull("Non-unique Stack", stackFilter.getSingletonPath());
} }
} }

View file

@ -635,13 +635,14 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg
TraceMemoryRegion echoText, echoData, libText, libData; TraceMemoryRegion echoText, echoData, libText, libData;
DBTraceMemoryManager mm = tb.trace.getMemoryManager(); DBTraceMemoryManager mm = tb.trace.getMemoryManager();
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
echoText = mm.createRegion("Memory.Regions[/bin/echo (0x00400000)]", tb.createRootObject("Target");
echoText = mm.createRegion("Memory[/bin/echo (0x00400000)]",
0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
echoData = mm.createRegion("Memory.Regions[/bin/echo (0x00600000)]", echoData = mm.createRegion("Memory[/bin/echo (0x00600000)]",
0, tb.range(0x00600000, 0x00600fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); 0, tb.range(0x00600000, 0x00600fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
libText = mm.createRegion("Memory.Regions[/lib/libc.so (0x7ff00000)]", libText = mm.createRegion("Memory[/lib/libc.so (0x7ff00000)]",
0, tb.range(0x7ff00000, 0x7ff0ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); 0, tb.range(0x7ff00000, 0x7ff0ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
libData = mm.createRegion("Memory.Regions[/lib/libc.so (0x7ff20000)]", libData = mm.createRegion("Memory[/lib/libc.so (0x7ff20000)]",
0, tb.range(0x7ff20000, 0x7ff20fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); 0, tb.range(0x7ff20000, 0x7ff20fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
} }
@ -688,7 +689,7 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg
objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY); objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
} }
TraceModule modBash = objModBash.queryInterface(TraceObjectModule.class); TraceModule modBash = objModBash.queryInterface(TraceModule.class);
assertEquals(Map.of(), assertEquals(Map.of(),
mappingService.proposeModuleMaps(List.of(modBash), 0, List.of(program))); mappingService.proposeModuleMaps(List.of(modBash), 0, List.of(program)));
} }

View file

@ -80,8 +80,8 @@ import ghidra.program.model.symbol.SourceType;
import ghidra.program.util.*; import ghidra.program.util.*;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.TraceLocation; import ghidra.trace.model.TraceLocation;
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.listing.TraceData; import ghidra.trace.model.listing.TraceData;
import ghidra.trace.model.memory.TraceMemorySpace; import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
@ -888,7 +888,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
waitOn(frameAtSetup.setReturnAddress(editor, tb.addr(0xdeadbeef))); waitOn(frameAtSetup.setReturnAddress(editor, tb.addr(0xdeadbeef)));
waitForTasks(); waitForTasks();
TraceBreakpoint bptUnwind; TraceBreakpointLocation bptUnwind;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
bptUnwind = tb.trace.getBreakpointManager() bptUnwind = tb.trace.getBreakpointManager()
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(), .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
@ -976,7 +976,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
Register sp = program.getCompilerSpec().getStackPointer(); Register sp = program.getCompilerSpec().getStackPointer();
long spAtSetup = regs.getValue(0, sp).getUnsignedValue().longValueExact(); long spAtSetup = regs.getValue(0, sp).getUnsignedValue().longValueExact();
TraceBreakpoint bptUnwind; TraceBreakpointLocation bptUnwind;
try (Transaction tx = tb.startTransaction()) { try (Transaction tx = tb.startTransaction()) {
bptUnwind = tb.trace.getBreakpointManager() bptUnwind = tb.trace.getBreakpointManager()
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), entry, Set.of(), .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), entry, Set.of(),

View file

@ -300,11 +300,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
} }
@DependentService @DependentService
protected DBTraceBreakpointManager createBreakpointManager(DBTraceThreadManager threadManager) protected DBTraceBreakpointManager createBreakpointManager(DBTraceObjectManager objectManager)
throws CancelledException, IOException { throws CancelledException, IOException {
return createTraceManager("Breakpoint Manager", return createTraceManager("Breakpoint Manager",
(openMode, monitor) -> new DBTraceBreakpointManager(dbh, openMode, rwLock, monitor, (openMode, monitor) -> new DBTraceBreakpointManager(dbh, openMode, rwLock, monitor,
baseLanguage, this, threadManager)); this, objectManager));
} }
@DependentService @DependentService
@ -367,10 +367,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
} }
@DependentService @DependentService
protected DBTraceModuleManager createModuleManager() throws CancelledException, IOException { protected DBTraceModuleManager createModuleManager(DBTraceObjectManager objectManager)
throws CancelledException, IOException {
return createTraceManager("Module Manager", return createTraceManager("Module Manager",
(openMode, monitor) -> new DBTraceModuleManager(dbh, openMode, rwLock, monitor, (openMode, monitor) -> new DBTraceModuleManager(dbh, openMode, rwLock, monitor, this,
baseLanguage, this)); objectManager));
} }
@DependentService @DependentService
@ -670,16 +671,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
if (recordChanges) { if (recordChanges) {
traceChangeSet.sourceArchiveAdded(sourceArchiveID.getValue()); traceChangeSet.sourceArchiveAdded(sourceArchiveID.getValue());
} }
setChanged( setChanged(new TraceChangeRecord<>(TraceEvents.SOURCE_TYPE_ARCHIVE_ADDED, null,
new TraceChangeRecord<>(TraceEvents.SOURCE_TYPE_ARCHIVE_ADDED, null, sourceArchiveID)); sourceArchiveID));
} }
public void dataTypeChanged(long changedID, DataType changedType) { public void dataTypeChanged(long changedID, DataType changedType) {
if (recordChanges) { if (recordChanges) {
traceChangeSet.dataTypeChanged(changedID); traceChangeSet.dataTypeChanged(changedID);
} }
setChanged( setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_CHANGED, null, changedID,
new TraceChangeRecord<>(TraceEvents.DATA_TYPE_CHANGED, null, changedID, changedType)); changedType));
} }
public void dataTypeAdded(long addedID, DataType addedType) { public void dataTypeAdded(long addedID, DataType addedType) {
@ -701,16 +702,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
if (recordChanges) { if (recordChanges) {
traceChangeSet.dataTypeChanged(movedID); traceChangeSet.dataTypeChanged(movedID);
} }
setChanged( setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_MOVED, null, movedID,
new TraceChangeRecord<>(TraceEvents.DATA_TYPE_MOVED, null, movedID, oldPath, newPath)); oldPath, newPath));
} }
public void dataTypeNameChanged(long renamedID, String oldName, String newName) { public void dataTypeNameChanged(long renamedID, String oldName, String newName) {
if (recordChanges) { if (recordChanges) {
traceChangeSet.dataTypeChanged(renamedID); traceChangeSet.dataTypeChanged(renamedID);
} }
setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_RENAMED, null, renamedID, oldName, setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_RENAMED, null, renamedID,
newName)); oldName, newName));
} }
public void dataTypeDeleted(long deletedID, DataTypePath deletedPath) { public void dataTypeDeleted(long deletedID, DataTypePath deletedPath) {
@ -725,16 +726,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
if (recordChanges) { if (recordChanges) {
traceChangeSet.categoryAdded(addedID); traceChangeSet.categoryAdded(addedID);
} }
setChanged( setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_ADDED, null, addedID,
new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_ADDED, null, addedID, addedCategory)); addedCategory));
} }
public void categoryMoved(long movedID, CategoryPath oldPath, CategoryPath newPath) { public void categoryMoved(long movedID, CategoryPath oldPath, CategoryPath newPath) {
if (recordChanges) { if (recordChanges) {
traceChangeSet.categoryChanged(movedID); traceChangeSet.categoryChanged(movedID);
} }
setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_MOVED, null, movedID, oldPath, setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_MOVED, null, movedID,
newPath)); oldPath, newPath));
} }
public void categoryRenamed(long renamedID, String oldName, String newName) { public void categoryRenamed(long renamedID, String oldName, String newName) {

View file

@ -433,18 +433,9 @@ public enum DBTraceUtils {
* *
* @param baseName the base name of the table group * @param baseName the base name of the table group
* @param space the address space * @param space the address space
* @param threadKey the thread key, -1 usually indicating "no thread"
* @param frameLevel the frame level
* @return the table name * @return the table name
*/ */
public static String tableName(String baseName, AddressSpace space, long threadKey, public static String tableName(String baseName, AddressSpace space) {
int frameLevel) {
if (space.isRegisterSpace()) {
if (frameLevel == 0) {
return baseName + "_" + space.getName() + "_" + threadKey;
}
return baseName + "_" + space.getName() + "_" + threadKey + "_" + frameLevel;
}
return baseName + "_" + space.getName(); return baseName + "_" + space.getName();
} }

View file

@ -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.
@ -222,7 +222,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
keyToRecordMap.remove(key); keyToRecordMap.remove(key);
} }
// Add any remaing overlay which are missing from factory // Add any remaining overlays which are missing from factory
for (long key : keyToRecordMap.keySet()) { for (long key : keyToRecordMap.keySet()) {
DBTraceOverlaySpaceEntry ent = keyToRecordMap.get(key); DBTraceOverlaySpaceEntry ent = keyToRecordMap.get(key);
String spaceName = ent.name; String spaceName = ent.name;
@ -268,7 +268,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
ent.set(space.getName(), base.getName()); ent.set(space.getName(), base.getName());
trace.updateViewsAddSpaceBlock(space); trace.updateViewsAddSpaceBlock(space);
trace.setChanged( trace.setChanged(
new TraceChangeRecord<>(TraceEvents.OVERLAY_ADDED, null, trace, null, space)); new TraceChangeRecord<>(TraceEvents.OVERLAY_ADDED, space, trace, null, space));
return space; return space;
} }
@ -315,7 +315,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager {
factory.removeOverlaySpace(name); factory.removeOverlaySpace(name);
trace.updateViewsDeleteSpaceBlock(space); trace.updateViewsDeleteSpaceBlock(space);
trace.setChanged( trace.setChanged(
new TraceChangeRecord<>(TraceEvents.OVERLAY_DELETED, null, trace, space, null)); new TraceChangeRecord<>(TraceEvents.OVERLAY_DELETED, space, trace, space, null));
invalidateCache(true); invalidateCache(true);
} }
} }

View file

@ -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.
@ -50,8 +50,8 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD
@DBAnnotatedColumn(COMMENT_COLUMN_NAME) @DBAnnotatedColumn(COMMENT_COLUMN_NAME)
static DBObjectColumn COMMENT_COLUMN; static DBObjectColumn COMMENT_COLUMN;
static String tableName(AddressSpace space, long threadKey, int frameLevel) { static String tableName(AddressSpace space) {
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); return DBTraceUtils.tableName(TABLE_NAME, space);
} }
@DBAnnotatedField(column = TYPE_COLUMN_NAME, indexed = true) @DBAnnotatedField(column = TYPE_COLUMN_NAME, indexed = true)
@ -104,7 +104,7 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD
@Override @Override
public long getId() { public long getId() {
return DBTraceBookmarkManager.packId(key, space); return DBTraceBookmarkManager.packId(key, range.getAddressSpace());
} }
@Override @Override
@ -140,14 +140,14 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD
update(CATEGORY_COLUMN, COMMENT_COLUMN); update(CATEGORY_COLUMN, COMMENT_COLUMN);
} }
space.trace.setChanged( space.trace.setChanged(
new TraceChangeRecord<>(TraceEvents.BOOKMARK_CHANGED, space, this)); new TraceChangeRecord<>(TraceEvents.BOOKMARK_CHANGED, space.space, this));
} }
@Override @Override
public void delete() { public void delete() {
space.bookmarkMapSpace.deleteData(this); space.bookmarkMapSpace.deleteData(this);
space.trace.setChanged( space.trace.setChanged(
new TraceChangeRecord<>(TraceEvents.BOOKMARK_DELETED, space, this)); new TraceChangeRecord<>(TraceEvents.BOOKMARK_DELETED, space.space, this));
} }
@Override @Override

View file

@ -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.
@ -29,7 +29,8 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTrace;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
import ghidra.trace.database.space.*; import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager;
import ghidra.trace.database.space.DBTraceDelegatingManager;
import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.database.thread.DBTraceThreadManager;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.bookmark.TraceBookmarkManager; import ghidra.trace.model.bookmark.TraceBookmarkManager;
@ -55,14 +56,6 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
* | SpaceID | Key | * | SpaceID | Key |
* +---------+----------+ * +---------+----------+
* } * }
*
* For register space:
*
* {@code
* +---12----+----32----+----8----+--12--+
* | SpaceID | Thread | Frame | Key |
* +---------+----------+---------+------+
* }
*/ */
// NOTE: There are few address spaces, but their IDs encode other stuff :/ // NOTE: There are few address spaces, but their IDs encode other stuff :/
protected static final int SPACE_ID_MASK = 0x0FFF; protected static final int SPACE_ID_MASK = 0x0FFF;
@ -71,23 +64,8 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
protected static final long MEM_KEY_MASK = 0x000F_FFFF_FFFF_FFFFL; protected static final long MEM_KEY_MASK = 0x000F_FFFF_FFFF_FFFFL;
protected static final int MEM_KEY_SHIFT = 0; protected static final int MEM_KEY_SHIFT = 0;
protected static final long REG_THREAD_MASK = 0x0_FFFF_FFFFL; protected static long packId(long key, AddressSpace space) {
protected static final int REG_THREAD_SHIFT = 20; long spaceId = space.getSpaceID();
protected static final long REG_FRAME_MASK = 0x00FF;
protected static final int REG_FRAME_SHIFT = 12;
protected static final long REG_KEY_MASK = 0x0FFF;
protected static final int REG_KEY_SHIFT = 0;
protected static long packId(long key, DBTraceSpaceKey spaceKey) {
return spaceKey.getAddressSpace().isRegisterSpace() ? packRegId(key, spaceKey)
: packMemId(key, spaceKey);
}
protected static long packMemId(long key, DBTraceSpaceKey spaceKey) {
long spaceId = spaceKey.getAddressSpace().getSpaceID();
assert spaceKey.getThread() == null;
if ((spaceId & SPACE_ID_MASK) != spaceId) { if ((spaceId & SPACE_ID_MASK) != spaceId) {
throw new AssertionError("Bad assumption"); throw new AssertionError("Bad assumption");
@ -98,69 +76,17 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
return (spaceId << SPACE_ID_SHIFT) | (key << MEM_KEY_SHIFT); return (spaceId << SPACE_ID_SHIFT) | (key << MEM_KEY_SHIFT);
} }
protected static long packRegId(long key, DBTraceSpaceKey spaceKey) {
long spaceId = spaceKey.getAddressSpace().getSpaceID();
long threadKey = spaceKey.getThread().getKey();
int frameLevel = spaceKey.getFrameLevel();
if ((spaceId & SPACE_ID_MASK) != spaceId) {
throw new AssertionError("Bad assumption");
}
if ((threadKey & REG_THREAD_MASK) != threadKey) {
throw new AssertionError("Bad assumption");
}
if ((frameLevel & REG_FRAME_MASK) != frameLevel) {
throw new AssertionError("Bad assumption");
}
if ((key & REG_KEY_MASK) != key) {
throw new AssertionError("Bad assumption");
}
return (spaceId << SPACE_ID_SHIFT) | (threadKey << REG_THREAD_SHIFT) |
(frameLevel << REG_FRAME_SHIFT) | (key << REG_KEY_SHIFT);
}
protected static int unpackSpaceId(long id) { protected static int unpackSpaceId(long id) {
return (int) ((id >> SPACE_ID_SHIFT) & SPACE_ID_MASK); return (int) ((id >> SPACE_ID_SHIFT) & SPACE_ID_MASK);
} }
protected static long unpackMemKey(long id) { protected static long unpackKey(long id) {
return (id >> MEM_KEY_SHIFT) & MEM_KEY_MASK; return (id >> MEM_KEY_SHIFT) & MEM_KEY_MASK;
} }
protected static long unpackRegThread(long id) { protected static AddressSpace unpackSpace(long id, AddressFactory addressFactory) {
return (id >> REG_THREAD_SHIFT) & REG_THREAD_MASK;
}
protected static int unpackRegFrame(long id) {
return (int) ((id >> REG_FRAME_SHIFT) & REG_FRAME_MASK);
}
protected static long unpackRegKey(long id) {
return (id >> REG_KEY_SHIFT) & REG_KEY_MASK;
}
protected static DBTraceSpaceKey unpackSpaceKey(long id, Language baseLanguage,
DBTraceThreadManager threadManager) {
int spaceId = unpackSpaceId(id); int spaceId = unpackSpaceId(id);
AddressSpace space = baseLanguage.getAddressFactory().getAddressSpace(spaceId); return addressFactory.getAddressSpace(spaceId);
if (space == null) {
return null;
}
return space.isRegisterSpace() ? unpackRegSpaceKey(space, threadManager, id)
: unpackMemSpaceKey(space, id);
}
protected static DBTraceSpaceKey unpackMemSpaceKey(AddressSpace space, long id) {
return DBTraceSpaceKey.create(space, null, 0);
}
protected static DBTraceSpaceKey unpackRegSpaceKey(AddressSpace space,
DBTraceThreadManager threadManager, long id) {
long threadKey = unpackRegThread(id);
TraceThread thread = threadManager.getThread(threadKey);
assert thread != null;
int frameLevel = unpackRegFrame(id);
return DBTraceSpaceKey.create(space, thread, frameLevel);
} }
protected final Map<String, DBTraceBookmarkType> typesByName = new HashMap<>(); protected final Map<String, DBTraceBookmarkType> typesByName = new HashMap<>();
@ -178,13 +104,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
@Override @Override
protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceBookmarkSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceBookmarkSpace(this, space, null, 0); return new DBTraceBookmarkSpace(this, space);
}
@Override
protected DBTraceBookmarkSpace createRegisterSpace(AddressSpace space, TraceThread thread,
DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceBookmarkSpace(this, space, thread, ent.getFrameLevel());
} }
@Override @Override
@ -267,16 +187,15 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
@Override @Override
public DBTraceBookmark getBookmark(long id) { public DBTraceBookmark getBookmark(long id) {
try (LockHold hold = LockHold.lock(lock.readLock())) { try (LockHold hold = LockHold.lock(lock.readLock())) {
DBTraceSpaceKey spaceKey = unpackSpaceKey(id, baseLanguage, threadManager); AddressSpace addressSpace = unpackSpace(id, trace.getInternalAddressFactory());
if (spaceKey == null) { if (addressSpace == null) {
return null; return null;
} }
DBTraceBookmarkSpace space = get(spaceKey, false); DBTraceBookmarkSpace space = get(addressSpace, false);
if (space == null) { if (space == null) {
return null; return null;
} }
long bookmarkKey = long bookmarkKey = unpackKey(id);
spaceKey.getAddressSpace().isRegisterSpace() ? unpackRegKey(id) : unpackMemKey(id);
return space.bookmarkMapSpace.getDataByKey(bookmarkKey); return space.bookmarkMapSpace.getDataByKey(bookmarkKey);
} }
} }
@ -288,7 +207,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
@Override @Override
public Set<String> getCategoriesForType(TraceBookmarkType type) { public Set<String> getCategoriesForType(TraceBookmarkType type) {
return delegateHashSet(getActiveMemorySpaces(), m -> m.getCategoriesForType(type)); return delegateHashSet(getActiveSpaces(), m -> m.getCategoriesForType(type));
} }
@Override @Override
@ -300,7 +219,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
@Override @Override
public Collection<? extends DBTraceBookmark> getAllBookmarks() { public Collection<? extends DBTraceBookmark> getAllBookmarks() {
return delegateCollection(getActiveMemorySpaces(), m -> m.getAllBookmarks()); return delegateCollection(getActiveSpaces(), m -> m.getAllBookmarks());
} }
@Override @Override
@ -329,7 +248,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
return Collections.emptySet(); return Collections.emptySet();
} }
Collection<DBTraceBookmark> result = new ArrayList<>(); Collection<DBTraceBookmark> result = new ArrayList<>();
for (DBTraceBookmarkSpace space : memSpaces.values()) { for (DBTraceBookmarkSpace space : spaces.values()) {
result.addAll(space.bookmarkMapSpace result.addAll(space.bookmarkMapSpace
.reduce(TraceAddressSnapRangeQuery.added(from, to, space.getAddressSpace())) .reduce(TraceAddressSnapRangeQuery.added(from, to, space.getAddressSpace()))
.values()); .values());
@ -343,7 +262,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager<DBT
return Collections.emptySet(); return Collections.emptySet();
} }
Collection<DBTraceBookmark> result = new ArrayList<>(); Collection<DBTraceBookmark> result = new ArrayList<>();
for (DBTraceBookmarkSpace space : memSpaces.values()) { for (DBTraceBookmarkSpace space : spaces.values()) {
result.addAll(space.bookmarkMapSpace result.addAll(space.bookmarkMapSpace
.reduce(TraceAddressSnapRangeQuery.removed(from, to, space.getAddressSpace())) .reduce(TraceAddressSnapRangeQuery.removed(from, to, space.getAddressSpace()))
.values()); .values());

View file

@ -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.
@ -25,9 +25,9 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
import ghidra.trace.database.space.DBTraceSpaceBased; import ghidra.trace.database.space.DBTraceSpaceBased;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace;
import ghidra.trace.model.bookmark.TraceBookmarkSpace; import ghidra.trace.model.bookmark.TraceBookmarkSpace;
import ghidra.trace.model.bookmark.TraceBookmarkType; import ghidra.trace.model.bookmark.TraceBookmarkType;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceChangeRecord;
import ghidra.trace.util.TraceEvents; import ghidra.trace.util.TraceEvents;
import ghidra.util.LockHold; import ghidra.util.LockHold;
@ -39,47 +39,37 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final DBTrace trace; protected final DBTrace trace;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBookmark, DBTraceBookmark> bookmarkMapSpace; protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBookmark, DBTraceBookmark> bookmarkMapSpace;
protected final DBCachedObjectIndex<String, DBTraceBookmark> bookmarksByTypeName; protected final DBCachedObjectIndex<String, DBTraceBookmark> bookmarksByTypeName;
protected final Collection<DBTraceBookmark> bookmarkView; protected final Collection<DBTraceBookmark> bookmarkView;
public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space, public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space)
TraceThread thread, int frameLevel)
throws VersionException, IOException { throws VersionException, IOException {
this.manager = manager; this.manager = manager;
this.lock = manager.getLock(); this.lock = manager.getLock();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = frameLevel;
this.bookmarkMapSpace = this.bookmarkMapSpace =
new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space, -1, 0), new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space), trace,
trace.getStoreFactory(), lock, space, null, 0, DBTraceBookmark.class, trace.getStoreFactory(), lock, space, DBTraceBookmark.class,
(t, s, r) -> new DBTraceBookmark(this, t, s, r)); (t, s, r) -> new DBTraceBookmark(this, t, s, r));
this.bookmarksByTypeName = this.bookmarksByTypeName =
bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN); bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN);
this.bookmarkView = Collections.unmodifiableCollection(bookmarkMapSpace.values()); this.bookmarkView = Collections.unmodifiableCollection(bookmarkMapSpace.values());
} }
@Override
public Trace getTrace() {
return trace;
}
@Override @Override
public AddressSpace getAddressSpace() { public AddressSpace getAddressSpace() {
return space; return space;
} }
@Override
public TraceThread getThread() {
return thread;
}
@Override
public int getFrameLevel() {
return frameLevel;
}
protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) { protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) {
if (!(type instanceof DBTraceBookmarkType)) { if (!(type instanceof DBTraceBookmarkType)) {
throw new IllegalArgumentException("Given type is not part of this trace"); throw new IllegalArgumentException("Given type is not part of this trace");
@ -110,7 +100,7 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas
try (LockHold hold = LockHold.lock(lock.writeLock())) { try (LockHold hold = LockHold.lock(lock.writeLock())) {
DBTraceBookmark bookmark = bookmarkMapSpace.put(address, lifespan, null); DBTraceBookmark bookmark = bookmarkMapSpace.put(address, lifespan, null);
bookmark.set(type.getTypeString(), category, comment); bookmark.set(type.getTypeString(), category, comment);
trace.setChanged(new TraceChangeRecord<>(TraceEvents.BOOKMARK_ADDED, this, bookmark)); trace.setChanged(new TraceChangeRecord<>(TraceEvents.BOOKMARK_ADDED, space, bookmark));
return bookmark; return bookmark;
} }
} }

View file

@ -1,460 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.breakpoint;
import java.io.IOException;
import java.util.*;
import db.DBRecord;
import ghidra.pcode.exec.SleighUtils;
import ghidra.program.model.address.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.DBTraceUtils;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData;
import ghidra.trace.database.thread.DBTraceThreadManager;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.trace.util.TraceEvents;
import ghidra.util.LockHold;
import ghidra.util.Msg;
import ghidra.util.database.DBCachedObjectStore;
import ghidra.util.database.DBObjectColumn;
import ghidra.util.database.annot.*;
import ghidra.util.exception.DuplicateNameException;
@DBAnnotatedObjectInfo(version = 1)
public class DBTraceBreakpoint
extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceBreakpoint>
implements TraceBreakpoint {
protected static final String TABLE_NAME = "Breakpoints";
private static final byte ENABLED_MASK = (byte) (1 << 7);
private static final byte EMU_ENABLED_MASK = (byte) (1 << 6);
static final String PATH_COLUMN_NAME = "Path";
static final String NAME_COLUMN_NAME = "Name";
static final String THREADS_COLUMN_NAME = "Threads";
static final String FLAGS_COLUMN_NAME = "Flags";
static final String COMMENT_COLUMN_NAME = "Comment";
static final String SLEIGH_COLUMN_NAME = "Sleigh";
@DBAnnotatedColumn(PATH_COLUMN_NAME)
static DBObjectColumn PATH_COLUMN;
@DBAnnotatedColumn(NAME_COLUMN_NAME)
static DBObjectColumn NAME_COLUMN;
@DBAnnotatedColumn(THREADS_COLUMN_NAME)
static DBObjectColumn THREADS_COLUMN;
@DBAnnotatedColumn(FLAGS_COLUMN_NAME)
static DBObjectColumn FLAGS_COLUMN;
@DBAnnotatedColumn(COMMENT_COLUMN_NAME)
static DBObjectColumn COMMENT_COLUMN;
@DBAnnotatedColumn(SLEIGH_COLUMN_NAME)
static DBObjectColumn SLEIGH_COLUMN;
protected static String tableName(AddressSpace space, long threadKey) {
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0);
}
@DBAnnotatedField(column = PATH_COLUMN_NAME, indexed = true)
private String path;
@DBAnnotatedField(column = NAME_COLUMN_NAME)
private String name;
@DBAnnotatedField(column = THREADS_COLUMN_NAME)
private long[] threadKeys;
@DBAnnotatedField(column = FLAGS_COLUMN_NAME)
private byte flagsByte;
@DBAnnotatedField(column = COMMENT_COLUMN_NAME)
private String comment;
@DBAnnotatedField(column = SLEIGH_COLUMN_NAME)
private String emuSleigh;
private final Set<TraceBreakpointKind> kinds = EnumSet.noneOf(TraceBreakpointKind.class);
private final Set<TraceBreakpointKind> kindsView = Collections.unmodifiableSet(kinds);
private boolean enabled;
private boolean emuEnabled;
protected final DBTraceBreakpointSpace space;
public DBTraceBreakpoint(DBTraceBreakpointSpace space,
DBTraceAddressSnapRangePropertyMapTree<DBTraceBreakpoint, ?> tree,
DBCachedObjectStore<?> store, DBRecord record) {
super(tree, store, record);
this.space = space;
}
@Override
protected void fresh(boolean created) throws IOException {
super.fresh(created);
if (created) {
return;
}
doFresh();
}
private void doFresh() {
kinds.clear();
for (TraceBreakpointKind k : TraceBreakpointKind.values()) {
if ((flagsByte & k.getBits()) != 0) {
kinds.add(k);
}
}
enabled = (flagsByte & ENABLED_MASK) != 0;
emuEnabled = (flagsByte & EMU_ENABLED_MASK) != 0;
}
@Override
public DBTrace getTrace() {
return space.trace;
}
@Override
protected void setRecordValue(DBTraceBreakpoint value) {
// Nothing: record is the value
}
@Override
protected DBTraceBreakpoint getRecordValue() {
return this;
}
public void set(String path, String name, Collection<TraceThread> threads,
Collection<TraceBreakpointKind> kinds, boolean enabled, boolean emuEnabled,
String comment) {
// TODO: Check that the threads exist and that each's lifespan covers the breakpoint's
// TODO: This would require additional validation any time those are updated
// TODO: For efficiency, would also require index of breakpoints by thread
this.path = path;
this.name = name;
if (!(threads instanceof Set<?>)) {
threads = Set.copyOf(threads);
}
this.threadKeys = new long[threads.size()];
int i = 0;
for (TraceThread t : threads) {
this.threadKeys[i++] = t.getKey();
}
this.flagsByte = 0;
this.kinds.clear();
for (TraceBreakpointKind k : kinds) {
this.flagsByte |= k.getBits();
this.kinds.add(k);
}
if (enabled) {
this.flagsByte |= ENABLED_MASK;
}
if (emuEnabled) {
this.flagsByte |= EMU_ENABLED_MASK;
}
this.comment = comment;
update(PATH_COLUMN, NAME_COLUMN, THREADS_COLUMN, FLAGS_COLUMN, COMMENT_COLUMN);
this.enabled = enabled;
this.emuEnabled = emuEnabled;
// Msg.debug(this, "trace: breakpoint " + this + " enabled=" + enabled + ", because set");
}
public void set(String path, String name, long[] threadKeys,
byte flagsByte, String comment) {
this.path = path;
this.name = name;
this.threadKeys = Arrays.copyOf(threadKeys, threadKeys.length);
this.flagsByte = flagsByte;
this.comment = comment;
update(PATH_COLUMN, NAME_COLUMN, THREADS_COLUMN, FLAGS_COLUMN, COMMENT_COLUMN);
doFresh();
}
@Override
public String getPath() {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return path;
}
}
@Override
public void setName(long snap, String name) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
this.name = name;
update(NAME_COLUMN);
}
space.trace
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
}
@Override
public String getName(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return name;
}
}
@Override
public Set<TraceThread> getThreads(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
if (threadKeys.length == 0) {
return Set.of();
}
// NOTE: Caching this result could get hairy if any threads are invalidated....
Set<TraceThread> threads = new LinkedHashSet<>(threadKeys.length);
DBTraceThreadManager threadManager = space.trace.getThreadManager();
for (int i = 0; i < threadKeys.length; i++) {
TraceThread t = threadManager.getThread(threadKeys[i]);
if (t == null) {
Msg.warn(this, "Thread " + threadKeys[i] +
" has been deleted since creating this breakpoint.");
}
threads.add(t);
}
return Collections.unmodifiableSet(threads);
}
}
@Override
public AddressRange getRange(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return range;
}
}
@Override
public Address getMinAddress(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return range.getMinAddress();
}
}
@Override
public Address getMaxAddress(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return range.getMaxAddress();
}
}
@Override
public long getLength(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return range.getLength();
}
}
protected void setLifespan(Lifespan newLifespan) throws DuplicateNameException {
Lifespan oldLifespan;
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
space.manager.checkDuplicatePath(this, path, newLifespan);
oldLifespan = lifespan;
doSetLifespan(newLifespan);
}
space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_LIFESPAN_CHANGED,
space, this, oldLifespan, newLifespan));
}
@Override
public Lifespan getLifespan() {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return lifespan;
}
}
protected DBTraceBreakpoint doCopy() {
DBTraceBreakpoint breakpoint = space.breakpointMapSpace.put(this, null);
breakpoint.set(path, name, threadKeys, flagsByte, comment);
return breakpoint;
}
protected static byte computeFlagsByte(boolean enabled, Collection<TraceBreakpointKind> kinds) {
byte flags = 0;
for (TraceBreakpointKind k : kinds) {
flags |= k.getBits();
}
if (enabled) {
flags |= ENABLED_MASK;
}
return flags;
}
protected void doSetFlags(boolean enabled, Collection<TraceBreakpointKind> kinds) {
this.flagsByte = computeFlagsByte(enabled, kinds);
this.kinds.clear();
this.kinds.addAll(kinds);
this.enabled = enabled;
// Msg.debug(this,
// "trace: breakpoint " + this + " enabled=" + enabled + ", because doSetFlags");
update(FLAGS_COLUMN);
}
protected void doSetEnabled(boolean enabled) {
this.enabled = enabled;
// Msg.debug(this,
// "trace: breakpoint " + this + " enabled=" + enabled + ", because doSetEnabled");
if (enabled) {
flagsByte |= ENABLED_MASK;
}
else {
flagsByte &= ~ENABLED_MASK;
}
update(FLAGS_COLUMN);
}
protected void doSetEmuEnabled(boolean emuEnabled) {
this.emuEnabled = emuEnabled;
if (emuEnabled) {
flagsByte |= EMU_ENABLED_MASK;
}
else {
flagsByte &= ~EMU_ENABLED_MASK;
}
update(FLAGS_COLUMN);
}
protected void doSetKinds(Collection<TraceBreakpointKind> kinds) {
for (TraceBreakpointKind k : TraceBreakpointKind.values()) {
if (kinds.contains(k)) {
this.flagsByte |= k.getBits();
this.kinds.add(k);
}
else {
this.flagsByte &= ~k.getBits();
this.kinds.remove(k);
}
}
update(FLAGS_COLUMN);
}
@Override
public void setEnabled(long snap, boolean enabled) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
doSetEnabled(enabled);
}
space.trace
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
}
@Override
public boolean isEnabled(long snap) {
// NB. Only object mode supports per-snap enablement
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return enabled;
}
}
@Override
public void setEmuEnabled(long snap, boolean enabled) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
doSetEmuEnabled(enabled);
}
space.trace
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
}
@Override
public boolean isEmuEnabled(long snap) {
// NB. Only object mode support per-snap emu-enablement
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return emuEnabled;
}
}
@Override
public void setKinds(long snap, Collection<TraceBreakpointKind> kinds) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
doSetKinds(kinds);
}
space.trace
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
}
@Override
public Set<TraceBreakpointKind> getKinds(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return kindsView;
}
}
@Override
public void setComment(long snap, String comment) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
this.comment = comment;
update(COMMENT_COLUMN);
}
space.trace
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
}
@Override
public String getComment(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return comment;
}
}
@Override
public void setEmuSleigh(long snap, String emuSleigh) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
if (emuSleigh == null || SleighUtils.UNCONDITIONAL_BREAK.equals(emuSleigh)) {
this.emuSleigh = null;
}
else {
this.emuSleigh = emuSleigh.trim();
}
update(SLEIGH_COLUMN);
}
space.trace
.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this));
}
@Override
public String getEmuSleigh(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return emuSleigh == null || emuSleigh.isBlank() ? SleighUtils.UNCONDITIONAL_BREAK
: emuSleigh;
}
}
@Override
public void delete() {
space.deleteBreakpoint(this);
}
@Override
public void remove(long snap) {
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
if (snap <= lifespan.lmin()) {
space.deleteBreakpoint(this);
}
else if (snap <= lifespan.lmax()) {
doSetLifespan(lifespan.withMax(snap - 1));
}
}
}
@Override
public boolean isValid(long snap) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return lifespan.contains(snap);
}
}
@Override
public boolean isAlive(Lifespan span) {
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
return lifespan.intersects(span);
}
}
}

View file

@ -19,54 +19,55 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import ghidra.pcode.exec.SleighUtils; import ghidra.pcode.exec.SleighUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.*;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.database.target.*; import ghidra.trace.database.target.*;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.breakpoint.TraceBreakpointSpec;
import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.iface.TraceObjectTogglable; import ghidra.trace.model.target.iface.TraceTogglable;
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
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;
import ghidra.trace.model.thread.*; import ghidra.trace.model.thread.TraceProcess;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.*; import ghidra.trace.util.*;
import ghidra.util.LockHold; import ghidra.util.LockHold;
public class DBTraceObjectBreakpointLocation public class DBTraceBreakpointLocation
implements TraceObjectBreakpointLocation, DBTraceObjectInterface { implements TraceBreakpointLocation, DBTraceObjectInterface {
protected static class BreakpointChangeTranslator extends Translator<TraceBreakpoint> { protected static class BreakpointChangeTranslator extends Translator<TraceBreakpointLocation> {
private static final Map<TraceObjectSchema, Set<String>> KEYS_BY_SCHEMA = private static final Map<TraceObjectSchema, Set<String>> KEYS_BY_SCHEMA =
new WeakHashMap<>(); new WeakHashMap<>();
private final Set<String> keys; private final Set<String> keys;
protected BreakpointChangeTranslator(DBTraceObject object, TraceBreakpoint iface) { protected BreakpointChangeTranslator(DBTraceObject object, TraceBreakpointLocation iface) {
super(KEY_RANGE, object, iface); super(KEY_RANGE, object, iface);
TraceObjectSchema schema = object.getSchema(); TraceObjectSchema schema = object.getSchema();
synchronized (KEYS_BY_SCHEMA) { synchronized (KEYS_BY_SCHEMA) {
keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of(
schema.checkAliasedAttribute(KEY_RANGE), schema.checkAliasedAttribute(KEY_RANGE),
schema.checkAliasedAttribute(KEY_DISPLAY), schema.checkAliasedAttribute(KEY_DISPLAY),
schema.checkAliasedAttribute(TraceObjectTogglable.KEY_ENABLED), schema.checkAliasedAttribute(TraceTogglable.KEY_ENABLED),
schema.checkAliasedAttribute(KEY_COMMENT))); schema.checkAliasedAttribute(KEY_COMMENT)));
} }
} }
@Override @Override
protected TraceEvent<TraceBreakpoint, Void> getAddedType() { protected TraceEvent<TraceBreakpointLocation, Void> getAddedType() {
return TraceEvents.BREAKPOINT_ADDED; return TraceEvents.BREAKPOINT_ADDED;
} }
@Override @Override
protected TraceEvent<TraceBreakpoint, Lifespan> getLifespanChangedType() { protected TraceEvent<TraceBreakpointLocation, Lifespan> getLifespanChangedType() {
return TraceEvents.BREAKPOINT_LIFESPAN_CHANGED; return TraceEvents.BREAKPOINT_LIFESPAN_CHANGED;
} }
@Override @Override
protected TraceEvent<TraceBreakpoint, Void> getChangedType() { protected TraceEvent<TraceBreakpointLocation, Void> getChangedType() {
return TraceEvents.BREAKPOINT_CHANGED; return TraceEvents.BREAKPOINT_CHANGED;
} }
@ -76,7 +77,7 @@ public class DBTraceObjectBreakpointLocation
} }
@Override @Override
protected TraceEvent<TraceBreakpoint, Void> getDeletedType() { protected TraceEvent<TraceBreakpointLocation, Void> getDeletedType() {
return TraceEvents.BREAKPOINT_DELETED; return TraceEvents.BREAKPOINT_DELETED;
} }
} }
@ -84,7 +85,7 @@ public class DBTraceObjectBreakpointLocation
private final DBTraceObject object; private final DBTraceObject object;
private final BreakpointChangeTranslator translator; private final BreakpointChangeTranslator translator;
public DBTraceObjectBreakpointLocation(DBTraceObject object) { public DBTraceBreakpointLocation(DBTraceObject object) {
this.object = object; this.object = object;
translator = new BreakpointChangeTranslator(object, this); translator = new BreakpointChangeTranslator(object, this);
@ -107,9 +108,7 @@ public class DBTraceObjectBreakpointLocation
@Override @Override
public void setName(long snap, String name) { public void setName(long snap, String name) {
try (LockHold hold = object.getTrace().lockWrite()) { setName(Lifespan.nowOn(snap), name);
setName(Lifespan.nowOn(snap), name);
}
} }
@Override @Override
@ -121,7 +120,7 @@ public class DBTraceObjectBreakpointLocation
return display; return display;
} }
TraceObject spec = TraceObject spec =
object.findCanonicalAncestorsInterface(TraceObjectBreakpointSpec.class) object.findCanonicalAncestorsInterface(TraceBreakpointSpec.class)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
if (spec == null) { if (spec == null) {
@ -169,21 +168,19 @@ public class DBTraceObjectBreakpointLocation
@Override @Override
public void setEnabled(Lifespan lifespan, boolean enabled) { public void setEnabled(Lifespan lifespan, boolean enabled) {
object.setValue(lifespan, TraceObjectTogglable.KEY_ENABLED, enabled); object.setValue(lifespan, TraceTogglable.KEY_ENABLED, enabled);
} }
@Override @Override
public void setEnabled(long snap, boolean enabled) { public void setEnabled(long snap, boolean enabled) {
try (LockHold hold = object.getTrace().lockWrite()) { setEnabled(Lifespan.nowOn(snap), enabled);
setEnabled(Lifespan.nowOn(snap), enabled);
}
} }
@Override @Override
public boolean isEnabled(long snap) { public boolean isEnabled(long snap) {
try (LockHold hold = object.getTrace().lockRead()) { try (LockHold hold = object.getTrace().lockRead()) {
Boolean locEn = TraceObjectInterfaceUtils.getValue(object, snap, Boolean locEn = TraceObjectInterfaceUtils.getValue(object, snap,
TraceObjectTogglable.KEY_ENABLED, Boolean.class, null); TraceTogglable.KEY_ENABLED, Boolean.class, null);
if (locEn != null) { if (locEn != null) {
return locEn && getSpecification().isEnabled(snap); return locEn && getSpecification().isEnabled(snap);
} }
@ -191,31 +188,6 @@ public class DBTraceObjectBreakpointLocation
} }
} }
@Override
public void setKinds(Lifespan lifespan, Collection<TraceBreakpointKind> kinds) {
try (LockHold hold = object.getTrace().lockWrite()) {
TraceObjectBreakpointSpec spec = getSpecification();
if (spec.getObject() != this.getObject()) {
throw new UnsupportedOperationException("Set via the specification instead");
}
spec.setKinds(lifespan, kinds);
}
}
@Override
public void setKinds(long snap, Collection<TraceBreakpointKind> kinds) {
try (LockHold hold = object.getTrace().lockWrite()) {
setKinds(Lifespan.nowOn(snap), kinds);
}
}
@Override
public Set<TraceBreakpointKind> getKinds(long snap) {
try (LockHold hold = object.getTrace().lockRead()) {
return getSpecification().getKinds(snap);
}
}
@Override @Override
public Set<TraceThread> getThreads(long snap) { public Set<TraceThread> getThreads(long snap) {
// TODO: Delete this? It's sort of deprecated out the gate anyway.... // TODO: Delete this? It's sort of deprecated out the gate anyway....
@ -223,17 +195,17 @@ public class DBTraceObjectBreakpointLocation
TraceObjectSchema schema = manager.getRootSchema(); TraceObjectSchema schema = manager.getRootSchema();
try (LockHold hold = object.getTrace().lockRead()) { try (LockHold hold = object.getTrace().lockRead()) {
Set<TraceThread> threads = Set<TraceThread> threads =
object.queryAncestorsInterface(Lifespan.at(snap), TraceObjectThread.class) object.queryAncestorsInterface(Lifespan.at(snap), TraceThread.class)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
if (!threads.isEmpty()) { if (!threads.isEmpty()) {
return threads; return threads;
} }
PathFilter procFilter = schema.searchFor(TraceObjectProcess.class, false); PathFilter procFilter = schema.searchFor(TraceProcess.class, false);
Lifespan lifespan = Lifespan.at(snap); Lifespan lifespan = Lifespan.at(snap);
return object.getAncestorsRoot(lifespan, procFilter) return object.getAncestorsRoot(lifespan, procFilter)
.flatMap(proc -> proc.getSource(object) .flatMap(proc -> proc.getSource(object)
.querySuccessorsInterface(lifespan, TraceObjectThread.class, true)) .querySuccessorsInterface(lifespan, TraceThread.class, true))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
} }
@ -245,9 +217,7 @@ public class DBTraceObjectBreakpointLocation
@Override @Override
public void setComment(long snap, String comment) { public void setComment(long snap, String comment) {
try (LockHold hold = object.getTrace().lockWrite()) { setComment(Lifespan.nowOn(snap), comment);
setComment(Lifespan.nowOn(snap), comment);
}
} }
@Override @Override
@ -258,11 +228,11 @@ public class DBTraceObjectBreakpointLocation
if (!comment.isBlank()) { if (!comment.isBlank()) {
return comment; return comment;
} }
TraceObjectBreakpointSpec spec = getSpecification(); TraceBreakpointSpec spec = getSpecification();
if (spec == null) { if (spec == null) {
return ""; return "";
} }
return spec.getExpression(snap); return spec.getComment(snap);
} }
} }
@ -340,20 +310,20 @@ public class DBTraceObjectBreakpointLocation
return object; return object;
} }
public TraceObjectBreakpointSpec getOrCreateSpecification() { public TraceBreakpointSpec getOrCreateSpecification() {
return object.queryOrCreateCanonicalAncestorInterface(TraceObjectBreakpointSpec.class); return object.queryOrCreateCanonicalAncestorInterface(TraceBreakpointSpec.class);
} }
@Override @Override
public TraceObjectBreakpointSpec getSpecification() { public TraceBreakpointSpec getSpecification() {
try (LockHold hold = object.getTrace().lockRead()) { try (LockHold hold = object.getTrace().lockRead()) {
return object.queryCanonicalAncestorsInterface(TraceObjectBreakpointSpec.class) return object.queryCanonicalAncestorsInterface(TraceBreakpointSpec.class)
.findAny() .findAny()
.orElseThrow(); .orElseThrow();
} }
} }
public TraceAddressSpace getTraceAddressSpace(long snap) { public AddressSpace getAddressSpace(long snap) {
return spaceForValue(snap, KEY_RANGE); return spaceForValue(snap, KEY_RANGE);
} }

View file

@ -17,146 +17,89 @@ package ghidra.trace.database.breakpoint;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import db.DBHandle; import db.DBHandle;
import ghidra.framework.data.OpenMode; import ghidra.framework.data.OpenMode;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language; import ghidra.program.model.address.AddressRange;
import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTrace;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager; import ghidra.trace.database.DBTraceManager;
import ghidra.trace.database.space.DBTraceDelegatingManager; import ghidra.trace.database.target.DBTraceObjectManager;
import ghidra.trace.database.thread.DBTraceThreadManager;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.*;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.LockHold;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.VersionException; import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DBTraceBreakpointManager public class DBTraceBreakpointManager implements TraceBreakpointManager, DBTraceManager {
extends AbstractDBTraceSpaceBasedManager<DBTraceBreakpointSpace> protected final ReadWriteLock lock;
implements TraceBreakpointManager, DBTraceDelegatingManager<DBTraceBreakpointSpace> { protected final DBTrace trace;
protected static final String NAME = "Breakpoint"; protected final DBTraceObjectManager objectManager;
public DBTraceBreakpointManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock, public DBTraceBreakpointManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock,
TaskMonitor monitor, Language baseLanguage, DBTrace trace, TaskMonitor monitor, DBTrace trace, DBTraceObjectManager objectManager)
DBTraceThreadManager threadManager) throws VersionException, IOException {
super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager);
loadSpaces();
}
@Override
protected DBTraceBreakpointSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceBreakpointSpace(this, dbh, space, ent); this.lock = lock;
this.trace = trace;
this.objectManager = objectManager;
} }
@Override @Override
protected DBTraceBreakpointSpace createRegisterSpace(AddressSpace space, TraceThread thread, public void dbError(IOException e) {
DBTraceSpaceEntry ent) throws VersionException, IOException { trace.dbError(e);
throw new UnsupportedOperationException();
} }
@Override @Override
public DBTraceBreakpointSpace getForSpace(AddressSpace space, boolean createIfAbsent) { public void invalidateCache(boolean all) {
return super.getForSpace(space, createIfAbsent); // NOTE: This is only a wrapper around the object manager
} }
@Override @Override
public Lock readLock() { public TraceBreakpointLocation addBreakpoint(String path, Lifespan lifespan, AddressRange range,
return lock.readLock();
}
@Override
public Lock writeLock() {
return lock.writeLock();
}
protected void checkDuplicatePath(TraceBreakpoint ignore, String path, Lifespan lifespan)
throws DuplicateNameException {
for (TraceBreakpoint pc : getBreakpointsByPath(path)) {
if (pc == ignore) {
continue;
}
if (!pc.isAlive(lifespan)) {
continue;
}
throw new DuplicateNameException("A breakpoint having path '" + path +
"' already exists within an overlapping snap");
}
}
@Override
public TraceBreakpoint addBreakpoint(String path, Lifespan lifespan, AddressRange range,
Collection<TraceThread> threads, Collection<TraceBreakpointKind> kinds, boolean enabled, Collection<TraceThread> threads, Collection<TraceBreakpointKind> kinds, boolean enabled,
String comment) throws DuplicateNameException { String comment) throws DuplicateNameException {
if (trace.getObjectManager().hasSchema()) { return objectManager.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment);
return trace.getObjectManager()
.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment);
}
checkDuplicatePath(null, path, lifespan);
return delegateWrite(range.getAddressSpace(),
m -> m.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment));
} }
@Override @Override
public Collection<? extends TraceBreakpoint> getAllBreakpoints() { public Collection<? extends TraceBreakpointSpec> getAllBreakpointSpecifications() {
if (trace.getObjectManager().hasSchema()) { return objectManager.getAllObjects(TraceBreakpointSpec.class);
return trace.getObjectManager().getAllObjects(TraceObjectBreakpointLocation.class);
}
return delegateCollection(getActiveMemorySpaces(), m -> m.getAllBreakpoints());
} }
@Override @Override
public Collection<? extends TraceBreakpoint> getBreakpointsByPath(String path) { public Collection<? extends TraceBreakpointLocation> getAllBreakpointLocations() {
if (trace.getObjectManager().hasSchema()) { return objectManager.getAllObjects(TraceBreakpointLocation.class);
return trace.getObjectManager()
.getObjectsByPath(path, TraceObjectBreakpointLocation.class);
}
return delegateCollection(getActiveMemorySpaces(), m -> m.getBreakpointsByPath(path));
} }
@Override @Override
public TraceBreakpoint getPlacedBreakpointByPath(long snap, String path) { public Collection<? extends TraceBreakpointSpec> getBreakpointSpecificationsByPath(
if (trace.getObjectManager().hasSchema()) { String path) {
return trace.getObjectManager() return objectManager.getObjectsByPath(path, TraceBreakpointSpec.class);
.getObjectByPath(snap, path, TraceObjectBreakpointLocation.class);
}
try (LockHold hold = LockHold.lock(lock.readLock())) {
return getBreakpointsByPath(path).stream()
.filter(b -> b.isValid(snap))
.findAny()
.orElse(null);
}
} }
@Override @Override
public Collection<? extends TraceBreakpoint> getBreakpointsAt(long snap, Address address) { public Collection<? extends TraceBreakpointLocation> getBreakpointLocationsByPath(String path) {
if (trace.getObjectManager().hasSchema()) { return objectManager.getObjectsByPath(path, TraceBreakpointLocation.class);
return trace.getObjectManager()
.getObjectsContaining(snap, address,
TraceObjectBreakpointLocation.KEY_RANGE,
TraceObjectBreakpointLocation.class);
}
return delegateRead(address.getAddressSpace(), m -> m.getBreakpointsAt(snap, address),
Collections.emptyList());
} }
@Override @Override
public Collection<? extends TraceBreakpoint> getBreakpointsIntersecting(Lifespan span, public TraceBreakpointLocation getPlacedBreakpointByPath(long snap, String path) {
return objectManager.getObjectByPath(snap, path, TraceBreakpointLocation.class);
}
@Override
public Collection<? extends TraceBreakpointLocation> getBreakpointsAt(long snap,
Address address) {
return objectManager.getObjectsContaining(snap, address, TraceBreakpointLocation.KEY_RANGE,
TraceBreakpointLocation.class);
}
@Override
public Collection<? extends TraceBreakpointLocation> getBreakpointsIntersecting(Lifespan span,
AddressRange range) { AddressRange range) {
if (trace.getObjectManager().hasSchema()) { return objectManager.getObjectsIntersecting(span, range, TraceBreakpointLocation.KEY_RANGE,
return trace.getObjectManager() TraceBreakpointLocation.class);
.getObjectsIntersecting(span, range,
TraceObjectBreakpointLocation.KEY_RANGE,
TraceObjectBreakpointLocation.class);
}
return delegateRead(range.getAddressSpace(), m -> m.getBreakpointsIntersecting(span, range),
Collections.emptyList());
} }
} }

View file

@ -1,138 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.database.breakpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.locks.ReadWriteLock;
import db.DBHandle;
import ghidra.program.model.address.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace;
import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery;
import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry;
import ghidra.trace.database.space.DBTraceSpaceBased;
import ghidra.trace.database.thread.DBTraceThread;
import ghidra.trace.database.thread.DBTraceThreadManager;
import ghidra.trace.model.ImmutableTraceAddressSnapRange;
import ghidra.trace.model.Lifespan;
import ghidra.trace.model.breakpoint.TraceBreakpoint;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceChangeRecord;
import ghidra.trace.util.TraceEvents;
import ghidra.util.LockHold;
import ghidra.util.database.DBCachedObjectIndex;
import ghidra.util.database.DBCachedObjectStoreFactory;
import ghidra.util.exception.VersionException;
public class DBTraceBreakpointSpace implements DBTraceSpaceBased {
protected final DBTraceBreakpointManager manager;
protected final DBHandle dbh;
protected final AddressSpace space;
protected final ReadWriteLock lock;
protected final DBTrace trace;
protected final DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint> breakpointMapSpace;
protected final DBCachedObjectIndex<String, DBTraceBreakpoint> breakpointsByPath;
protected final Collection<TraceBreakpoint> breakpointView;
public DBTraceBreakpointSpace(DBTraceBreakpointManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
this.manager = manager;
this.dbh = dbh;
this.space = space;
this.lock = manager.getLock();
this.trace = manager.getTrace();
DBCachedObjectStoreFactory factory = trace.getStoreFactory();
long threadKey = ent.getThreadKey();
assert threadKey == -1; // No breakpoints on registers
breakpointMapSpace =
new DBTraceAddressSnapRangePropertyMapSpace<DBTraceBreakpoint, DBTraceBreakpoint>(
DBTraceBreakpoint.tableName(space, threadKey), factory, lock, space, null, 0,
DBTraceBreakpoint.class, (t, s, r) -> new DBTraceBreakpoint(this, t, s, r));
breakpointsByPath =
breakpointMapSpace.getUserIndex(String.class, DBTraceBreakpoint.PATH_COLUMN);
breakpointView = Collections.unmodifiableCollection(breakpointMapSpace.values());
}
@Override
public AddressSpace getAddressSpace() {
return space;
}
@Override
public DBTraceThread getThread() {
return null;
}
@Override
public int getFrameLevel() {
return 0;
}
protected DBTraceBreakpoint addBreakpoint(String path, Lifespan lifespan, AddressRange range,
Collection<TraceThread> threads, Collection<TraceBreakpointKind> kinds, boolean enabled,
String comment) {
// NOTE: thread here is not about address/register spaces.
// It's about which thread to trap
try (LockHold hold = LockHold.lock(lock.writeLock())) {
DBTraceThreadManager threadManager = trace.getThreadManager();
for (TraceThread t : threads) {
threadManager.assertIsMine(t);
}
DBTraceBreakpoint breakpoint =
breakpointMapSpace.put(new ImmutableTraceAddressSnapRange(range, lifespan), null);
breakpoint.set(path, path, threads, kinds, enabled, true, comment);
trace.setChanged(
new TraceChangeRecord<>(TraceEvents.BREAKPOINT_ADDED, this, breakpoint));
return breakpoint;
}
}
public Collection<? extends DBTraceBreakpoint> getAllBreakpoints() {
return breakpointMapSpace.values();
}
public Collection<? extends DBTraceBreakpoint> getBreakpointsByPath(String name) {
return Collections.unmodifiableCollection(breakpointsByPath.get(name));
}
public Collection<? extends DBTraceBreakpoint> getBreakpointsAt(long snap, Address address) {
return Collections.unmodifiableCollection(
breakpointMapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).values());
}
public Collection<? extends DBTraceBreakpoint> getBreakpointsIntersecting(Lifespan span,
AddressRange range) {
return Collections.unmodifiableCollection(breakpointMapSpace.reduce(
TraceAddressSnapRangeQuery.intersecting(range, span)).orderedValues());
}
public void deleteBreakpoint(DBTraceBreakpoint breakpoint) {
breakpointMapSpace.deleteData(breakpoint);
trace.setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_DELETED, this, breakpoint));
}
@Override
public void invalidateCache() {
breakpointMapSpace.invalidateCache();
}
}

View file

@ -18,8 +18,7 @@ package ghidra.trace.database.breakpoint;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.AddressRange;
import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObject;
import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.database.target.DBTraceObjectInterface;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
@ -28,17 +27,15 @@ import ghidra.trace.model.breakpoint.*;
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
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.TraceObjectInterface; import ghidra.trace.model.target.iface.TraceTogglable;
import ghidra.trace.model.target.iface.TraceObjectTogglable;
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.target.schema.TraceObjectSchema;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord;
import ghidra.trace.util.*; import ghidra.trace.util.TraceEvents;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.Msg; import ghidra.util.Msg;
public class DBTraceObjectBreakpointSpec public class DBTraceBreakpointSpec implements TraceBreakpointSpec, DBTraceObjectInterface {
implements TraceObjectBreakpointSpec, DBTraceObjectInterface {
private static final Map<TraceObjectSchema, Set<String>> KEYS_BY_SCHEMA = new WeakHashMap<>(); private static final Map<TraceObjectSchema, Set<String>> KEYS_BY_SCHEMA = new WeakHashMap<>();
private final DBTraceObject object; private final DBTraceObject object;
@ -46,13 +43,13 @@ public class DBTraceObjectBreakpointSpec
private TraceBreakpointKindSet kinds = TraceBreakpointKindSet.of(); private TraceBreakpointKindSet kinds = TraceBreakpointKindSet.of();
public DBTraceObjectBreakpointSpec(DBTraceObject object) { public DBTraceBreakpointSpec(DBTraceObject object) {
this.object = object; this.object = object;
TraceObjectSchema schema = object.getSchema(); TraceObjectSchema schema = object.getSchema();
synchronized (KEYS_BY_SCHEMA) { synchronized (KEYS_BY_SCHEMA) {
keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, keys = KEYS_BY_SCHEMA.computeIfAbsent(schema,
s -> Set.of(schema.checkAliasedAttribute(TraceObjectBreakpointSpec.KEY_KINDS), s -> Set.of(schema.checkAliasedAttribute(KEY_KINDS),
schema.checkAliasedAttribute(TraceObjectTogglable.KEY_ENABLED))); schema.checkAliasedAttribute(TraceTogglable.KEY_ENABLED)));
} }
} }
@ -66,51 +63,35 @@ public class DBTraceObjectBreakpointSpec
return object.getCanonicalPath().toString(); return object.getCanonicalPath().toString();
} }
@Override
public void setName(Lifespan lifespan, String name) {
object.setValue(lifespan, KEY_DISPLAY, name);
}
@Override @Override
public void setName(long snap, String name) { public void setName(long snap, String name) {
try (LockHold hold = object.getTrace().lockWrite()) { setName(Lifespan.nowOn(snap), name);
object.setValue(Lifespan.nowOn(snap), TraceObjectInterface.KEY_DISPLAY, name);
}
} }
@Override @Override
public String getName(long snap) { public String getName(long snap) {
return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectInterface.KEY_DISPLAY, return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, "");
String.class, "");
} }
@Override @Override
public AddressRange getRange(long snap) { public void setEnabled(Lifespan lifespan, boolean enabled) {
throw new UnsupportedOperationException("Ask a location instead"); object.setValue(lifespan, TraceTogglable.KEY_ENABLED, enabled ? true : null);
}
@Override
public Address getMinAddress(long snap) {
throw new UnsupportedOperationException("Ask a location instead");
}
@Override
public Address getMaxAddress(long snap) {
throw new UnsupportedOperationException("Ask a location instead");
}
@Override
public long getLength(long snap) {
throw new UnsupportedOperationException("Ask a location instead");
} }
@Override @Override
public void setEnabled(long snap, boolean enabled) { public void setEnabled(long snap, boolean enabled) {
try (LockHold hold = object.getTrace().lockWrite()) { setEnabled(Lifespan.nowOn(snap), enabled);
object.setValue(Lifespan.nowOn(snap), TraceObjectTogglable.KEY_ENABLED,
enabled ? true : null);
}
} }
@Override @Override
public boolean isEnabled(long snap) { public boolean isEnabled(long snap) {
return TraceObjectInterfaceUtils.getValue(object, snap, return TraceObjectInterfaceUtils.getValue(object, snap,
TraceObjectTogglable.KEY_ENABLED, Boolean.class, false); TraceTogglable.KEY_ENABLED, Boolean.class, false);
} }
@Override @Override
@ -118,8 +99,7 @@ public class DBTraceObjectBreakpointSpec
// TODO: More efficient encoding // TODO: More efficient encoding
// TODO: Target-Trace mapping is implied by encoded name. Seems bad. // TODO: Target-Trace mapping is implied by encoded name. Seems bad.
try (LockHold hold = object.getTrace().lockWrite()) { try (LockHold hold = object.getTrace().lockWrite()) {
object.setValue(lifespan, TraceObjectBreakpointSpec.KEY_KINDS, object.setValue(lifespan, KEY_KINDS, TraceBreakpointKindSet.encode(kinds));
TraceBreakpointKindSet.encode(kinds));
this.kinds = TraceBreakpointKindSet.copyOf(kinds); this.kinds = TraceBreakpointKindSet.copyOf(kinds);
} }
} }
@ -133,8 +113,8 @@ public class DBTraceObjectBreakpointSpec
@Override @Override
public Set<TraceBreakpointKind> getKinds(long snap) { public Set<TraceBreakpointKind> getKinds(long snap) {
String kindsStr = TraceObjectInterfaceUtils.getValue(object, snap, String kindsStr =
TraceObjectBreakpointSpec.KEY_KINDS, String.class, null); TraceObjectInterfaceUtils.getValue(object, snap, KEY_KINDS, String.class, null);
if (kindsStr == null) { if (kindsStr == null) {
return kinds; return kinds;
} }
@ -149,43 +129,24 @@ public class DBTraceObjectBreakpointSpec
@Override @Override
public String getExpression(long snap) { public String getExpression(long snap) {
return TraceObjectInterfaceUtils.getValue(object, snap, return TraceObjectInterfaceUtils.getValue(object, snap, KEY_EXPRESSION, String.class, null);
TraceObjectBreakpointSpec.KEY_EXPRESSION, String.class, null);
} }
@Override @Override
public Set<TraceThread> getThreads(long snap) { public void setComment(Lifespan lifespan, String comment) {
throw new UnsupportedOperationException("Ask a location instead"); object.setValue(lifespan, KEY_COMMENT, comment);
} }
@Override @Override
public void setComment(long snap, String comment) { public void setComment(long snap, String comment) {
throw new UnsupportedOperationException("Set on a location instead"); setComment(Lifespan.nowOn(snap), comment);
} }
@Override @Override
public String getComment(long snap) { public String getComment(long snap) {
throw new UnsupportedOperationException("Ask a location instead"); try (LockHold hold = object.getTrace().lockRead()) {
} return TraceObjectInterfaceUtils.getValue(object, snap, KEY_COMMENT, String.class, "");
}
@Override
public void setEmuEnabled(long snap, boolean enabled) {
throw new UnsupportedOperationException("Set on a location instead");
}
@Override
public boolean isEmuEnabled(long snap) {
throw new UnsupportedOperationException("Ask a location instead");
}
@Override
public void setEmuSleigh(long snap, String sleigh) {
throw new UnsupportedOperationException("Set on a location instead");
}
@Override
public String getEmuSleigh(long snap) {
throw new UnsupportedOperationException("Ask a location instead");
} }
@Override @Override
@ -217,15 +178,15 @@ public class DBTraceObjectBreakpointSpec
return object; return object;
} }
protected Collection<? extends TraceObjectBreakpointLocation> getLocations(Lifespan span) { protected Collection<? extends TraceBreakpointLocation> getLocations(Lifespan span) {
try (LockHold hold = object.getTrace().lockRead()) { try (LockHold hold = object.getTrace().lockRead()) {
return object.querySuccessorsInterface(span, TraceObjectBreakpointLocation.class, true) return object.querySuccessorsInterface(span, TraceBreakpointLocation.class, true)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
} }
@Override @Override
public Collection<? extends TraceObjectBreakpointLocation> getLocations(long snap) { public Collection<? extends TraceBreakpointLocation> getLocations(long snap) {
return getLocations(Lifespan.at(snap)); return getLocations(Lifespan.at(snap));
} }
@ -243,9 +204,9 @@ public class DBTraceObjectBreakpointSpec
if (object.getCanonicalParent(affected.getMaxSnap()) == null) { if (object.getCanonicalParent(affected.getMaxSnap()) == null) {
return null; // Incomplete object return null; // Incomplete object
} }
for (TraceObjectBreakpointLocation loc : getLocations(affected.getLifespan())) { for (TraceBreakpointLocation loc : getLocations(affected.getLifespan())) {
DBTraceObjectBreakpointLocation dbLoc = (DBTraceObjectBreakpointLocation) loc; DBTraceBreakpointLocation dbLoc = (DBTraceBreakpointLocation) loc;
TraceAddressSpace space = dbLoc.getTraceAddressSpace(affected.getMinSnap()); AddressSpace space = dbLoc.getAddressSpace(affected.getMinSnap());
TraceChangeRecord<?, ?> evt = TraceChangeRecord<?, ?> evt =
new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, loc, null, null); new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, loc, null, null);
object.getTrace().setChanged(evt); object.getTrace().setChanged(evt);

View file

@ -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.
@ -101,14 +101,7 @@ public class DBTraceRegisterContextManager
@Override @Override
protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceRegisterContextSpace(this, dbh, space, ent, null); return new DBTraceRegisterContextSpace(this, dbh, space, ent);
}
@Override
protected DBTraceRegisterContextSpace createRegisterSpace(AddressSpace space,
TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException {
// TODO: Should I just forbid this? It doesn't seem sane. Then again, what do I know?
return new DBTraceRegisterContextSpace(this, dbh, space, ent, thread);
} }
@Override @Override
@ -205,7 +198,7 @@ public class DBTraceRegisterContextManager
@Override @Override
public AddressSetView getRegisterValueAddressRanges(Language language, Register register, public AddressSetView getRegisterValueAddressRanges(Language language, Register register,
long snap) { long snap) {
return delegateAddressSet(getActiveMemorySpaces(), return delegateAddressSet(getActiveSpaces(),
m -> m.getRegisterValueAddressRanges(language, register, snap)); m -> m.getRegisterValueAddressRanges(language, register, snap));
} }
@ -218,8 +211,7 @@ public class DBTraceRegisterContextManager
@Override @Override
public boolean hasRegisterValue(Language language, Register register, long snap) { public boolean hasRegisterValue(Language language, Register register, long snap) {
return delegateAny(getActiveMemorySpaces(), return delegateAny(getActiveSpaces(), m -> m.hasRegisterValue(language, register, snap));
m -> m.hasRegisterValue(language, register, snap));
} }
@Override @Override

View file

@ -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.
@ -39,7 +39,6 @@ import ghidra.trace.database.space.DBTraceSpaceBased;
import ghidra.trace.model.*; import ghidra.trace.model.*;
import ghidra.trace.model.context.TraceRegisterContextSpace; import ghidra.trace.model.context.TraceRegisterContextSpace;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.LockHold; import ghidra.util.LockHold;
import ghidra.util.database.*; import ghidra.util.database.*;
import ghidra.util.database.annot.*; import ghidra.util.database.annot.*;
@ -79,8 +78,6 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
protected final DBTraceRegisterContextManager manager; protected final DBTraceRegisterContextManager manager;
protected final DBHandle dbh; protected final DBHandle dbh;
protected final AddressSpace space; protected final AddressSpace space;
protected final TraceThread thread;
protected final int frameLevel;
protected final ReadWriteLock lock; protected final ReadWriteLock lock;
protected final Language baseLanguage; protected final Language baseLanguage;
protected final DBTrace trace; protected final DBTrace trace;
@ -91,13 +88,10 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
new HashMap<>(); new HashMap<>();
public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh, public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh,
AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread) AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException {
throws VersionException, IOException {
this.manager = manager; this.manager = manager;
this.dbh = dbh; this.dbh = dbh;
this.space = space; this.space = space;
this.thread = thread;
this.frameLevel = ent.getFrameLevel();
this.lock = manager.getLock(); this.lock = manager.getLock();
this.baseLanguage = manager.getBaseLanguage(); this.baseLanguage = manager.getBaseLanguage();
this.trace = manager.getTrace(); this.trace = manager.getTrace();
@ -105,8 +99,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
DBCachedObjectStoreFactory factory = trace.getStoreFactory(); DBCachedObjectStoreFactory factory = trace.getStoreFactory();
registerStore = factory.getOrCreateCachedStore( registerStore = factory.getOrCreateCachedStore(DBTraceUtils.tableName(TABLE_NAME, space),
DBTraceUtils.tableName(TABLE_NAME, space, ent.getThreadKey(), ent.getFrameLevel()),
DBTraceRegisterEntry.class, DBTraceRegisterEntry::new, true); DBTraceRegisterEntry.class, DBTraceRegisterEntry::new, true);
loadRegisterValueMaps(); loadRegisterValueMaps();
@ -125,28 +118,18 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
} }
} }
@Override
public DBTrace getTrace() {
return trace;
}
@Override @Override
public AddressSpace getAddressSpace() { public AddressSpace getAddressSpace() {
return space; return space;
} }
@Override
public TraceThread getThread() {
return thread;
}
protected long getThreadKey() {
TraceThread thread = getThread();
return thread == null ? -1 : thread.getKey();
}
@Override
public int getFrameLevel() {
return frameLevel;
}
protected String tableName(Language language, Register register) { protected String tableName(Language language, Register register) {
return DBTraceUtils.tableName(TABLE_NAME, space, getThreadKey(), getFrameLevel()) + "_" + return DBTraceUtils.tableName(TABLE_NAME, space) + "_" +
language.getLanguageID().getIdAsString() + "_" + register.getName(); language.getLanguageID().getIdAsString() + "_" + register.getName();
} }
@ -154,9 +137,9 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D
Pair<Language, Register> lr) throws VersionException { Pair<Language, Register> lr) throws VersionException {
String name = tableName(lr.getLeft(), lr.getRight()); String name = tableName(lr.getLeft(), lr.getRight());
try { try {
return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(), return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace,
lock, space, thread, frameLevel, DBTraceRegisterContextEntry.class, trace.getStoreFactory(), lock, space,
DBTraceRegisterContextEntry::new); DBTraceRegisterContextEntry.class, DBTraceRegisterContextEntry::new);
} }
catch (IOException e) { catch (IOException e) {
manager.dbError(e); manager.dbError(e);

View file

@ -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.
@ -158,12 +158,12 @@ public class DBTraceDataSettingsAdapter
public class DBTraceDataSettingsSpace extends public class DBTraceDataSettingsSpace extends
DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry> DBTraceAddressSnapRangePropertyMapSpace<DBTraceSettingsEntry, DBTraceSettingsEntry>
implements DBTraceDataSettingsOperations { implements DBTraceDataSettingsOperations {
public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory, public DBTraceDataSettingsSpace(String tableName, DBTrace trace,
ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel, DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space,
Class<DBTraceSettingsEntry> dataType, Class<DBTraceSettingsEntry> dataType,
DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory) DBTraceAddressSnapRangePropertyMapDataFactory<DBTraceSettingsEntry, DBTraceSettingsEntry> dataFactory)
throws VersionException, IOException { throws VersionException, IOException {
super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory); super(tableName, trace, storeFactory, lock, space, dataType, dataFactory);
} }
@Override @Override
@ -187,17 +187,8 @@ public class DBTraceDataSettingsAdapter
@Override @Override
protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent)
throws VersionException, IOException { throws VersionException, IOException {
return new DBTraceDataSettingsSpace( return new DBTraceDataSettingsSpace(tableName(space), trace, trace.getStoreFactory(), lock,
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), space, dataType, dataFactory);
lock, space, null, 0, dataType, dataFactory);
}
@Override
protected DBTraceDataSettingsSpace createRegisterSpace(AddressSpace space, TraceThread thread,
DBTraceSpaceEntry ent) throws VersionException, IOException {
return new DBTraceDataSettingsSpace(
tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(),
lock, space, thread, ent.getFrameLevel(), dataType, dataFactory);
} }
@Override @Override

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