diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerLogicalBreakpointService.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerLogicalBreakpointService.java index b9a98ab9a2..98c0bf58a3 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerLogicalBreakpointService.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/app/services/DebuggerLogicalBreakpointService.java @@ -4,9 +4,9 @@ * 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. @@ -21,16 +21,16 @@ import java.util.function.BiFunction; import java.util.function.Supplier; import ghidra.debug.api.breakpoint.LogicalBreakpoint; -import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener; import ghidra.debug.api.breakpoint.LogicalBreakpoint.State; +import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener; import ghidra.framework.plugintool.ServiceInfo; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; import ghidra.program.util.CodeUnitLocation; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.program.TraceProgramView; @ServiceInfo( @@ -99,10 +99,10 @@ public interface DebuggerLogicalBreakpointService { * If the given trace breakpoint is not part of any logical breakpoint, e.g., because the trace * is not opened in the tool or events are still being processed, then null is returned. * - * @param bpt the trace breakpoint + * @param loc the trace breakpoint location * @return the logical breakpoint, or null */ - LogicalBreakpoint getBreakpoint(TraceBreakpoint bpt); + LogicalBreakpoint getBreakpoint(TraceBreakpointLocation loc); /** * Get the collected logical breakpoints (at present) at the given location. @@ -297,10 +297,10 @@ public interface DebuggerLogicalBreakpointService { * *

* If the given location refers to a static image, this behaves as in - * {@link #placeBreakpointAt(Program, Address, TraceBreakpointKind)}. If it refers to a trace - * view, this behaves as in {@link #placeBreakpointAt(Trace, Address, TraceBreakpointKind)}, - * ignoring the view's current snapshot in favor of the present. The name is only saved for a - * program breakpoint. + * {@link #placeBreakpointAt(Program, Address, long, Collection, String)}. If it refers to a + * trace view, this behaves as in * + * {@link #placeBreakpointAt(Trace, Address, long, Collection, String)}, ignoring the view's + * current snapshot in favor of the present. The name is only saved for a program breakpoint. * * @param loc the location * @param length size of the breakpoint, may be ignored by debugger @@ -348,7 +348,7 @@ public interface DebuggerLogicalBreakpointService { /** * Disable a collection of logical breakpoints on target, if applicable * - * @see #enableAll(Collection) + * @see #enableAll(Collection, Trace) * @param col the collection * @param trace a trace, if the command should be limited to the given trace * @return a future which completes when all associated specifications have been disabled @@ -358,7 +358,7 @@ public interface DebuggerLogicalBreakpointService { /** * Delete, if possible, a collection of logical breakpoints on target, if applicable * - * @see #enableAll(Collection) + * @see #enableAll(Collection, Trace) * @param col the collection * @param trace a trace, if the command should be limited to the given trace * @return a future which completes when all associated specifications have been deleted @@ -371,7 +371,7 @@ public interface DebuggerLogicalBreakpointService { * @param col the trace breakpoints * @return a future which completes when the command has been processed */ - CompletableFuture enableLocs(Collection col); + CompletableFuture enableLocs(Collection col); /** * Disable the given locations @@ -379,7 +379,7 @@ public interface DebuggerLogicalBreakpointService { * @param col the trace breakpoints * @return a future which completes when the command has been processed */ - CompletableFuture disableLocs(Collection col); + CompletableFuture disableLocs(Collection col); /** * Delete the given locations @@ -387,7 +387,7 @@ public interface DebuggerLogicalBreakpointService { * @param col the trace breakpoints * @return a future which completes when the command has been processed */ - CompletableFuture deleteLocs(Collection col); + CompletableFuture deleteLocs(Collection col); /** * Generate an informational message when toggling the breakpoints @@ -397,7 +397,8 @@ public interface DebuggerLogicalBreakpointService { * is for toggling breakpoints. If the breakpoint set is empty, this should return null, since * the usual behavior in that case is to prompt to place a new breakpoint. * - * @see #generateStatusEnable(Collection, Trace)) + * @see #generateStatusEnable(Collection, Trace) + * @param bs the set of logical breakpoints * @param loc a representative location * @return the status message, or null */ @@ -407,12 +408,12 @@ public interface DebuggerLogicalBreakpointService { * Generate an informational message when toggling the breakpoints at the given location * *

- * This works in the same manner as {@link #generateStatusEnable(Collection, Trace))}, except it + * This works in the same manner as {@link #generateStatusEnable(Collection, Trace)}, except it * is for toggling breakpoints at a given location. If there are no breakpoints at the location, * this should return null, since the usual behavior in that case is to prompt to place a new * breakpoint. * - * @see #generateStatusEnable(Collection) + * @see #generateStatusEnable(Collection, Trace) * @param loc the location * @return the status message, or null */ diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTracker.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTracker.java index beab2ae89f..dc3c1ec656 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTracker.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTracker.java @@ -4,9 +4,9 @@ * 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. @@ -18,11 +18,11 @@ package ghidra.debug.api.action; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.stack.TraceStack; -import ghidra.trace.util.TraceAddressSpace; /** * The actual tracking logic for a location tracking spec @@ -73,8 +73,8 @@ public interface LocationTracker { * @param coordinates the provider's current coordinates * @return true if re-computation and "goto" is warranted */ - boolean affectedByBytesChange(TraceAddressSpace space, - TraceAddressSnapRange range, DebuggerCoordinates coordinates); + boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range, + DebuggerCoordinates coordinates); /** * Check if the address should be recomputed given the indicated stack change diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTrackingSpec.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTrackingSpec.java index 2bf2bbd5c5..680638a4d1 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTrackingSpec.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/action/LocationTrackingSpec.java @@ -4,9 +4,9 @@ * 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. @@ -20,9 +20,8 @@ import javax.swing.Icon; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec; +import ghidra.program.model.address.AddressSpace; import ghidra.trace.model.TraceAddressSnapRange; -import ghidra.trace.model.memory.TraceMemorySpace; -import ghidra.trace.util.TraceAddressSpace; /** * A specification for automatic navigation of the dynamic listing @@ -67,21 +66,13 @@ public interface LocationTrackingSpec { * @param current the current coordinates * @return true if the change affects the tracked address for the given coordinates */ - static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range, + static boolean changeIsCurrent(AddressSpace space, TraceAddressSnapRange range, DebuggerCoordinates current) { if (space == null) { return false; } - if (!space.getAddressSpace().isMemorySpace()) { - if (current.getThread() == null) { - return false; - } - TraceMemorySpace memSpace = current.getTrace() - .getMemoryManager() - .getMemoryRegisterSpace(current.getThread(), current.getFrame(), false); - if (memSpace == null || memSpace.getAddressSpace() != space.getAddressSpace()) { - return false; - } + if (!space.isMemorySpace() && !current.isRegisterSpace(space)) { + return false; } if (!range.getLifespan().contains(current.getSnap())) { return false; diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpoint.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpoint.java index 17f7821399..78dd1da554 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpoint.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpoint.java @@ -28,8 +28,8 @@ import ghidra.program.model.listing.Bookmark; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import resources.MultiIcon; /** @@ -471,6 +471,8 @@ public interface LogicalBreakpoint { */ INCONSISTENT_MIXED(Mode.MIXED, Consistency.INCONSISTENT, NAME_MARKER_INCON_MIX, ICON_MARKER_INCON_MIX); + public static final List VALUES = List.of(values()); + public final Mode mode; public final Consistency consistency; public final String display; @@ -658,7 +660,7 @@ public interface LogicalBreakpoint { * Get the sleigh injection when emulating this breakpoint * * @return the sleigh injection - * @see TraceBreakpoint#getEmuSleigh() + * @see TraceBreakpointLocation#getEmuSleigh(long) */ String getEmuSleigh(); @@ -666,7 +668,7 @@ public interface LogicalBreakpoint { * Set the sleigh injection when emulating this breakpoint * * @param sleigh the sleigh injection - * @see TraceBreakpoint#setEmuSleigh(String) + * @see TraceBreakpointLocation#setEmuSleigh(long,String) */ void setEmuSleigh(String sleigh); @@ -699,7 +701,7 @@ public interface LogicalBreakpoint { * * @return the set of trace breakpoints */ - Set getTraceBreakpoints(); + Set getTraceBreakpoints(); /** * Get all trace breakpoints for the given trace which map to this logical breakpoint. @@ -707,15 +709,15 @@ public interface LogicalBreakpoint { * @param trace the trace * @return the set of trace breakpoints */ - Set getTraceBreakpoints(Trace trace); + Set getTraceBreakpoints(Trace trace); /** * Get the traces for which this logical breakpoint has an address. * *

- * Note, this does not necessarily indicate that a {@link TraceBreakpoint} is present for each - * trace, but rather that for each returned trace, the logical breakpoint can be mapped to an - * address in that trace. See {@link #getParticipatingTraces()}. + * Note, this does not necessarily indicate that a {@link TraceBreakpointLocation} is present + * for each trace, but rather that for each returned trace, the logical breakpoint can be mapped + * to an address in that trace. See {@link #getParticipatingTraces()}. * * @return a copy of the set of traces */ @@ -725,8 +727,8 @@ public interface LogicalBreakpoint { * Get the traces for which this logical breakpoint has a trace breakpoint. * *

- * Note, unlike {@link #getMappedTraces()}, this does indicate that a {@link TraceBreakpoint} is - * present for each trace. + * Note, unlike {@link #getMappedTraces()}, this does indicate that a + * {@link TraceBreakpointLocation} is present for each trace. * * @return the set of traces */ @@ -779,7 +781,7 @@ public interface LogicalBreakpoint { * @param loc the location * @return the state */ - State computeStateForLocation(TraceBreakpoint loc); + State computeStateForLocation(TraceBreakpointLocation loc); /** * Compute the state for all involved traces and program. diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpointsChangeListener.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpointsChangeListener.java index 592423942f..cb42ddf05c 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpointsChangeListener.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/breakpoint/LogicalBreakpointsChangeListener.java @@ -17,7 +17,7 @@ package ghidra.debug.api.breakpoint; import java.util.Collection; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; public interface LogicalBreakpointsChangeListener { default void breakpointAdded(LogicalBreakpoint added) { @@ -47,12 +47,12 @@ public interface LogicalBreakpointsChangeListener { } } - default void locationAdded(TraceBreakpoint added) { + default void locationAdded(TraceBreakpointLocation added) { } - default void locationUpdated(TraceBreakpoint updated) { + default void locationUpdated(TraceBreakpointLocation updated) { } - default void locationRemoved(TraceBreakpoint removed) { + default void locationRemoved(TraceBreakpointLocation removed) { } } diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/target/Target.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/target/Target.java index 4064db3b44..56bc5da823 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/target/Target.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/target/Target.java @@ -29,8 +29,7 @@ import ghidra.program.model.lang.Register; import ghidra.program.model.lang.RegisterValue; import ghidra.trace.model.Trace; import ghidra.trace.model.TraceExecutionState; -import ghidra.trace.model.breakpoint.TraceBreakpoint; -import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.stack.TraceStackFrame; @@ -617,12 +616,12 @@ public interface Target { * @param breakpoint the breakpoint * @return true if valid */ - boolean isBreakpointValid(TraceBreakpoint breakpoint); + boolean isBreakpointValid(TraceBreakpointLocation breakpoint); /** - * @see #deleteBreakpoint(TraceBreakpoint) + * @see #deleteBreakpoint(TraceBreakpointCommon) */ - CompletableFuture deleteBreakpointAsync(TraceBreakpoint breakpoint); + CompletableFuture deleteBreakpointAsync(TraceBreakpointCommon breakpoint); /** * Delete the given breakpoint from the target @@ -633,12 +632,13 @@ public interface Target { * * @param breakpoint the breakpoint to delete */ - void deleteBreakpoint(TraceBreakpoint breakpoint); + void deleteBreakpoint(TraceBreakpointCommon breakpoint); /** - * @see #toggleBreakpoint(TraceBreakpoint, boolean) + * @see #toggleBreakpoint(TraceBreakpointLocation, boolean) */ - CompletableFuture toggleBreakpointAsync(TraceBreakpoint breakpoint, boolean enabled); + CompletableFuture toggleBreakpointAsync(TraceBreakpointCommon breakpoint, + boolean enabled); /** * Toggle the given breakpoint on the target @@ -651,7 +651,7 @@ public interface Target { * @param breakpoint the breakpoint to toggle * @param enabled true to enable, false to disable */ - void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled); + void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled); /** * @see #forceTerminate() diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracemgr/DebuggerCoordinates.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracemgr/DebuggerCoordinates.java index 0224f2de34..7f51b76abd 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracemgr/DebuggerCoordinates.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracemgr/DebuggerCoordinates.java @@ -27,15 +27,16 @@ import ghidra.framework.model.*; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.store.LockException; +import ghidra.program.model.address.AddressSpace; import ghidra.trace.database.DBTraceContentHandler; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.program.TraceProgramView; -import ghidra.trace.model.stack.*; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.schedule.TraceSchedule; @@ -315,36 +316,34 @@ public class DebuggerCoordinates { return thread(trace.getThreadManager().getThread(thread.getKey())); } - private static KeyPath resolvePath(TraceThread thread, Integer frameLevel, - TraceSchedule time) { - if (thread instanceof TraceObjectThread tot) { - TraceObject objThread = tot.getObject(); - if (frameLevel == null) { - return objThread.getCanonicalPath(); - } - TraceStack stack; - long snap = time.getSnap(); - try { - stack = thread.getTrace().getStackManager().getStack(thread, snap, false); - } - catch (IllegalStateException e) { - // Schema does not specify a stack - return objThread.getCanonicalPath(); - } - if (stack == null) { - return objThread.getCanonicalPath(); - } - TraceStackFrame frame = stack.getFrame(snap, frameLevel, false); - if (frame == null) { - return objThread.getCanonicalPath(); - } - return ((TraceObjectStackFrame) frame).getObject().getCanonicalPath(); + private static KeyPath resolvePath(TraceThread thread, Integer frameLevel, TraceSchedule time) { + if (thread == null) { + return KeyPath.of(); } - return null; + TraceObject objThread = thread.getObject(); + if (frameLevel == null) { + return objThread.getCanonicalPath(); + } + TraceStack stack; + long snap = time.getSnap(); + try { + stack = thread.getTrace().getStackManager().getStack(thread, snap, false); + } + catch (IllegalStateException e) { + // Schema does not specify a stack + return objThread.getCanonicalPath(); + } + if (stack == null) { + return objThread.getCanonicalPath(); + } + TraceStackFrame frame = stack.getFrame(snap, frameLevel, false); + if (frame == null) { + return objThread.getCanonicalPath(); + } + return frame.getObject().getCanonicalPath(); } - private static KeyPath choose(KeyPath curPath, - KeyPath newPath) { + private static KeyPath choose(KeyPath curPath, KeyPath newPath) { if (curPath == null) { return newPath; } @@ -525,9 +524,7 @@ public class DebuggerCoordinates { if (object == null) { return null; } - return object.queryCanonicalAncestorsInterface(TraceObjectThread.class) - .findFirst() - .orElse(null); + return object.queryCanonicalAncestorsInterface(TraceThread.class).findFirst().orElse(null); } private static Integer resolveFrame(Trace trace, KeyPath path) { @@ -535,10 +532,9 @@ public class DebuggerCoordinates { if (object == null) { return null; } - TraceObjectStackFrame frame = - object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class) - .findFirst() - .orElse(null); + TraceStackFrame frame = object.queryCanonicalAncestorsInterface(TraceStackFrame.class) + .findFirst() + .orElse(null); return frame == null ? null : frame.getLevel(); } @@ -669,6 +665,11 @@ public class DebuggerCoordinates { return registerContainer = object.findRegisterContainer(getFrame()); } + public boolean isRegisterSpace(AddressSpace space) { + TraceObject container = getRegisterContainer(); + return container != null && container.getCanonicalPath().toString().equals(space.getName()); + } + public synchronized long getViewSnap() { if (viewSnap != null) { return viewSnap; diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java index 06e7c2821f..40b0183c2d 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java @@ -53,7 +53,6 @@ import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.util.MathUtilities; @@ -1452,11 +1451,7 @@ public interface FlatDebuggerAPI { } default ActionContext createContext(TraceThread thread) { - if (thread instanceof TraceObjectThread objThread) { - return createContext(objThread.getObject()); - } - return new DebuggerSingleObjectPathActionContext( - KeyPath.parse(thread.getPath())); + return createContext(thread.getObject()); } default ActionContext createContext(Trace trace) { diff --git a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiConnector.java b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiConnector.java index 7b85272d16..09ef03ace2 100644 --- a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiConnector.java +++ b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiConnector.java @@ -21,7 +21,7 @@ import java.util.Map; import com.sun.jdi.*; import ghidra.app.plugin.core.debug.client.tracermi.*; -import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod; +import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceRmiMethod; import ghidra.dbg.jdi.manager.impl.DebugStatus; import ghidra.dbg.jdi.manager.impl.JdiManagerImpl; import ghidra.program.model.address.*; @@ -144,7 +144,7 @@ public class JdiConnector { } public void registerRemoteMethod(JdiMethods methods, java.lang.reflect.Method m, String name) { - TraceMethod annot = m.getAnnotation(TraceMethod.class); + TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class); if (annot == null) { return; } diff --git a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiMethods.java b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiMethods.java index 1b2a38881c..4801dac5b6 100644 --- a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiMethods.java +++ b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiMethods.java @@ -24,11 +24,11 @@ import com.sun.jdi.*; import com.sun.jdi.request.*; import ghidra.app.plugin.core.debug.client.tracermi.*; -import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod; +import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceRmiMethod; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; import ghidra.rmi.trace.TraceRmi.MemoryState; -import ghidra.trace.model.target.iface.TraceObjectMethod.Param; +import ghidra.trace.model.target.iface.TraceMethod.Param; import ghidra.util.Msg; public class JdiMethods implements RmiMethods { @@ -45,14 +45,14 @@ public class JdiMethods implements RmiMethods { public void registerMethods() { Class cls = this.getClass(); for (java.lang.reflect.Method m : cls.getMethods()) { - TraceMethod annot = m.getAnnotation(TraceMethod.class); + TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class); if (annot != null) { connector.registerRemoteMethod(this, m, m.getName()); } } } - @TraceMethod(action = "refresh", display = "Refresh VM") + @TraceRmiMethod(action = "refresh", display = "Refresh VM") public void refresh_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVM")) { String path = obj.getPath(); @@ -61,7 +61,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh process") + @TraceRmiMethod(action = "refresh", display = "Refresh process") public void refresh_process( @Param(schema = "ProcessRef", name = "process") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshProcess")) { @@ -71,7 +71,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh thread groups") + @TraceRmiMethod(action = "refresh", display = "Refresh thread groups") public void refresh_thread_groups( @Param( schema = "ThreadGroupReferenceContainer", @@ -89,7 +89,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh thread group") + @TraceRmiMethod(action = "refresh", display = "Refresh thread group") public void refresh_thread_group_proxy( @Param(schema = "ThreadGroupReferenceProxy", name = "proxy") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) { @@ -105,7 +105,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh thread group") + @TraceRmiMethod(action = "refresh", display = "Refresh thread group") public void refresh_thread_group( @Param(schema = "ThreadGroupReference", name = "group") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) { @@ -115,7 +115,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh threads") + @TraceRmiMethod(action = "refresh", display = "Refresh threads") public void refresh_threads( @Param(schema = "ThreadContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) { @@ -126,7 +126,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh threads") + @TraceRmiMethod(action = "refresh", display = "Refresh threads") public void refresh_threadrefs( @Param(schema = "ThreadReferenceContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) { @@ -147,7 +147,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh thread") + @TraceRmiMethod(action = "refresh", display = "Refresh thread") public void refresh_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThread")) { String path = obj.getPath(); @@ -156,14 +156,14 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh stack") + @TraceRmiMethod(action = "refresh", display = "Refresh stack") public void refresh_stack(@Param(schema = "Stack", name = "stack") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshStack")) { cmds.ghidraTracePutFrames(); } } - @TraceMethod(action = "refresh", display = "Refresh registers") + @TraceRmiMethod(action = "refresh", display = "Refresh registers") public void refresh_registers( @Param(schema = "RegisterContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshRegisters")) { @@ -171,7 +171,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh modules") + @TraceRmiMethod(action = "refresh", display = "Refresh modules") public void refresh_modules( @Param(schema = "ModuleReferenceContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModules")) { @@ -179,7 +179,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh module") + @TraceRmiMethod(action = "refresh", display = "Refresh module") public void refresh_module( @Param(schema = "ModuleReference", name = "module") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModule")) { @@ -189,7 +189,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh monitor info") + @TraceRmiMethod(action = "refresh", display = "Refresh monitor info") public void refresh_monitors( @Param(schema = "MonitorInfoContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) { @@ -203,7 +203,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh monitor info") + @TraceRmiMethod(action = "refresh", display = "Refresh monitor info") public void refresh_monitor_info( @Param(schema = "MonitorInfo", name = "monitor_info") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) { @@ -213,13 +213,13 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh fields") + @TraceRmiMethod(action = "refresh", display = "Refresh fields") public void refresh_canonical_fields( @Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) { refresh_fields(obj); } - @TraceMethod(action = "refresh", display = "Refresh fields") + @TraceRmiMethod(action = "refresh", display = "Refresh fields") public void refresh_fields( @Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshFields")) { @@ -235,7 +235,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh objects") + @TraceRmiMethod(action = "refresh", display = "Refresh objects") public void refresh_objects( @Param(schema = "ObjectReferenceContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObjects")) { @@ -261,7 +261,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh object") + @TraceRmiMethod(action = "refresh", display = "Refresh object") public void refresh_object_proxy( @Param(schema = "ObjectReferenceProxy", name = "proxy") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObject")) { @@ -283,7 +283,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh object") + @TraceRmiMethod(action = "refresh", display = "Refresh object") public void refresh_object( @Param(schema = "ObjectReference", name = "object") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshInstance")) { @@ -293,13 +293,13 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh methods") + @TraceRmiMethod(action = "refresh", display = "Refresh methods") public void refresh_canonical_methods( @Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) { refresh_methods(obj); } - @TraceMethod(action = "refresh", display = "Refresh methods") + @TraceRmiMethod(action = "refresh", display = "Refresh methods") public void refresh_methods( @Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethods")) { @@ -310,7 +310,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh method") + @TraceRmiMethod(action = "refresh", display = "Refresh method") public void refresh_method(@Param(schema = "Method", name = "method") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethod")) { String path = obj.getPath(); @@ -319,7 +319,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh arguments") + @TraceRmiMethod(action = "refresh", display = "Refresh arguments") public void refresh_arguments( @Param(schema = "ArgumentContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshArguments")) { @@ -330,7 +330,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Load class") + @TraceRmiMethod(display = "Load class") public boolean find_canonical_class( @Param( schema = "CanonicalReferenceTypeContainer", @@ -344,7 +344,7 @@ public class JdiMethods implements RmiMethods { return find_class(obj, targetClass); } - @TraceMethod(display = "Load class") + @TraceRmiMethod(display = "Load class") public boolean find_class( @Param( schema = "ReferenceTypeContainer", @@ -370,12 +370,12 @@ public class JdiMethods implements RmiMethods { * NB. Did not assign action="refresh" because this method is expensive. Assigning that action * name will cause the UI to do it upon expanding the node, which we do not want. */ - @TraceMethod(display = "Refresh memory") + @TraceRmiMethod(display = "Refresh memory") public void refresh_memory(@Param(schema = "Memory", name = "memory") RmiTraceObject obj) { refresh_reference_types(obj); } - @TraceMethod(display = "Refresh reference types") + @TraceRmiMethod(display = "Refresh reference types") public void refresh_canonical_reference_types( @Param( schema = "CanonicalReferenceTypeContainer", @@ -387,7 +387,7 @@ public class JdiMethods implements RmiMethods { * NB. Did not assign action="refresh" because this method is expensive. Assigning that action * name will cause the UI to do it upon expanding the node, which we do not want. */ - @TraceMethod(display = "Refresh reference types") + @TraceRmiMethod(display = "Refresh reference types") public void refresh_reference_types( @Param(schema = "ReferenceTypeContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceTypes")) { @@ -430,7 +430,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh reference type") + @TraceRmiMethod(action = "refresh", display = "Refresh reference type") public void refresh_reference_type_proxy( @Param(schema = "ReferenceTypeProxy", name = "proxy") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) { @@ -452,13 +452,13 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh reference type") + @TraceRmiMethod(action = "refresh", display = "Refresh reference type") public void refresh_canonical_reference_type( @Param(schema = "CanonicalReferenceType", name = "container") RmiTraceObject obj) { refresh_reference_type(obj); } - @TraceMethod(action = "refresh", display = "Refresh reference type") + @TraceRmiMethod(action = "refresh", display = "Refresh reference type") public void refresh_reference_type( @Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) { @@ -468,7 +468,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Load reference type") + @TraceRmiMethod(display = "Load reference type") public void load_reftype( @Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) { @@ -480,13 +480,13 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh variables") + @TraceRmiMethod(action = "refresh", display = "Refresh variables") public void refresh_canonical_variables( @Param(schema = "CanonicalVariableContainer", name = "container") RmiTraceObject obj) { refresh_variables(obj); } - @TraceMethod(action = "refresh", display = "Refresh variables") + @TraceRmiMethod(action = "refresh", display = "Refresh variables") public void refresh_variables( @Param(schema = "VariableContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariables")) { @@ -513,7 +513,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh variable") + @TraceRmiMethod(action = "refresh", display = "Refresh variable") public void refresh_variable( @Param(schema = "Variable", name = "variable") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariable")) { @@ -525,7 +525,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh locations") + @TraceRmiMethod(action = "refresh", display = "Refresh locations") public void refresh_locations( @Param(schema = "LocationContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocations")) { @@ -543,7 +543,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh location") + @TraceRmiMethod(action = "refresh", display = "Refresh location") public void refresh_location( @Param(schema = "Location", name = "location") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) { @@ -553,7 +553,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh breakpoints") + @TraceRmiMethod(action = "refresh", display = "Refresh breakpoints") public void refresh_breakpoints( @Param(schema = "BreakpointContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshBreakpoints")) { @@ -561,7 +561,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh events") + @TraceRmiMethod(action = "refresh", display = "Refresh events") public void refresh_events( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshEvents")) { @@ -569,7 +569,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh values") + @TraceRmiMethod(action = "refresh", display = "Refresh values") public void refresh_values( @Param(schema = "ValueContainer", name = "container") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshValues")) { @@ -582,7 +582,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "refresh", display = "Refresh value") + @TraceRmiMethod(action = "refresh", display = "Refresh value") public void refresh_value(@Param(schema = "Value", name = "value") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) { String path = obj.getPath(); @@ -591,7 +591,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Set value") + @TraceRmiMethod(display = "Set value") public void set_value_lvar( @Param( schema = "Variable", @@ -609,7 +609,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Set value") + @TraceRmiMethod(display = "Set value") public void set_value_field( @Param( schema = "Field", @@ -627,7 +627,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "activate", display = "Activate") + @TraceRmiMethod(action = "activate", display = "Activate") public void activate(@Param(schema = "OBJECT", name = "object") RmiTraceObject obj) { try (RmiTransaction tx = cmds.state.trace.openTx("Activate")) { String path = obj.getPath(); @@ -635,7 +635,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "kill", display = "Terminate") + @TraceRmiMethod(action = "kill", display = "Terminate") public void kill(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath()); vm.exit(143); @@ -647,28 +647,28 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "resume", display = "Resume") + @TraceRmiMethod(action = "resume", display = "Resume") public void resume_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath()); vm.resume(); connector.getHooks().setState(vm); } - @TraceMethod(action = "resume", display = "Resume") + @TraceRmiMethod(action = "resume", display = "Resume") public void resume_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); thread.resume(); connector.getHooks().setState(thread.virtualMachine()); } - @TraceMethod(action = "interrupt", display = "Suspend") + @TraceRmiMethod(action = "interrupt", display = "Suspend") public void suspend_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath()); vm.suspend(); connector.getHooks().setState(vm); } - @TraceMethod(action = "interrupt", display = "Suspend") + @TraceRmiMethod(action = "interrupt", display = "Suspend") public void suspend_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); thread.suspend(); @@ -679,7 +679,7 @@ public class JdiMethods implements RmiMethods { * NB: For the VirtualMachine, the step methods add requests for break-on-step for all threads. * These requests will remain pending until the VM is resumed. */ - @TraceMethod(action = "step_into", display = "Step into") + @TraceRmiMethod(action = "step_into", display = "Step into") public void step_vm_into(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); List threads = getThreadsFromValue(obj); @@ -697,7 +697,7 @@ public class JdiMethods implements RmiMethods { vm.resume(); } - @TraceMethod(action = "step_over", display = "Step over") + @TraceRmiMethod(action = "step_over", display = "Step over") public void step_vm_over(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); List threads = getThreadsFromValue(obj); @@ -715,7 +715,7 @@ public class JdiMethods implements RmiMethods { vm.resume(); } - @TraceMethod(action = "step_out", display = "Step out") + @TraceRmiMethod(action = "step_out", display = "Step out") public void step_vm_out(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); List threads = getThreadsFromValue(obj); @@ -733,7 +733,7 @@ public class JdiMethods implements RmiMethods { vm.resume(); } - @TraceMethod(action = "step_into", display = "Step into") + @TraceRmiMethod(action = "step_into", display = "Step into") public void step_into(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); @@ -744,7 +744,7 @@ public class JdiMethods implements RmiMethods { vm.resume(); } - @TraceMethod(action = "step_over", display = "Step over") + @TraceRmiMethod(action = "step_over", display = "Step over") public void step_over(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); @@ -755,7 +755,7 @@ public class JdiMethods implements RmiMethods { vm.resume(); } - @TraceMethod(action = "step_out", display = "Step out") + @TraceRmiMethod(action = "step_out", display = "Step out") public void step_out(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath()); @@ -766,7 +766,7 @@ public class JdiMethods implements RmiMethods { vm.resume(); } - @TraceMethod(display = "Thread Interrupt") + @TraceRmiMethod(display = "Thread Interrupt") public void thread_interrupt(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { Object object = getObjectFromPath(obj.getPath()); if (object instanceof ThreadReference thread) { @@ -775,7 +775,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "step_ext", display = "Pop stack") + @TraceRmiMethod(action = "step_ext", display = "Pop stack") public void pop_stack(@Param(schema = "StackFrame", name = "frame") RmiTraceObject obj) { StackFrame frame = (StackFrame) getObjectFromPath(obj.getPath()); ThreadReference thread = frame.thread(); @@ -787,7 +787,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Break on execute") + @TraceRmiMethod(display = "Break on execute") public void break_location(@Param(schema = "Location", name = "location") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); Object ctxt = getObjectFromPath(obj.getPath()); @@ -799,7 +799,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Break on access") + @TraceRmiMethod(display = "Break on access") public void break_access(@Param(schema = "Field", name = "field") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); Object ctxt = getObjectFromPath(obj.getPath()); @@ -811,7 +811,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Break on modify") + @TraceRmiMethod(display = "Break on modify") public void break_modify(@Param(schema = "Field", name = "field") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); Object ctxt = getObjectFromPath(obj.getPath()); @@ -823,7 +823,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Break on exception") + @TraceRmiMethod(display = "Break on exception") public void break_exception( @Param( schema = "ReferenceType", @@ -861,13 +861,13 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on thread start") + @TraceRmiMethod(display = "Break on thread start") public void break_started_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_started(obj); } - @TraceMethod(display = "Break on thread start") + @TraceRmiMethod(display = "Break on thread start") public void break_started_thread( @Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_started(obj); @@ -886,18 +886,18 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on thread exit") + @TraceRmiMethod(display = "Break on thread exit") public void break_death_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_death(obj); } - @TraceMethod(display = "Break on thread exit") + @TraceRmiMethod(display = "Break on thread exit") public void break_death_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_death(obj); } - @TraceMethod(display = "Break on VM death") + @TraceRmiMethod(display = "Break on VM death") public void break_vm_death(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); VMDeathRequest brkReq = vm.eventRequestManager() @@ -927,25 +927,25 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on method enter") + @TraceRmiMethod(display = "Break on method enter") public void break_enter_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_enter(obj); } - @TraceMethod(display = "Break on method enter") + @TraceRmiMethod(display = "Break on method enter") public void break_enter_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_enter(obj); } - @TraceMethod(display = "Break on method enter") + @TraceRmiMethod(display = "Break on method enter") public void break_enter_instance( @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { break_enter(obj); } - @TraceMethod(display = "Break on method enter") + @TraceRmiMethod(display = "Break on method enter") public void break_enter_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_enter(obj); } @@ -971,25 +971,25 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on method exit") + @TraceRmiMethod(display = "Break on method exit") public void break_exit_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_exit(obj); } - @TraceMethod(display = "Break on method exit") + @TraceRmiMethod(display = "Break on method exit") public void break_exit_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_exit(obj); } - @TraceMethod(display = "Break on method exit") + @TraceRmiMethod(display = "Break on method exit") public void break_exit_instance( @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { break_exit(obj); } - @TraceMethod(display = "Break on method exit") + @TraceRmiMethod(display = "Break on method exit") public void break_exit_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_exit(obj); } @@ -1007,13 +1007,13 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on class load") + @TraceRmiMethod(display = "Break on class load") public void break_load_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_load(obj); } - @TraceMethod(display = "Break on class load") + @TraceRmiMethod(display = "Break on class load") public void break_load_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_load(obj); @@ -1027,7 +1027,7 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on class unload") + @TraceRmiMethod(display = "Break on class unload") public void break_unload_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_unload(obj); @@ -1054,25 +1054,25 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on monitor contended enter") + @TraceRmiMethod(display = "Break on monitor contended enter") public void break_mon_enter_contention_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_mon_enter_contention(obj); } - @TraceMethod(display = "Break on monitor contended enter") + @TraceRmiMethod(display = "Break on monitor contended enter") public void break_mon_enter_contention_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_mon_enter_contention(obj); } - @TraceMethod(display = "Break on monitor contended enter") + @TraceRmiMethod(display = "Break on monitor contended enter") public void break_mon_enter_contention_instance( @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { break_mon_enter_contention(obj); } - @TraceMethod(display = "Break on monitor contended enter") + @TraceRmiMethod(display = "Break on monitor contended enter") public void break_mon_enter_contention_thread( @Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_mon_enter_contention(obj); @@ -1099,25 +1099,25 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on monitor contented entered") + @TraceRmiMethod(display = "Break on monitor contented entered") public void break_mon_entered_contention_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_mon_entered_contention(obj); } - @TraceMethod(display = "Break on monitor contented entered") + @TraceRmiMethod(display = "Break on monitor contented entered") public void break_mon_entered_contention_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_mon_entered_contention(obj); } - @TraceMethod(display = "Break on monitor contented entered") + @TraceRmiMethod(display = "Break on monitor contented entered") public void break_mon_entered_contention_instance( @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { break_mon_entered_contention(obj); } - @TraceMethod(display = "Break on monitor contented entered") + @TraceRmiMethod(display = "Break on monitor contented entered") public void break_mon_entered_contention_thread( @Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_mon_entered_contention(obj); @@ -1144,25 +1144,25 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on monitor wait") + @TraceRmiMethod(display = "Break on monitor wait") public void break_mon_wait_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_mon_wait(obj); } - @TraceMethod(display = "Break on monitor wait") + @TraceRmiMethod(display = "Break on monitor wait") public void break_mon_wait_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_mon_wait(obj); } - @TraceMethod(display = "Break on monitor wait") + @TraceRmiMethod(display = "Break on monitor wait") public void break_mon_wait_instance( @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { break_mon_wait(obj); } - @TraceMethod(display = "Break on monitor wait") + @TraceRmiMethod(display = "Break on monitor wait") public void break_mon_wait_thread( @Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_mon_wait(obj); @@ -1189,31 +1189,31 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Break on monitor waited") + @TraceRmiMethod(display = "Break on monitor waited") public void break_mon_waited_container( @Param(schema = "EventContainer", name = "container") RmiTraceObject obj) { break_mon_waited(obj); } - @TraceMethod(display = "Break on monitor waited") + @TraceRmiMethod(display = "Break on monitor waited") public void break_mon_waited_reftype( @Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) { break_mon_waited(obj); } - @TraceMethod(display = "Break on monitor waited") + @TraceRmiMethod(display = "Break on monitor waited") public void break_mon_waited_instance( @Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) { break_mon_waited(obj); } - @TraceMethod(display = "Break on monitor waited") + @TraceRmiMethod(display = "Break on monitor waited") public void break_mon_waited_thread( @Param(schema = "Thread", name = "thread") RmiTraceObject obj) { break_mon_waited(obj); } - @TraceMethod(display = "Add count filter") + @TraceRmiMethod(display = "Add count filter") public void add_count_filter( @Param( schema = "Event", @@ -1234,7 +1234,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Set class filter") + @TraceRmiMethod(display = "Set class filter") public void set_class_filter( @Param( schema = "Event", @@ -1349,7 +1349,7 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Set source filter") + @TraceRmiMethod(display = "Set source filter") public void set_source_filter( @Param( schema = "Event", @@ -1370,7 +1370,7 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(display = "Set platform filter") + @TraceRmiMethod(display = "Set platform filter") public void set_platform_filter(@Param(schema = "Event", name = "event") RmiTraceObject obj) { Object ctxt = getObjectFromPath(obj.getPath()); if (ctxt instanceof ThreadStartRequest req) { @@ -1388,7 +1388,7 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(action = "toggle", display = "Toggle breakpoint") + @TraceRmiMethod(action = "toggle", display = "Toggle breakpoint") public void toggle_breakpoint( @Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); @@ -1409,7 +1409,7 @@ public class JdiMethods implements RmiMethods { cmds.putBreakpoints(); } - @TraceMethod(action = "delete", display = "Delete breakpoint") + @TraceRmiMethod(action = "delete", display = "Delete breakpoint") public void delete_breakpoint( @Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); @@ -1420,7 +1420,7 @@ public class JdiMethods implements RmiMethods { cmds.putBreakpoints(); } - @TraceMethod(action = "toggle", display = "Toggle event") + @TraceRmiMethod(action = "toggle", display = "Toggle event") public void toggle_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) { Object ctxt = getObjectFromPath(obj.getPath()); if (ctxt instanceof EventRequest req) { @@ -1434,7 +1434,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "delete", display = "Delete Event") + @TraceRmiMethod(action = "delete", display = "Delete Event") public void delete_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) { VirtualMachine vm = connector.getJdi().getCurrentVM(); Object ctxt = getObjectFromPath(obj.getPath()); @@ -1444,13 +1444,13 @@ public class JdiMethods implements RmiMethods { cmds.putEvents(); } - @TraceMethod(action = "toggle", display = "Toggle scope") + @TraceRmiMethod(action = "toggle", display = "Toggle scope") public void toggle_scope_canonical_methods( @Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) { toggle_scope_methods(obj); } - @TraceMethod(action = "toggle", display = "Toggle scope") + @TraceRmiMethod(action = "toggle", display = "Toggle scope") public void toggle_scope_methods( @Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) { String ppath = cmds.getParentPath(obj.getPath()); @@ -1459,13 +1459,13 @@ public class JdiMethods implements RmiMethods { refresh_methods(obj); } - @TraceMethod(action = "toggle", display = "Toggle scope") + @TraceRmiMethod(action = "toggle", display = "Toggle scope") public void toggle_scope_canonical_fields( @Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) { toggle_scope_fields(obj); } - @TraceMethod(action = "toggle", display = "Toggle scope") + @TraceRmiMethod(action = "toggle", display = "Toggle scope") public void toggle_scope_fields( @Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) { String ppath = cmds.getParentPath(obj.getPath()); @@ -1479,7 +1479,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(action = "read_mem", display = "Read Memory") + @TraceRmiMethod(action = "read_mem", display = "Read Memory") public long read_mem( @Param( schema = "VirtualMachine", @@ -1503,7 +1503,7 @@ public class JdiMethods implements RmiMethods { return range.getLength(); } - @TraceMethod(display = "Invoke method (no args)") + @TraceRmiMethod(display = "Invoke method (no args)") public void execute_on_instance( @Param( schema = "ObjectReference", @@ -1531,7 +1531,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Invoke static method (no args)") + @TraceRmiMethod(display = "Invoke static method (no args)") public void execute_on_class( @Param( schema = "ReferenceType", @@ -1565,7 +1565,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Invoke method (no args)") + @TraceRmiMethod(display = "Invoke method (no args)") public void execute_method( @Param( schema = "Method", @@ -1596,7 +1596,7 @@ public class JdiMethods implements RmiMethods { } } - @TraceMethod(display = "Invoke static method (no args)") + @TraceRmiMethod(display = "Invoke static method (no args)") public void execute_static_method( @Param( schema = "Method", diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiMethodRegistry.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiMethodRegistry.java index a929e0b578..28433f5758 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiMethodRegistry.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiMethodRegistry.java @@ -26,7 +26,7 @@ public class RmiMethodRegistry { */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) - public static @interface TraceMethod { + public static @interface TraceRmiMethod { String action() default ""; String display() default ""; diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiRemoteMethod.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiRemoteMethod.java index f7473316e0..68899f63a8 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiRemoteMethod.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/client/tracermi/RmiRemoteMethod.java @@ -18,7 +18,7 @@ package ghidra.app.plugin.core.debug.client.tracermi; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription; +import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription; import ghidra.trace.model.target.schema.*; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java index 779643b1a5..dc0c547952 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java @@ -51,7 +51,8 @@ import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.memory.*; -import ghidra.trace.model.stack.*; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.*; import ghidra.trace.model.target.iface.*; import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; @@ -60,7 +61,8 @@ import ghidra.trace.model.target.path.PathFilter.Align; import ghidra.trace.model.target.schema.*; import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.thread.*; +import ghidra.trace.model.thread.TraceProcess; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule.ScheduleForm; import ghidra.util.Msg; import ghidra.util.task.TaskMonitor; @@ -186,12 +188,12 @@ public class TraceRmiTarget extends AbstractTarget { } protected ScheduleForm getSupportedTimeFormByAttribute(TraceObject obj, long snap) { - TraceObject eventScope = obj.findSuitableInterface(TraceObjectEventScope.class); + TraceObject eventScope = obj.findSuitableInterface(TraceEventScope.class); if (eventScope == null) { return null; } TraceObjectValue timeSupportStr = - eventScope.getAttribute(snap, TraceObjectEventScope.KEY_TIME_SUPPORT); + eventScope.getAttribute(snap, TraceEventScope.KEY_TIME_SUPPORT); if (timeSupportStr == null) { return null; } @@ -213,11 +215,7 @@ public class TraceRmiTarget extends AbstractTarget { @Override public TraceExecutionState getThreadExecutionState(TraceThread thread) { - if (!(thread instanceof TraceObjectThread tot)) { - Msg.error(this, "Non-object thread with Trace RMI!"); - return TraceExecutionState.ALIVE; - } - return tot.getObject().getExecutionState(getSnap()); + return thread.getObject().getExecutionState(getSnap()); } @Override @@ -226,7 +224,7 @@ public class TraceRmiTarget extends AbstractTarget { if (object == null) { return null; } - return object.queryCanonicalAncestorsInterface(TraceObjectThread.class) + return object.queryCanonicalAncestorsInterface(TraceThread.class) .findFirst() .orElse(null); } @@ -237,7 +235,7 @@ public class TraceRmiTarget extends AbstractTarget { if (object == null) { return null; } - return object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class) + return object.queryCanonicalAncestorsInterface(TraceStackFrame.class) .findFirst() .orElse(null); } @@ -303,7 +301,7 @@ public class TraceRmiTarget extends AbstractTarget { return null; } TraceObjectValue attrEnabled = - object.getAttribute(getSnap(), TraceObjectTogglable.KEY_ENABLED); + object.getAttribute(getSnap(), TraceTogglable.KEY_ENABLED); boolean enabled = attrEnabled != null && attrEnabled.getValue() instanceof Boolean b && b; return !enabled; } @@ -549,7 +547,7 @@ public class TraceRmiTarget extends AbstractTarget { } return schema .getInterfaces() - .contains(TraceObjectFocusScope.class) && + .contains(TraceFocusScope.class) && !connection.getMethods().getByAction(ActionName.ACTIVATE).isEmpty(); } @@ -557,7 +555,7 @@ public class TraceRmiTarget extends AbstractTarget { public KeyPath getFocus() { TraceObjectValue focusVal = trace.getObjectManager() .getRootObject() - .getAttribute(getSnap(), TraceObjectFocusScope.KEY_FOCUS); + .getAttribute(getSnap(), TraceFocusScope.KEY_FOCUS); if (focusVal == null || !focusVal.isObject()) { return null; } @@ -740,7 +738,7 @@ public class TraceRmiTarget extends AbstractTarget { record ReadMemMatcher(int score, List spec) implements MethodMatcher { static final ReadMemMatcher HAS_PROC_RANGE = new ReadMemMatcher(2, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("range", AddressRange.class))); static final ReadMemMatcher HAS_RANGE = new ReadMemMatcher(1, List.of( new TypeParamSpec("range", AddressRange.class))); @@ -749,7 +747,7 @@ public class TraceRmiTarget extends AbstractTarget { record WriteMemMatcher(int score, List spec) implements MethodMatcher { static final WriteMemMatcher HAS_PROC_START_DATA = new WriteMemMatcher(2, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("start", Address.class), new TypeParamSpec("data", byte[].class))); static final WriteMemMatcher HAS_START_DATA = new WriteMemMatcher(1, List.of( @@ -760,43 +758,43 @@ public class TraceRmiTarget extends AbstractTarget { record ReadRegsMatcher(int score, List spec) implements MethodMatcher { static final ReadRegsMatcher HAS_CONTAINER = new ReadRegsMatcher(3, List.of( - new TypeParamSpec("container", TraceObjectRegisterContainer.class))); + new TypeParamSpec("container", TraceRegisterContainer.class))); static final ReadRegsMatcher HAS_REGISTER = new ReadRegsMatcher(1, List.of( - new TypeParamSpec("register", TraceObjectRegister.class))); + new TypeParamSpec("register", TraceRegister.class))); static final List ALL = matchers(HAS_CONTAINER, HAS_REGISTER); } record WriteRegMatcher(int score, List spec) implements MethodMatcher { static final WriteRegMatcher HAS_FRAME_NAME_VALUE = new WriteRegMatcher(3, List.of( - new TypeParamSpec("frame", TraceObjectStackFrame.class), + new TypeParamSpec("frame", TraceStackFrame.class), new TypeParamSpec("name", String.class), new TypeParamSpec("value", byte[].class))); static final WriteRegMatcher HAS_THREAD_NAME_VALUE = new WriteRegMatcher(2, List.of( - new TypeParamSpec("thread", TraceObjectThread.class), + new TypeParamSpec("thread", TraceThread.class), new TypeParamSpec("name", String.class), new TypeParamSpec("value", byte[].class))); static final WriteRegMatcher HAS_REG_VALUE = new WriteRegMatcher(1, List.of( - new TypeParamSpec("register", TraceObjectRegister.class), + new TypeParamSpec("register", TraceRegister.class), new TypeParamSpec("value", byte[].class))); static final List ALL = matchers(HAS_FRAME_NAME_VALUE, HAS_REG_VALUE); } record BreakExecMatcher(int score, List spec) implements MethodMatcher { static final BreakExecMatcher HAS_PROC_ADDR_COND_CMDS = new BreakExecMatcher(8, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("address", Address.class), new NameParamSpec("condition", String.class), new NameParamSpec("commands", String.class))); static final BreakExecMatcher HAS_PROC_ADDR_COND = new BreakExecMatcher(7, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("address", Address.class), new NameParamSpec("condition", String.class))); static final BreakExecMatcher HAS_PROC_ADDR_CMDS = new BreakExecMatcher(6, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("address", Address.class), new NameParamSpec("commands", String.class))); static final BreakExecMatcher HAS_PROC_ADDR = new BreakExecMatcher(5, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("address", Address.class))); static final BreakExecMatcher HAS_ADDR_COND_CMDS = new BreakExecMatcher(4, List.of( new TypeParamSpec("address", Address.class), @@ -818,20 +816,20 @@ public class TraceRmiTarget extends AbstractTarget { // TODO: Probably need a better way to deal with optional requirements record BreakAccMatcher(int score, List spec) implements MethodMatcher { static final BreakAccMatcher HAS_PROC_RNG_COND_CMDS = new BreakAccMatcher(8, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("range", AddressRange.class), new NameParamSpec("condition", String.class), new NameParamSpec("commands", String.class))); static final BreakAccMatcher HAS_PROC_RNG_COND = new BreakAccMatcher(7, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("range", AddressRange.class), new NameParamSpec("condition", String.class))); static final BreakAccMatcher HAS_PROC_RNG_CMDS = new BreakAccMatcher(6, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("range", AddressRange.class), new NameParamSpec("commands", String.class))); static final BreakAccMatcher HAS_PROC_RNG = new BreakAccMatcher(5, List.of( - new TypeParamSpec("process", TraceObjectProcess.class), + new TypeParamSpec("process", TraceProcess.class), new TypeParamSpec("range", AddressRange.class))); static final BreakAccMatcher HAS_RNG_COND_CMDS = new BreakAccMatcher(4, List.of( new TypeParamSpec("range", AddressRange.class), @@ -852,19 +850,19 @@ public class TraceRmiTarget extends AbstractTarget { record DelBreakMatcher(int score, List spec) implements MethodMatcher { static final DelBreakMatcher HAS_LOC = new DelBreakMatcher(2, List.of( - new TypeParamSpec("location", TraceObjectBreakpointLocation.class))); + new TypeParamSpec("location", TraceBreakpointLocation.class))); static final DelBreakMatcher HAS_SPEC = new DelBreakMatcher(1, List.of( - new TypeParamSpec("specification", TraceObjectBreakpointSpec.class))); + new TypeParamSpec("specification", TraceBreakpointSpec.class))); static final List ALL = matchers(HAS_LOC, HAS_SPEC); static final List SPEC = matchers(HAS_SPEC); } record ToggleBreakMatcher(int score, List spec) implements MethodMatcher { static final ToggleBreakMatcher HAS_LOC = new ToggleBreakMatcher(2, List.of( - new TypeParamSpec("location", TraceObjectBreakpointLocation.class), + new TypeParamSpec("location", TraceBreakpointLocation.class), new TypeParamSpec("enabled", Boolean.class))); static final ToggleBreakMatcher HAS_SPEC = new ToggleBreakMatcher(1, List.of( - new TypeParamSpec("specification", TraceObjectBreakpointSpec.class), + new TypeParamSpec("specification", TraceBreakpointSpec.class), new TypeParamSpec("enabled", Boolean.class))); static final List ALL = matchers(HAS_LOC, HAS_SPEC); static final List SPEC = matchers(HAS_SPEC); @@ -1079,8 +1077,8 @@ public class TraceRmiTarget extends AbstractTarget { } protected TraceObject getProcessForSpace(AddressSpace space) { - List processes = trace.getObjectManager() - .queryAllInterface(Lifespan.at(getSnap()), TraceObjectProcess.class) + List processes = trace.getObjectManager() + .queryAllInterface(Lifespan.at(getSnap()), TraceProcess.class) .toList(); if (processes.size() == 1) { return processes.get(0).getObject(); @@ -1089,11 +1087,10 @@ public class TraceRmiTarget extends AbstractTarget { return null; } for (TraceMemoryRegion region : trace.getMemoryManager() - .getRegionsIntersecting( - Lifespan.at(getSnap()), + .getRegionsIntersecting(Lifespan.at(getSnap()), new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) { - TraceObject obj = ((TraceObjectMemoryRegion) region).getObject(); - return obj.findCanonicalAncestorsInterface(TraceObjectProcess.class) + TraceObject obj = region.getObject(); + return obj.findCanonicalAncestorsInterface(TraceProcess.class) .findFirst() .orElse(null); } @@ -1207,11 +1204,7 @@ public class TraceRmiTarget extends AbstractTarget { if (readRegs == null) { return AsyncUtils.nil(); } - if (!(thread instanceof TraceObjectThread tot)) { - Msg.error(this, "Non-object trace with TraceRmi!"); - return AsyncUtils.nil(); - } - TraceObject container = tot.getObject().findRegisterContainer(frame); + TraceObject container = thread.getObject().findRegisterContainer(frame); if (container == null) { Msg.error(this, "Cannot find register container for thread,frame: " + thread + "," + frame); @@ -1229,8 +1222,7 @@ public class TraceRmiTarget extends AbstractTarget { keys.add("[" + lower + "]"); } Set regs = container - .findSuccessorsInterface(Lifespan.at(getSnap()), TraceObjectRegister.class, - true) + .findSuccessorsInterface(Lifespan.at(getSnap()), TraceRegister.class, true) .filter(p -> keys.contains(p.getLastEntry().getEntryKey().toLowerCase())) .map(r -> r.getDestination(null)) .collect(Collectors.toSet()); @@ -1303,14 +1295,13 @@ public class TraceRmiTarget extends AbstractTarget { return findRegister(container, filter, parent); } - protected FoundRegister findRegister(TraceObjectThread thread, int frame, - Register register) { + protected FoundRegister findRegister(TraceThread thread, int frame, Register register) { TraceObject container = thread.getObject().findRegisterContainer(frame); if (container == null) { Msg.error(this, "No register container for thread=" + thread + ",frame=" + frame); return null; } - PathFilter filter = container.getSchema().searchFor(TraceObjectRegister.class, true); + PathFilter filter = container.getSchema().searchFor(TraceRegister.class, true); return findRegister(container, filter, register); } @@ -1337,11 +1328,7 @@ public class TraceRmiTarget extends AbstractTarget { if (writeReg == null) { return AsyncUtils.nil(); } - if (!(thread instanceof TraceObjectThread tot)) { - Msg.error(this, "Non-object trace with TraceRmi!"); - return AsyncUtils.nil(); - } - FoundRegister found = findRegister(tot, frameLevel, value.getRegister()); + FoundRegister found = findRegister(thread, frameLevel, value.getRegister()); if (found == null) { Msg.warn(this, "Could not find register " + value.getRegister() + " in object model."); } @@ -1352,7 +1339,7 @@ public class TraceRmiTarget extends AbstractTarget { RemoteParameter paramThread = writeReg.params.get("thread"); if (paramThread != null) { return writeReg.method.invokeAsync(Map.ofEntries( - Map.entry(paramThread.name(), tot.getObject()), + Map.entry(paramThread.name(), thread.getObject()), Map.entry(writeReg.params.get("name").name(), found.name()), Map.entry(writeReg.params.get("value").name(), getBytes(value)))) .toCompletableFuture() @@ -1363,12 +1350,8 @@ public class TraceRmiTarget extends AbstractTarget { if (paramFrame != null) { TraceStack stack = trace.getStackManager().getLatestStack(thread, getSnap()); TraceStackFrame frame = stack.getFrame(getSnap(), frameLevel, false); - if (!(frame instanceof TraceObjectStackFrame tof)) { - Msg.error(this, "Non-object trace with TraceRmi!"); - return AsyncUtils.nil(); - } return writeReg.method.invokeAsync(Map.ofEntries( - Map.entry(paramFrame.name(), tof.getObject()), + Map.entry(paramFrame.name(), frame.getObject()), Map.entry(writeReg.params.get("name").name(), found.name()), Map.entry(writeReg.params.get("value").name(), getBytes(value)))) .toCompletableFuture() @@ -1398,11 +1381,8 @@ public class TraceRmiTarget extends AbstractTarget { if (register == null) { return false; } - if (!(thread instanceof TraceObjectThread tot)) { - return false; - } // May be primitive or object - FoundRegister found = findRegister(tot, frame, register); + FoundRegister found = findRegister(thread, frame, register); if (found == null) { return false; } @@ -1596,7 +1576,7 @@ public class TraceRmiTarget extends AbstractTarget { } @Override - public boolean isBreakpointValid(TraceBreakpoint breakpoint) { + public boolean isBreakpointValid(TraceBreakpointLocation breakpoint) { long snap = getSnap(); if (breakpoint.getName(snap).endsWith("emu-" + breakpoint.getMinAddress(snap))) { return false; @@ -1607,7 +1587,7 @@ public class TraceRmiTarget extends AbstractTarget { return true; } - protected CompletableFuture deleteBreakpointSpecAsync(TraceObjectBreakpointSpec spec) { + protected CompletableFuture deleteBreakpointSpecAsync(TraceBreakpointSpec spec) { KeyPath path = spec.getObject().getCanonicalPath(); MatchedMethod delBreak = matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.SPEC); @@ -1621,7 +1601,7 @@ public class TraceRmiTarget extends AbstractTarget { } // TODO: Would this make sense for any debugger? To delete individual locations? - protected CompletableFuture deleteBreakpointLocAsync(TraceObjectBreakpointLocation loc) { + protected CompletableFuture deleteBreakpointLocAsync(TraceBreakpointLocation loc) { KeyPath path = loc.getObject().getCanonicalPath(); MatchedMethod delBreak = matches.getBest(DelBreakMatcher.class, path, ActionName.DELETE, DelBreakMatcher.ALL); @@ -1639,18 +1619,18 @@ public class TraceRmiTarget extends AbstractTarget { } @Override - public CompletableFuture deleteBreakpointAsync(TraceBreakpoint breakpoint) { - if (breakpoint instanceof TraceObjectBreakpointLocation loc) { + public CompletableFuture deleteBreakpointAsync(TraceBreakpointCommon breakpoint) { + if (breakpoint instanceof TraceBreakpointLocation loc) { return deleteBreakpointLocAsync(loc); } - if (breakpoint instanceof TraceObjectBreakpointSpec spec) { + if (breakpoint instanceof TraceBreakpointSpec spec) { return deleteBreakpointSpecAsync(spec); } Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint); return AsyncUtils.nil(); } - protected CompletableFuture toggleBreakpointSpecAsync(TraceObjectBreakpointSpec spec, + protected CompletableFuture toggleBreakpointSpecAsync(TraceBreakpointSpec spec, boolean enabled) { KeyPath path = spec.getObject().getCanonicalPath(); MatchedMethod toggleBreak = @@ -1667,7 +1647,7 @@ public class TraceRmiTarget extends AbstractTarget { .thenApply(__ -> null); } - protected CompletableFuture toggleBreakpointLocAsync(TraceObjectBreakpointLocation loc, + protected CompletableFuture toggleBreakpointLocAsync(TraceBreakpointLocation loc, boolean enabled) { KeyPath path = loc.getObject().getCanonicalPath(); MatchedMethod toggleBreak = @@ -1690,12 +1670,12 @@ public class TraceRmiTarget extends AbstractTarget { } @Override - public CompletableFuture toggleBreakpointAsync(TraceBreakpoint breakpoint, + public CompletableFuture toggleBreakpointAsync(TraceBreakpointCommon breakpoint, boolean enabled) { - if (breakpoint instanceof TraceObjectBreakpointLocation loc) { + if (breakpoint instanceof TraceBreakpointLocation loc) { return toggleBreakpointLocAsync(loc, enabled); } - if (breakpoint instanceof TraceObjectBreakpointSpec spec) { + if (breakpoint instanceof TraceBreakpointSpec spec) { return toggleBreakpointSpecAsync(spec, enabled); } Msg.error(this, "Unrecognized TraceBreakpoint: " + breakpoint); diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/RemoteMethodInvocationDialogTest.java b/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/RemoteMethodInvocationDialogTest.java index d99180f3dc..2c9034dff0 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/RemoteMethodInvocationDialogTest.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/RemoteMethodInvocationDialogTest.java @@ -37,8 +37,8 @@ import ghidra.debug.api.target.ActionName; import ghidra.debug.api.tracermi.RemoteMethod; import ghidra.debug.api.tracermi.RemoteParameter; import ghidra.framework.options.PropertyBoolean; -import ghidra.trace.model.target.iface.TraceObjectMethod.Param; -import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription; +import ghidra.trace.model.target.iface.TraceMethod.Param; +import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription; import ghidra.trace.model.target.schema.*; import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; diff --git a/Ghidra/Debug/Debugger/ghidra_scripts/PopulateDemoTrace.java b/Ghidra/Debug/Debugger/ghidra_scripts/PopulateDemoTrace.java index a53fa6e066..dffdfa3aad 100644 --- a/Ghidra/Debug/Debugger/ghidra_scripts/PopulateDemoTrace.java +++ b/Ghidra/Debug/Debugger/ghidra_scripts/PopulateDemoTrace.java @@ -343,16 +343,16 @@ public class PopulateDemoTrace extends GhidraScript { */ mainLabel = trace.getSymbolManager() .labels() - .create(snap, null, addr(0x00400000), "main", global, SourceType.USER_DEFINED); + .create(snap, addr(0x00400000), "main", global, SourceType.USER_DEFINED); cloneLabel = trace.getSymbolManager() .labels() - .create(snap, null, addr(0x00400060), "clone", global, SourceType.USER_DEFINED); + .create(snap, addr(0x00400060), "clone", global, SourceType.USER_DEFINED); childLabel = trace.getSymbolManager() .labels() - .create(snap, null, addr(0x00400034), "child", global, SourceType.USER_DEFINED); + .create(snap, addr(0x00400034), "child", global, SourceType.USER_DEFINED); exitLabel = trace.getSymbolManager() .labels() - .create(snap, null, addr(0x00400061), "exit", global, SourceType.USER_DEFINED); + .create(snap, addr(0x00400061), "exit", global, SourceType.USER_DEFINED); /** * Note the use of getProgramView as a means of using components intended for Program diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByModuleAutoMapSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByModuleAutoMapSpec.java index 0c4243c680..fabefbada4 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByModuleAutoMapSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByModuleAutoMapSpec.java @@ -29,8 +29,8 @@ import ghidra.debug.api.modules.ModuleMapProposal; import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry; import ghidra.program.model.listing.Program; import ghidra.trace.model.Trace; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; -import ghidra.trace.model.modules.TraceObjectModule; +import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.modules.TraceModule; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.util.TraceEvent; import ghidra.trace.util.TraceEvents; @@ -76,8 +76,8 @@ public class ByModuleAutoMapSpec implements AutoMapSpec { @Override public boolean objectHasType(TraceObjectValue value) { - return value.getParent().queryInterface(TraceObjectModule.class) != null || - value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null; + return value.getParent().queryInterface(TraceModule.class) != null || + value.getParent().queryInterface(TraceMemoryRegion.class) != null; } @Override diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByRegionAutoMapSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByRegionAutoMapSpec.java index 177b67099f..aefc37f076 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByRegionAutoMapSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/ByRegionAutoMapSpec.java @@ -29,7 +29,7 @@ import ghidra.debug.api.modules.RegionMapProposal; import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry; import ghidra.program.model.listing.Program; import ghidra.trace.model.Trace; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; +import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.util.TraceEvent; import ghidra.trace.util.TraceEvents; @@ -61,7 +61,7 @@ public class ByRegionAutoMapSpec implements AutoMapSpec { @Override public boolean objectHasType(TraceObjectValue value) { - return value.getParent().queryInterface(TraceObjectMemoryRegion.class) != null; + return value.getParent().queryInterface(TraceMemoryRegion.class) != null; } static String getInfoForRegions(Trace trace, long snap) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BySectionAutoMapSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BySectionAutoMapSpec.java index cbb6efba73..e3a6f6dc60 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BySectionAutoMapSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BySectionAutoMapSpec.java @@ -28,8 +28,8 @@ import ghidra.debug.api.modules.MapProposal; import ghidra.debug.api.modules.SectionMapProposal; import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry; import ghidra.program.model.listing.Program; -import ghidra.trace.database.module.TraceObjectSection; import ghidra.trace.model.Trace; +import ghidra.trace.model.modules.TraceSection; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.util.TraceEvent; import ghidra.trace.util.TraceEvents; @@ -61,7 +61,7 @@ public class BySectionAutoMapSpec implements AutoMapSpec { @Override public boolean objectHasType(TraceObjectValue value) { - return value.getParent().queryInterface(TraceObjectSection.class) != null; + return value.getParent().queryInterface(TraceSection.class) != null; } @Override diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationTrait.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationTrait.java index f31c3b4a1b..b006703182 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationTrait.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationTrait.java @@ -40,11 +40,13 @@ import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.annotation.AutoConfigStateField; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.*; import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; +import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceEvents; import ghidra.util.Msg; @@ -60,10 +62,12 @@ public class DebuggerTrackLocationTrait { public ForTrackingListener() { listenFor(TraceEvents.BYTES_CHANGED, this::registersChanged); - listenFor(TraceEvents.STACK_CHANGED, this::stackChanged); + //listenFor(TraceEvents.STACK_CHANGED, this::stackChanged); + listenFor(TraceEvents.VALUE_CREATED, this::valueCreated); + listenFor(TraceEvents.VALUE_LIFESPAN_CHANGED, this::valueLifespanChanged); } - private void registersChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void registersChanged(AddressSpace space, TraceAddressSnapRange range, byte[] oldValue, byte[] newValue) { if (current.getView() == null || spec == null) { // Should only happen during transitional times, if at all. @@ -85,6 +89,42 @@ public class DebuggerTrackLocationTrait { } doTrack(TrackCause.DB_CHANGE); } + + private void valueCreated(TraceObjectValue value) { + if (!value.getLifespan().contains(current.getSnap())) { + return; + } + if (!value.getEntryKey().equals(TraceStackFrame.KEY_PC)) { + return; + } + TraceStackFrame frame = value.getParent().queryInterface(TraceStackFrame.class); + if (frame == null) { + return; + } + if (!tracker.affectedByStackChange(frame.getStack(), current)) { + return; + } + doTrack(TrackCause.DB_CHANGE); + } + + private void valueLifespanChanged(TraceObjectValue value, Lifespan oldLife, + Lifespan newLife) { + long snap = current.getSnap(); + if (oldLife.contains(snap) == newLife.contains(snap)) { + return; + } + if (!value.getEntryKey().equals(TraceStackFrame.KEY_PC)) { + return; + } + TraceStackFrame frame = value.getParent().queryInterface(TraceStackFrame.class); + if (frame == null) { + return; + } + if (!tracker.affectedByStackChange(frame.getStack(), current)) { + return; + } + doTrack(TrackCause.DB_CHANGE); + } } // TODO: This may already be deprecated.... @@ -297,6 +337,9 @@ public class DebuggerTrackLocationTrait { trackedLocation = newLocation; locationTracked(); } + catch (TraceClosedException ex) { + // Silently continue + } catch (Throwable ex) { Msg.error(this, "Error while computing location: " + ex); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java index af74c7b581..324589c772 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java @@ -4,9 +4,9 @@ * 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. @@ -22,10 +22,10 @@ import ghidra.debug.api.action.*; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.stack.TraceStack; -import ghidra.trace.util.TraceAddressSpace; public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTracker { INSTANCE; @@ -77,8 +77,8 @@ public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTr } @Override - public boolean affectedByBytesChange(TraceAddressSpace space, - TraceAddressSnapRange range, DebuggerCoordinates coordinates) { + public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range, + DebuggerCoordinates coordinates) { return false; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java index 52ab1c5ba7..5337da5ddc 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java @@ -22,13 +22,13 @@ import ghidra.debug.api.action.*; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.Trace; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, LocationTracker { INSTANCE; @@ -124,7 +124,7 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat } @Override - public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range, + public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range, DebuggerCoordinates coordinates) { return false; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java index aeb1f39368..ebe5408d11 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java @@ -4,9 +4,9 @@ * 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. @@ -22,10 +22,10 @@ import ghidra.debug.api.action.*; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.stack.TraceStack; -import ghidra.trace.util.TraceAddressSpace; public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTracker { INSTANCE; @@ -91,7 +91,7 @@ public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTrac } @Override - public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range, + public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range, DebuggerCoordinates coordinates) { return BY_REG.affectedByBytesChange(space, range, coordinates); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java index f41afad328..f1971550d2 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java @@ -29,7 +29,6 @@ import ghidra.trace.model.memory.TraceMemorySpace; import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, LocationTracker { Register computeRegister(DebuggerCoordinates coordinates); @@ -102,18 +101,17 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, Loca } @Override - default boolean affectedByBytesChange(TraceAddressSpace space, - TraceAddressSnapRange range, DebuggerCoordinates coordinates) { + default boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range, + DebuggerCoordinates coordinates) { if (!LocationTrackingSpec.changeIsCurrent(space, range, coordinates)) { return false; } Register register = computeRegister(coordinates); - AddressSpace as = space.getAddressSpace(); - if (register == null || register.getAddressSpace() != as) { + if (register == null) { return false; } AddressRange regRng = coordinates.getPlatform() - .getConventionalRegisterRange(as.isRegisterSpace() ? as : null, register); + .getConventionalRegisterRange(space.isRegisterSpace() ? space : null, register); return range.getRange().intersects(regRng); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/WatchLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/WatchLocationTrackingSpec.java index 8b951adc31..7f98648c3a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/WatchLocationTrackingSpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/WatchLocationTrackingSpec.java @@ -4,9 +4,9 @@ * 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. @@ -28,13 +28,11 @@ import ghidra.framework.plugintool.ServiceProvider; import ghidra.pcode.exec.*; import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue; import ghidra.pcode.exec.SleighUtils.AddressOf; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.address.*; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.stack.TraceStack; -import ghidra.trace.util.TraceAddressSpace; /** * A tracking specification for the address of a given Sleigh expression @@ -151,7 +149,7 @@ public class WatchLocationTrackingSpec implements LocationTrackingSpec { } @Override - public boolean affectedByBytesChange(TraceAddressSpace space, TraceAddressSnapRange range, + public boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range, DebuggerCoordinates coordinates) { return LocationTrackingSpec.changeIsCurrent(space, range, coordinates) && (reads == null || reads.intersects(range.getX1(), range.getX2())); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java index 8bc8095635..c835c5c32a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/BreakpointLocationRow.java @@ -24,13 +24,14 @@ import ghidra.debug.api.breakpoint.LogicalBreakpoint.State; import ghidra.pcode.exec.SleighUtils; import ghidra.program.model.address.Address; import ghidra.program.util.ProgramLocation; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; public class BreakpointLocationRow { private final DebuggerBreakpointsProvider provider; - private final TraceBreakpoint loc; + private final TraceBreakpointLocation loc; - public BreakpointLocationRow(DebuggerBreakpointsProvider provider, TraceBreakpoint loc) { + public BreakpointLocationRow(DebuggerBreakpointsProvider provider, + TraceBreakpointLocation loc) { this.provider = provider; this.loc = loc; } @@ -116,7 +117,7 @@ public class BreakpointLocationRow { return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh(getSnap())); } - public TraceBreakpoint getTraceBreakpoint() { + public TraceBreakpointLocation getTraceBreakpoint() { return loc; } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointLocationsActionContext.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointLocationsActionContext.java index 0873b6ed01..fe8bd5e8a6 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointLocationsActionContext.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointLocationsActionContext.java @@ -4,9 +4,9 @@ * 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. @@ -19,7 +19,7 @@ import java.util.Collection; import java.util.stream.Collectors; import docking.DefaultActionContext; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; public class DebuggerBreakpointLocationsActionContext extends DefaultActionContext { private final Collection selection; @@ -32,7 +32,7 @@ public class DebuggerBreakpointLocationsActionContext extends DefaultActionConte return selection; } - public Collection getLocations() { + public Collection getLocations() { return selection.stream().map(row -> row.getTraceBreakpoint()).collect(Collectors.toList()); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java index 7a14b7309f..c7a90e983b 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java @@ -57,8 +57,8 @@ import ghidra.program.model.address.AddressRange; import ghidra.program.util.MarkerLocation; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.util.TraceEvents; import ghidra.util.*; import ghidra.util.database.ObjectKey; @@ -230,11 +230,13 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter protected static class BreakpointLocationTableModel extends RowWrappedEnumeratedColumnTableModel< // - BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, TraceBreakpoint> { + BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, // + TraceBreakpointLocation> { public BreakpointLocationTableModel(DebuggerBreakpointsProvider provider) { super(provider.getTool(), "Locations", BreakpointLocationTableColumns.class, - TraceBreakpoint::getObjectKey, loc -> new BreakpointLocationRow(provider, loc), + TraceBreakpointLocation::getObjectKey, + loc -> new BreakpointLocationRow(provider, loc), BreakpointLocationRow::getTraceBreakpoint); } @@ -376,7 +378,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter if (context instanceof DebuggerBreakpointLocationsActionContext) { DebuggerBreakpointLocationsActionContext ctx = (DebuggerBreakpointLocationsActionContext) context; - Collection sel = ctx.getLocations(); + Collection sel = ctx.getLocations(); breakpointService.enableLocs(sel).exceptionally(ex -> { breakpointError("Enable Breakpoints", "Could not enable breakpoints", ex); return null; @@ -455,7 +457,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter if (context instanceof DebuggerBreakpointLocationsActionContext) { DebuggerBreakpointLocationsActionContext ctx = (DebuggerBreakpointLocationsActionContext) context; - Collection sel = ctx.getLocations(); + Collection sel = ctx.getLocations(); breakpointService.disableLocs(sel).exceptionally(ex -> { breakpointError("Disable Breakpoints", "Could not disable breakpoints", ex); return null; @@ -526,7 +528,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter if (context instanceof DebuggerBreakpointLocationsActionContext) { DebuggerBreakpointLocationsActionContext ctx = (DebuggerBreakpointLocationsActionContext) context; - Collection sel = ctx.getLocations(); + Collection sel = ctx.getLocations(); breakpointService.deleteLocs(sel).exceptionally(ex -> { breakpointError("Clear Breakpoints", "Could not clear breakpoints", ex); return null; @@ -700,26 +702,26 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter reloadBreakpointLocations(trace); } - private boolean isVisible(TraceBreakpoint location) { + private boolean isVisible(TraceBreakpointLocation location) { long snap = traceManager.getCurrentFor(trace).getSnap(); return location.isValid(snap); } - private void locationAdded(TraceBreakpoint location) { + private void locationAdded(TraceBreakpointLocation location) { if (!isVisible(location)) { return; } breakpointLocationAdded(location); } - private void locationChanged(TraceBreakpoint location) { + private void locationChanged(TraceBreakpointLocation location) { if (!isVisible(location)) { return; } breakpointLocationUpdated(location); } - private void locationLifespanChanged(TraceBreakpoint location, Lifespan oldSpan, + private void locationLifespanChanged(TraceBreakpointLocation location, Lifespan oldSpan, Lifespan newSpan) { long snap = traceManager.getCurrentFor(trace).getSnap(); boolean isLiveOld = oldSpan.contains(snap); @@ -735,7 +737,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter } } - private void locationDeleted(TraceBreakpoint location) { + private void locationDeleted(TraceBreakpointLocation location) { if (!isVisible(location)) { return; } @@ -955,15 +957,15 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter return; } Lifespan span = Lifespan.at(currentFor.getSnap()); - Collection visible = new ArrayList<>(); + Collection visible = new ArrayList<>(); for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) { - Collection breaks = + Collection breaks = trace.getBreakpointManager().getBreakpointsIntersecting(span, range); if (mode.useEmulatedBreakpoints()) { visible.addAll(breaks); } else { - for (TraceBreakpoint l : breaks) { + for (TraceBreakpointLocation l : breaks) { if (target.isBreakpointValid(l)) { visible.add(l); } @@ -982,19 +984,19 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter loadBreakpointLocations(trace); } - private void breakpointLocationAdded(TraceBreakpoint location) { + private void breakpointLocationAdded(TraceBreakpointLocation location) { locationTableModel.addItem(location); } - private void breakpointLocationUpdated(TraceBreakpoint location) { + private void breakpointLocationUpdated(TraceBreakpointLocation location) { locationTableModel.updateItem(location); } - private void breakpointLocationsUpdated(Collection locations) { + private void breakpointLocationsUpdated(Collection locations) { locationTableModel.updateAllItems(locations); } - private void breakpointLocationRemoved(TraceBreakpoint location) { + private void breakpointLocationRemoved(TraceBreakpointLocation location) { locationTableModel.deleteItem(location); } @@ -1304,12 +1306,12 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter } } else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { - Collection locations = locCtx.getLocations(); + Collection locations = locCtx.getLocations(); if (locations.isEmpty()) { return false; } - for (TraceBreakpoint tb : locations) { - traces.add(tb.getTrace()); + for (TraceBreakpointLocation loc : locations) { + traces.add(loc.getTrace()); } } else { @@ -1338,9 +1340,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter return true; } else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { - for (TraceBreakpoint tb : locCtx.getLocations()) { - long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap(); - if (!EXECUTE_KINDS.containsAll(tb.getKinds(snap))) { + for (TraceBreakpointLocation loc : locCtx.getLocations()) { + long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap(); + if (!EXECUTE_KINDS.containsAll(loc.getKinds(snap))) { return false; } } @@ -1371,9 +1373,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter return sleigh; } else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { - for (TraceBreakpoint tb : locCtx.getLocations()) { - long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap(); - String s = tb.getEmuSleigh(snap); + for (TraceBreakpointLocation loc : locCtx.getLocations()) { + long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap(); + String s = loc.getEmuSleigh(snap); if (sleigh != null && !sleigh.equals(s)) { return null; } @@ -1397,9 +1399,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter } } else if (ctx instanceof DebuggerBreakpointLocationsActionContext locCtx) { - for (TraceBreakpoint tb : locCtx.getLocations()) { - long snap = traceManager.getCurrentFor(tb.getTrace()).getSnap(); - tb.setEmuSleigh(snap, sleigh); + for (TraceBreakpointLocation loc : locCtx.getLocations()) { + long snap = traceManager.getCurrentFor(loc.getTrace()).getSnap(); + loc.setEmuSleigh(snap, sleigh); } } else { @@ -1466,7 +1468,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter breakpointTableModel, breakpointFilterPanel); } - public void setSelectedLocations(Set sel) { + public void setSelectedLocations(Set sel) { DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable, locationTableModel, locationFilterPanel); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlan.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlan.java index 5e708c6669..2d08d29041 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlan.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlan.java @@ -28,7 +28,7 @@ import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.memory.TraceMemoryManager; import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.program.TraceProgramView; @@ -220,7 +220,7 @@ public class DebuggerCopyPlan { public void copy(TraceProgramView from, AddressRange fromRange, Program into, Address intoAddress, TaskMonitor monitor) throws Exception { long snap = from.getSnap(); - for (TraceBreakpoint bpt : from.getTrace() + for (TraceBreakpointLocation bpt : from.getTrace() .getBreakpointManager() .getBreakpointsIntersecting(Lifespan.at(from.getSnap()), fromRange)) { monitor.checkCancelled(); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java index 5b33e933b6..e4374c21bd 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerAddRegionDialog.java @@ -32,7 +32,7 @@ import ghidra.program.model.address.*; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.memory.TraceMemoryFlag; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; +import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.util.layout.PairLayout; @@ -161,8 +161,8 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider { if (rootSchema == null) { return ""; } - KeyPath suitable = rootSchema.searchForSuitableContainer(TraceObjectMemoryRegion.class, - current.getPath()); + KeyPath suitable = + rootSchema.searchForSuitableContainer(TraceMemoryRegion.class, current.getPath()); if (suitable == null) { return ""; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java index ac26caf51e..4a1767f3c2 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java @@ -55,8 +55,7 @@ import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.annotation.AutoConfigStateField; import ghidra.framework.plugintool.annotation.AutoServiceConsumed; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryBlock; @@ -65,7 +64,6 @@ import ghidra.program.util.ProgramSelection; import ghidra.trace.model.Trace; import ghidra.trace.model.TraceDomainObjectListener; import ghidra.trace.model.program.TraceProgramView; -import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceEvents; import ghidra.util.Swing; @@ -99,8 +97,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi listenFor(TraceEvents.BYTES_CHANGED, this::bytesChanged); } - private void bytesChanged(TraceAddressSpace space) { - if (space.getAddressSpace().isMemorySpace()) { + private void bytesChanged(AddressSpace space) { + if (space.isMemorySpace()) { currCache.invalidate(); prevCache.invalidate(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsPanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsPanel.java index 4f2a727891..6ff24f9b04 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsPanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsPanel.java @@ -29,13 +29,14 @@ import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; import ghidra.trace.model.Trace; -import ghidra.trace.model.memory.*; +import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.memory.TraceMemory; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.model.thread.TraceObjectProcess; +import ghidra.trace.model.thread.TraceProcess; -public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel { +public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel { private static class RegionKeyColumn extends TraceValueKeyColumn { @Override @@ -66,7 +67,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel getSelectedRegions(DebuggerObjectActionContext ctx) { @@ -182,7 +183,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel { MemoryBox box = new MemoryBox(currentTrace, "Thread " + thread.getName(p.getMinSnap()), MemviewBoxType.THREAD, rng, p.getLifespan()); @@ -118,13 +120,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener { } private void regionChanged(TraceMemoryRegion region) { - if (!trackRegions || !trackTrace || - !(region instanceof TraceObjectMemoryRegion objRegion)) { + if (!trackRegions || !trackTrace) { return; } - TraceObject obj = objRegion.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectMemoryRegion.KEY_RANGE, true).forEach(v -> { + TraceObject obj = region.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceMemoryRegion.KEY_RANGE, true).forEach(v -> { if (region.getName(v.getMinSnap()).equals("full memory")) { return; } @@ -136,12 +137,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener { } private void moduleChanged(TraceModule module) { - if (!trackModules || !trackTrace || !(module instanceof TraceObjectModule objModule)) { + if (!trackModules || !trackTrace) { return; } - TraceObject obj = objModule.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectModule.KEY_RANGE, true).forEach(v -> { + TraceObject obj = module.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceModule.KEY_RANGE, true).forEach(v -> { MemoryBox box = new MemoryBox(currentTrace, "Module " + module.getName(v.getMinSnap()), MemviewBoxType.MODULE, v.castValue(), v.getLifespan()); updateList.add(box); @@ -150,12 +151,12 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener { } private void sectionChanged(TraceSection section) { - if (!trackSections || !trackTrace || !(section instanceof TraceObjectSection objSection)) { + if (!trackSections || !trackTrace) { return; } - TraceObject obj = objSection.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectSection.KEY_RANGE, true).forEach(v -> { + TraceObject obj = section.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceSection.KEY_RANGE, true).forEach(v -> { MemoryBox box = new MemoryBox(currentTrace, "Module " + section.getName(v.getMinSnap()), MemviewBoxType.IMAGE, v.castValue(), v.getLifespan()); updateList.add(box); @@ -163,14 +164,13 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener { updateLabelDebouncer.contact(null); } - private void breakpointChanged(TraceBreakpoint bpt) { - if (!trackBreakpoints || !trackTrace || - !(bpt instanceof TraceObjectBreakpointLocation objBpt)) { + private void breakpointChanged(TraceBreakpointLocation bpt) { + if (!trackBreakpoints || !trackTrace) { return; } - TraceObject obj = objBpt.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) + TraceObject obj = bpt.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) .forEach(v -> { MemoryBox box = new MemoryBox(currentTrace, "Module " + bpt.getName(v.getMinSnap()), @@ -301,7 +301,7 @@ public class DebuggerMemviewTraceListener extends TraceDomainObjectListener { regionChanged(region); } TraceBreakpointManager breakpointManager = trace.getBreakpointManager(); - for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) { + for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) { breakpointChanged(bpt); } updateLabelDebouncer.contact(null); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectDefaultActionsMixin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectDefaultActionsMixin.java index 41e5b5ff49..7315319469 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectDefaultActionsMixin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectDefaultActionsMixin.java @@ -130,7 +130,7 @@ public interface ObjectDefaultActionsMixin { default boolean performDefaultAction(TraceObject object) { Set> interfaces = object.getSchema().getInterfaces(); - if (interfaces.contains(TraceObjectActivatable.class)) { + if (interfaces.contains(TraceActivatable.class)) { activatePath(object.getCanonicalPath()); return true; } @@ -138,7 +138,7 @@ public interface ObjectDefaultActionsMixin { * Should I check aliveAndPresent() here? If I do, behavior changes when target is dead, * which might be unexpected. */ - if (interfaces.contains(TraceObjectTogglable.class)) { + if (interfaces.contains(TraceTogglable.class)) { toggleObject(object); return true; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectTreeModel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectTreeModel.java index 0417322e11..cb71223117 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectTreeModel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/ObjectTreeModel.java @@ -26,8 +26,8 @@ import generic.theme.GIcon; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.framework.model.*; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation; -import ghidra.trace.model.breakpoint.TraceObjectBreakpointSpec; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.breakpoint.TraceBreakpointSpec; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.iface.*; @@ -65,10 +65,10 @@ public class ObjectTreeModel implements DisplaysModified { if (!value.getParent() .getSchema() .getInterfaces() - .contains(TraceObjectEventScope.class)) { + .contains(TraceEventScope.class)) { return false; } - if (!TraceObjectEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) { + if (!TraceEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) { return false; } return true; @@ -77,12 +77,12 @@ public class ObjectTreeModel implements DisplaysModified { protected boolean isEnabledValue(TraceObjectValue value) { Set> interfaces = value.getParent().getSchema().getInterfaces(); - if (!interfaces.contains(TraceObjectBreakpointSpec.class) && - !interfaces.contains(TraceObjectBreakpointLocation.class) && - !interfaces.contains(TraceObjectTogglable.class)) { + if (!interfaces.contains(TraceBreakpointSpec.class) && + !interfaces.contains(TraceBreakpointLocation.class) && + !interfaces.contains(TraceTogglable.class)) { return false; } - if (!TraceObjectTogglable.KEY_ENABLED.equals(value.getEntryKey())) { + if (!TraceTogglable.KEY_ENABLED.equals(value.getEntryKey())) { return false; } return true; @@ -675,7 +675,7 @@ public class ObjectTreeModel implements DisplaysModified { protected TraceObject getEventObject(TraceObject object) { TraceObject scope = object - .findCanonicalAncestorsInterface(TraceObjectEventScope.class) + .findCanonicalAncestorsInterface(TraceEventScope.class) .findFirst() .orElse(null); if (scope == null) { @@ -685,7 +685,7 @@ public class ObjectTreeModel implements DisplaysModified { return null; } TraceObjectValue eventValue = - scope.getAttribute(snap, TraceObjectEventScope.KEY_EVENT_THREAD); + scope.getAttribute(snap, TraceEventScope.KEY_EVENT_THREAD); if (eventValue == null || !eventValue.isObject()) { return null; } @@ -712,7 +712,7 @@ public class ObjectTreeModel implements DisplaysModified { if (type.contains("Breakpoint") || type.contains("Watchpoint")) { TraceObject object = edge.getChild(); TraceObjectValue en = - object.getAttribute(snap, TraceObjectTogglable.KEY_ENABLED); + object.getAttribute(snap, TraceTogglable.KEY_ENABLED); // includes true or non-boolean values if (en == null || !Objects.equals(false, en.getValue())) { return DebuggerResources.ICON_SET_BREAKPOINT; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java index b4a26fe64c..9ee413ef48 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java @@ -31,20 +31,20 @@ import ghidra.docking.settings.Settings; import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.*; -import ghidra.trace.database.module.TraceObjectSection; import ghidra.trace.model.Trace; -import ghidra.trace.model.modules.*; +import ghidra.trace.model.modules.TraceModule; +import ghidra.trace.model.modules.TraceSection; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.model.thread.TraceObjectProcess; +import ghidra.trace.model.thread.TraceProcess; -public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel { +public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel { private static class ModuleBaseColumn extends AbstractTraceValueObjectAddressColumn { public ModuleBaseColumn() { - super(TraceObjectModule.KEY_RANGE); + super(TraceModule.KEY_RANGE); } @Override @@ -60,7 +60,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel { public ModuleNameColumn() { - super(TraceObjectModule.KEY_MODULE_NAME, String.class); + super(TraceModule.KEY_MODULE_NAME, String.class); } @Override @@ -98,7 +98,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel attr = - rowObject.getAttribute(TraceObjectModule.KEY_RANGE, AddressRange.class); + rowObject.getAttribute(TraceModule.KEY_RANGE, AddressRange.class); if (attr == null) { return ""; } @@ -131,7 +131,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel { +public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel { private static class SectionStartColumn extends AbstractTraceValueObjectAddressColumn { public SectionStartColumn() { - super(TraceObjectSection.KEY_RANGE); + super(TraceSection.KEY_RANGE); } @Override @@ -61,7 +60,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel { @@ -201,7 +199,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel> validateArguments( Map> parameters, Map> arguments) { Map args = ValStr.toPlainMap(arguments); - return ValStr.fromPlainMap(TraceObjectMethod.validateArguments(parameters, args, false)); + return ValStr.fromPlainMap(TraceMethod.validateArguments(parameters, args, false)); } @Override diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java index 87d54e8eae..3424208868 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java @@ -69,9 +69,9 @@ import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.listing.*; import ghidra.trace.model.memory.*; import ghidra.trace.model.program.TraceProgramView; -import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.*; +import ghidra.trace.util.TraceEvents; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.classfinder.ClassSearcher; @@ -283,37 +283,28 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter listenFor(TraceEvents.THREAD_LIFESPAN_CHANGED, this::threadDestroyed); } - private boolean isVisibleObjectsMode(AddressSpace space) { - TraceObject container = current.getRegisterContainer(); - return container != null && - container.getCanonicalPath().toString().equals(space.getName()); - } - - private boolean isVisible(TraceAddressSpace space) { + private boolean isVisible(AddressSpace space) { + if (!space.isRegisterSpace()) { + return true; // Memory-mapped, visible no matter the active thread + } TraceThread curThread = current.getThread(); if (curThread == null) { return false; } - if (space.getAddressSpace().isOverlaySpace()) { - return isVisibleObjectsMode(space.getAddressSpace()); + if (space.isOverlaySpace()) { + return current.isRegisterSpace(space); } - if (!space.getAddressSpace().isRegisterSpace()) { - return true; // Memory-mapped, visible no matter the active thread + if (space.isRegisterSpace()) { + throw new AssertionError(); } - if (space.getThread() != curThread) { - return false; - } - if (space.getFrameLevel() != current.getFrame()) { - return false; - } - return true; + return false; } - private boolean isVisible(TraceAddressSpace space, TraceAddressSnapRange range) { + private boolean isVisible(AddressSpace space, TraceAddressSnapRange range) { if (!isVisible(space)) { return false; } - if (space.getAddressSpace().isMemorySpace()) { + if (space.isMemorySpace()) { return current.getPlatform() .getLanguage() .getRegisterAddresses() @@ -351,7 +342,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter } } - private void registerValueChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void registerValueChanged(AddressSpace space, TraceAddressSnapRange range, byte[] oldIsNull, byte[] newVal) { if (!isVisible(space, range)) { return; @@ -359,7 +350,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter refreshRange(range.getRange()); } - private void registerStateChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void registerStateChanged(AddressSpace space, TraceAddressSnapRange range, TraceMemoryState oldState, TraceMemoryState newState) { if (!isVisible(space, range)) { return; @@ -368,7 +359,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter refreshRange(range.getRange()); } - private void registerTypeAdded(TraceAddressSpace space, TraceAddressSnapRange range, + private void registerTypeAdded(AddressSpace space, TraceAddressSnapRange range, TraceCodeUnit oldIsNull, TraceCodeUnit newUnit) { if (!isVisible(space, range)) { return; @@ -376,7 +367,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter refreshRange(range.getRange()); } - private void registerTypeReplaced(TraceAddressSpace space, TraceAddressSnapRange range, + private void registerTypeReplaced(AddressSpace space, TraceAddressSnapRange range, long oldTypeID, long newTypeID) { if (!isVisible(space, range)) { return; @@ -384,7 +375,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter refreshRange(range.getRange()); } - private void registerTypeLifespanChanged(TraceAddressSpace space, TraceCodeUnit unit, + private void registerTypeLifespanChanged(AddressSpace space, TraceCodeUnit unit, Lifespan oldSpan, Lifespan newSpan) { if (!isVisible(space)) { return; @@ -402,7 +393,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter refreshRange(range); // Slightly wasteful, as we already have the data unit } - private void registerTypeRemoved(TraceAddressSpace space, TraceAddressSnapRange range, + private void registerTypeRemoved(AddressSpace space, TraceAddressSnapRange range, TraceCodeUnit oldUnit, TraceCodeUnit newIsNull) { if (!isVisible(space)) { return; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java index c8bf0c592c..e42bf5b02a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java @@ -34,15 +34,15 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.trace.model.Trace; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.schema.TraceObjectSchema; -public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel +public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel implements ListSelectionListener { private static class FrameLevelColumn extends TraceValueKeyColumn { @@ -59,7 +59,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel { public FramePcColumn() { - super(TraceObjectStackFrame.KEY_PC, Address.class); + super(TraceStackFrame.KEY_PC, Address.class); } @Override @@ -72,7 +72,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel { +public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel { protected static ModelQuery successorThreads(TraceObjectSchema rootSchema, KeyPath path) { TraceObjectSchema schema = rootSchema.getSuccessorSchema(path); - return new ModelQuery(schema.searchFor(TraceObjectThread.class, path, true)); + return new ModelQuery(schema.searchFor(TraceThread.class, path, true)); } private static class ThreadPathColumn extends TraceValueKeyColumn { @@ -246,7 +246,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel { public ThreadStateColumn() { // NB. The recorder converts enums to strings - super(TraceObjectExecutionStateful.KEY_STATE, String.class); + super(TraceExecutionStateful.KEY_STATE, String.class); } @Override @@ -258,7 +258,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel { public ThreadCommentColumn() { - super(TraceObjectThread.KEY_COMMENT, String.class); + super(TraceThread.KEY_COMMENT, String.class); } @Override @@ -315,7 +315,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel allServices; @@ -270,27 +273,19 @@ public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin { Trace trace = traceManager.getCurrentTrace(); TraceThreadManager threadManager = trace.getThreadManager(); for (TraceThread thread : threadManager.getAllThreads()) { - if (thread instanceof TraceObjectThread objThread) { - addObject(set, objThread.getObject()); - } + addObject(set, thread.getObject()); } TraceModuleManager moduleManager = trace.getModuleManager(); for (TraceModule module : moduleManager.getAllModules()) { - if (module instanceof TraceObjectModule objModule) { - addObject(set, objModule.getObject()); - } + addObject(set, module.getObject()); } TraceMemoryManager memoryManager = trace.getMemoryManager(); for (TraceMemoryRegion region : memoryManager.getAllRegions()) { - if (region instanceof TraceObjectMemoryRegion objRegion) { - addObject(set, objRegion.getObject()); - } + addObject(set, region.getObject()); } TraceBreakpointManager breakpointManager = trace.getBreakpointManager(); - for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) { - if (bpt instanceof TraceObjectBreakpointLocation objBreakpoint) { - addObject(set, objBreakpoint.getObject()); - } + for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) { + addObject(set, bpt.getObject()); } TraceBookmarkManager bookmarkManager = trace.getBookmarkManager(); for (TraceBookmark mark : bookmarkManager.getAllBookmarks()) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/timeoverview/TimeOverviewEventListener.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/timeoverview/TimeOverviewEventListener.java index 9a7b278f0f..781a8931bb 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/timeoverview/TimeOverviewEventListener.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/timeoverview/TimeOverviewEventListener.java @@ -23,11 +23,15 @@ import ghidra.framework.model.DomainObjectChangeRecord; import ghidra.framework.model.DomainObjectEvent; import ghidra.trace.model.*; import ghidra.trace.model.bookmark.TraceBookmark; -import ghidra.trace.model.breakpoint.*; -import ghidra.trace.model.memory.*; -import ghidra.trace.model.modules.*; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.breakpoint.TraceBreakpointManager; +import ghidra.trace.model.memory.TraceMemoryManager; +import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.modules.TraceModule; +import ghidra.trace.model.modules.TraceModuleManager; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.*; +import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.model.thread.TraceThreadManager; import ghidra.trace.util.TraceEvents; import ghidra.util.Swing; @@ -118,193 +122,150 @@ public class TimeOverviewEventListener extends TraceDomainObjectListener { regionChanged(region); } TraceBreakpointManager breakpointManager = trace.getBreakpointManager(); - for (TraceBreakpoint bpt : breakpointManager.getAllBreakpoints()) { + for (TraceBreakpointLocation bpt : breakpointManager.getAllBreakpointLocations()) { bptChanged(bpt); } } - - private void threadAdded(TraceThread thread) { - if (!(thread instanceof TraceObjectThread objThread)) { - return; - } - TraceObject obj = objThread.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMinSnap(); - p.updateMap(snap, TimeType.BPT_ADDED, thread.getName(snap), true); - }); + private void threadAdded(TraceThread thread) { + TraceObject obj = thread.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMinSnap(); + p.updateMap(snap, TimeType.BPT_ADDED, thread.getName(snap), true); + }); } private void threadChanged(TraceThread thread) { - if (!(thread instanceof TraceObjectThread objThread)) { - return; - } - - TraceObject obj = objThread.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectThread.KEY_TID, true) - .forEach(v -> { - long snapMin = v.getMinSnap(); - long snapMax = v.getMaxSnap(); - if (snapMin == snapMax) { - p.updateMap(snapMin, TimeType.THREAD_CHANGED, thread.getName(snapMin), true); - } - else { - p.updateMap(snapMin, TimeType.THREAD_ADDED, thread.getName(snapMin), true); - p.updateMap(snapMax, TimeType.THREAD_REMOVED, thread.getName(snapMax), true); - } - }); + TraceObject obj = thread.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceThread.KEY_TID, true).forEach(v -> { + long snapMin = v.getMinSnap(); + long snapMax = v.getMaxSnap(); + if (snapMin == snapMax) { + p.updateMap(snapMin, TimeType.THREAD_CHANGED, thread.getName(snapMin), + true); + } + else { + p.updateMap(snapMin, TimeType.THREAD_ADDED, thread.getName(snapMin), true); + p.updateMap(snapMax, TimeType.THREAD_REMOVED, thread.getName(snapMax), + true); + } + }); } private void threadDeleted(TraceThread thread) { - if (!(thread instanceof TraceObjectThread objThread)) { - return; - } - - TraceObject obj = objThread.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMaxSnap(); - p.updateMap(snap, TimeType.THREAD_REMOVED, thread.getName(snap), true); - }); + TraceObject obj = thread.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMaxSnap(); + p.updateMap(snap, TimeType.THREAD_REMOVED, thread.getName(snap), true); + }); } private void moduleAdded(TraceModule module) { - if (!(module instanceof TraceObjectModule objMod)) { - return; - } - - TraceObject obj = objMod.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMinSnap(); - p.updateMap(snap, TimeType.MODULE_ADDED, module.getName(snap), true); - }); + TraceObject obj = module.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMinSnap(); + p.updateMap(snap, TimeType.MODULE_ADDED, module.getName(snap), true); + }); } private void moduleChanged(TraceModule module) { - if (!(module instanceof TraceObjectModule objMod)) { - return; - } - - TraceObject obj = objMod.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snapMin = v.getMinSnap(); - long snapMax = v.getMaxSnap(); - if (snapMin == snapMax) { - p.updateMap(snapMin, TimeType.MODULE_CHANGED, module.getName(snapMin), true); - } - else { - p.updateMap(snapMin, TimeType.MODULE_ADDED, module.getName(snapMin), true); - p.updateMap(snapMax, TimeType.MODULE_REMOVED, module.getName(snapMax), true); - } - }); + TraceObject obj = module.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snapMin = v.getMinSnap(); + long snapMax = v.getMaxSnap(); + if (snapMin == snapMax) { + p.updateMap(snapMin, TimeType.MODULE_CHANGED, module.getName(snapMin), + true); + } + else { + p.updateMap(snapMin, TimeType.MODULE_ADDED, module.getName(snapMin), true); + p.updateMap(snapMax, TimeType.MODULE_REMOVED, module.getName(snapMax), + true); + } + }); } private void moduleDeleted(TraceModule module) { - if (!(module instanceof TraceObjectModule objMod)) { - return; - } - - TraceObject obj = objMod.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMaxSnap(); - p.updateMap(snap, TimeType.MODULE_REMOVED, module.getName(snap), true); - }); + TraceObject obj = module.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMaxSnap(); + p.updateMap(snap, TimeType.MODULE_REMOVED, module.getName(snap), true); + }); } private void regionAdded(TraceMemoryRegion region) { - if (!(region instanceof TraceObjectMemoryRegion objReg)) { - return; - } - - TraceObject obj = objReg.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMinSnap(); - p.updateMap(snap, TimeType.REGION_ADDED, region.getName(snap), true); - }); + TraceObject obj = region.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMinSnap(); + p.updateMap(snap, TimeType.REGION_ADDED, region.getName(snap), true); + }); } private void regionChanged(TraceMemoryRegion region) { - if (!(region instanceof TraceObjectMemoryRegion objReg)) { - return; - } - - TraceObject obj = objReg.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snapMin = v.getMinSnap(); - long snapMax = v.getMaxSnap(); - if (snapMin == snapMax) { - p.updateMap(snapMin, TimeType.REGION_CHANGED, region.getName(snapMin), true); - } - else { - p.updateMap(snapMin, TimeType.REGION_ADDED, region.getName(snapMin), true); - p.updateMap(snapMax, TimeType.REGION_REMOVED, region.getName(snapMax), true); - } - }); + TraceObject obj = region.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snapMin = v.getMinSnap(); + long snapMax = v.getMaxSnap(); + if (snapMin == snapMax) { + p.updateMap(snapMin, TimeType.REGION_CHANGED, region.getName(snapMin), + true); + } + else { + p.updateMap(snapMin, TimeType.REGION_ADDED, region.getName(snapMin), true); + p.updateMap(snapMax, TimeType.REGION_REMOVED, region.getName(snapMax), + true); + } + }); } private void regionDeleted(TraceMemoryRegion region) { - if (!(region instanceof TraceObjectMemoryRegion objReg)) { - return; - } - - TraceObject obj = objReg.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMaxSnap(); - p.updateMap(snap, TimeType.REGION_REMOVED, region.getName(snap), true); - }); + TraceObject obj = region.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMaxSnap(); + p.updateMap(snap, TimeType.REGION_REMOVED, region.getName(snap), true); + }); } - private void bptAdded(TraceBreakpoint bpt) { - if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) { - return; - } - - TraceObject obj = objBpt.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMinSnap(); - p.updateMap(snap, TimeType.BPT_ADDED, bpt.getName(snap), true); - }); + private void bptAdded(TraceBreakpointLocation bpt) { + TraceObject obj = bpt.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMinSnap(); + p.updateMap(snap, TimeType.BPT_ADDED, bpt.getName(snap), true); + }); } - private void bptChanged(TraceBreakpoint bpt) { - if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) { - return; - } - - TraceObject obj = objBpt.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snapMin = v.getMinSnap(); - long snapMax = v.getMaxSnap(); - if (snapMin == snapMax) { - p.updateMap(snapMin, TimeType.BPT_CHANGED, bpt.getName(snapMin), true); - } - else { - p.updateMap(snapMin, TimeType.BPT_ADDED, bpt.getName(snapMin), true); - p.updateMap(snapMax, TimeType.BPT_REMOVED, bpt.getName(snapMax), true); - } - }); + private void bptChanged(TraceBreakpointLocation bpt) { + TraceObject obj = bpt.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snapMin = v.getMinSnap(); + long snapMax = v.getMaxSnap(); + if (snapMin == snapMax) { + p.updateMap(snapMin, TimeType.BPT_CHANGED, bpt.getName(snapMin), true); + } + else { + p.updateMap(snapMin, TimeType.BPT_ADDED, bpt.getName(snapMin), true); + p.updateMap(snapMax, TimeType.BPT_REMOVED, bpt.getName(snapMax), true); + } + }); } - private void bptDeleted(TraceBreakpoint bpt) { - if (!(bpt instanceof TraceObjectBreakpointLocation objBpt)) { - return; - } - - TraceObject obj = objBpt.getObject(); - obj.getOrderedValues(Lifespan.ALL, TraceObjectBreakpointLocation.KEY_RANGE, true) - .forEach(v -> { - long snap = v.getMaxSnap(); - p.updateMap(snap, TimeType.BPT_REMOVED, bpt.getName(snap), true); - }); + private void bptDeleted(TraceBreakpointLocation bpt) { + TraceObject obj = bpt.getObject(); + obj.getOrderedValues(Lifespan.ALL, TraceBreakpointLocation.KEY_RANGE, true) + .forEach(v -> { + long snap = v.getMaxSnap(); + p.updateMap(snap, TimeType.BPT_REMOVED, bpt.getName(snap), true); + }); } private void bookmarkAdded(TraceBookmark bookmark) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java index 26cc6d27a6..3433fcf0bd 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java @@ -78,7 +78,6 @@ import ghidra.trace.model.*; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.time.schedule.TraceSchedule; -import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceEvents; import ghidra.util.HelpLocation; import ghidra.util.Msg; @@ -260,14 +259,14 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter } } - private void bytesChanged(TraceAddressSpace space, TraceAddressSnapRange range) { - if (space.getThread() == current.getThread() || space.getThread() == null) { + private void bytesChanged(AddressSpace space, TraceAddressSnapRange range) { + if (space.isMemorySpace() || current.isRegisterSpace(space)) { addChanged(range.getRange()); } } - private void stateChanged(TraceAddressSpace space, TraceAddressSnapRange range) { - if (space.getThread() == current.getThread() || space.getThread() == null) { + private void stateChanged(AddressSpace space, TraceAddressSnapRange range) { + if (space.isMemorySpace() || current.isRegisterSpace(space)) { addChanged(range.getRange()); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DefaultWatchRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DefaultWatchRow.java index 9d316dbeb9..caa870740a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DefaultWatchRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DefaultWatchRow.java @@ -529,7 +529,7 @@ public class DefaultWatchRow implements WatchRow { DebuggerCoordinates current = provider.current; Trace trace = current.getTrace(); Collection labels = - trace.getSymbolManager().labels().getAt(current.getSnap(), null, address, false); + trace.getSymbolManager().labels().getAt(current.getSnap(), address, false); if (!labels.isEmpty()) { return labels.iterator().next(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DebuggerPlatformOpinion.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DebuggerPlatformOpinion.java index 96bc9c4e9e..b41aa425ed 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DebuggerPlatformOpinion.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DebuggerPlatformOpinion.java @@ -22,7 +22,7 @@ import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; -import ghidra.trace.model.target.iface.TraceObjectEnvironment; +import ghidra.trace.model.target.iface.TraceEnvironment; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; import ghidra.util.Msg; @@ -67,7 +67,7 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint { } TraceObject root = object.getRoot(); KeyPath pathToEnv = root.getSchema() - .searchForSuitable(TraceObjectEnvironment.class, object.getCanonicalPath()); + .searchForSuitable(TraceEnvironment.class, object.getCanonicalPath()); if (pathToEnv == null) { return null; } @@ -86,15 +86,15 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint { } static String getDebugggerFromEnv(TraceObject env, long snap) { - return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_DEBUGGER); + return getStringAttribute(env, snap, TraceEnvironment.KEY_DEBUGGER); } static String getArchitectureFromEnv(TraceObject env, long snap) { - return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_ARCH); + return getStringAttribute(env, snap, TraceEnvironment.KEY_ARCH); } static String getOperatingSystemFromEnv(TraceObject env, long snap) { - return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_OS); + return getStringAttribute(env, snap, TraceEnvironment.KEY_OS); } /** @@ -105,7 +105,7 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint { * @return the endianness, or null */ static Endian getEndianFromEnv(TraceObject env, long snap) { - String strEndian = getStringAttribute(env, snap, TraceObjectEnvironment.KEY_ENDIAN); + String strEndian = getStringAttribute(env, snap, TraceEnvironment.KEY_ENDIAN); if (strEndian == null) { return null; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/BreakpointActionSet.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/BreakpointActionSet.java index dd40e734da..5b7dbd7623 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/BreakpointActionSet.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/BreakpointActionSet.java @@ -20,7 +20,7 @@ import java.util.concurrent.CompletableFuture; import ghidra.async.AsyncFence; import ghidra.debug.api.target.Target; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; /** * A de-duplicated collection of breakpoint action items necessary to implement a logical breakpoint @@ -37,11 +37,12 @@ public class BreakpointActionSet extends LinkedHashSet { * Add an item to enable a target breakpoint * * @param target the target - * @param bpt the target breakpoint + * @param loc the target breakpoint * @return the added item */ - public EnableTargetBreakpointActionItem planEnableTarget(Target target, TraceBreakpoint bpt) { - EnableTargetBreakpointActionItem action = new EnableTargetBreakpointActionItem(target, bpt); + public EnableTargetBreakpointActionItem planEnableTarget(Target target, + TraceBreakpointLocation loc) { + EnableTargetBreakpointActionItem action = new EnableTargetBreakpointActionItem(target, loc); add(action); return action; } @@ -49,12 +50,12 @@ public class BreakpointActionSet extends LinkedHashSet { /** * Add an item to enable an emulated breakpoint * - * @param bpt the trace breakpoint + * @param loc the trace breakpoint * @param snap the snap * @return the added item */ - public EnableEmuBreakpointActionItem planEnableEmu(TraceBreakpoint bpt, long snap) { - EnableEmuBreakpointActionItem action = new EnableEmuBreakpointActionItem(bpt, snap); + public EnableEmuBreakpointActionItem planEnableEmu(TraceBreakpointLocation loc, long snap) { + EnableEmuBreakpointActionItem action = new EnableEmuBreakpointActionItem(loc, snap); add(action); return action; } @@ -63,12 +64,13 @@ public class BreakpointActionSet extends LinkedHashSet { * Add an item to disable a target breakpoint * * @param target the target - * @param bpt the target breakpoint + * @param loc the target breakpoint * @return the added item */ - public DisableTargetBreakpointActionItem planDisableTarget(Target target, TraceBreakpoint bpt) { + public DisableTargetBreakpointActionItem planDisableTarget(Target target, + TraceBreakpointLocation loc) { DisableTargetBreakpointActionItem action = - new DisableTargetBreakpointActionItem(target, bpt); + new DisableTargetBreakpointActionItem(target, loc); add(action); return action; } @@ -76,12 +78,12 @@ public class BreakpointActionSet extends LinkedHashSet { /** * Add an item to disable an emulated breakpoint * - * @param bpt the trace breakpoint + * @param loc the trace breakpoint * @param snap the snap * @return the added item */ - public DisableEmuBreakpointActionItem planDisableEmu(TraceBreakpoint bpt, long snap) { - DisableEmuBreakpointActionItem action = new DisableEmuBreakpointActionItem(bpt, snap); + public DisableEmuBreakpointActionItem planDisableEmu(TraceBreakpointLocation loc, long snap) { + DisableEmuBreakpointActionItem action = new DisableEmuBreakpointActionItem(loc, snap); add(action); return action; } @@ -90,11 +92,12 @@ public class BreakpointActionSet extends LinkedHashSet { * Add an item to delete a target breakpoint * * @param target the target - * @param bpt the target breakpoint + * @param loc the target breakpoint * @return the added item */ - public DeleteTargetBreakpointActionItem planDeleteTarget(Target target, TraceBreakpoint bpt) { - DeleteTargetBreakpointActionItem action = new DeleteTargetBreakpointActionItem(target, bpt); + public DeleteTargetBreakpointActionItem planDeleteTarget(Target target, + TraceBreakpointLocation loc) { + DeleteTargetBreakpointActionItem action = new DeleteTargetBreakpointActionItem(target, loc); add(action); return action; } @@ -102,12 +105,12 @@ public class BreakpointActionSet extends LinkedHashSet { /** * Add an item to delete an emulated breakpoint * - * @param bpt the trace breakpoint + * @param loc the trace breakpoint * @param snap the snap * @return the added item */ - public DeleteEmuBreakpointActionItem planDeleteEmu(TraceBreakpoint bpt, long snap) { - DeleteEmuBreakpointActionItem action = new DeleteEmuBreakpointActionItem(bpt, snap); + public DeleteEmuBreakpointActionItem planDeleteEmu(TraceBreakpointLocation loc, long snap) { + DeleteEmuBreakpointActionItem action = new DeleteEmuBreakpointActionItem(loc, snap); add(action); return action; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServicePlugin.java index 0a13b21440..bc16fa77b6 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServicePlugin.java @@ -45,15 +45,13 @@ import ghidra.framework.model.*; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.annotation.AutoServiceConsumed; import ghidra.framework.plugintool.util.PluginStatus; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRange; +import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.util.*; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.program.TraceProgramView; -import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceEvents; import ghidra.util.Msg; import ghidra.util.datastruct.ListenerSet; @@ -228,7 +226,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin info.reloadBreakpoints(c); } - private void breakpointAdded(TraceBreakpoint tb) { + private void breakpointAdded(TraceBreakpointLocation tb) { if (!tb.isValid(info.snap)) { return; } @@ -241,7 +239,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } } - private void breakpointChanged(TraceBreakpoint tb) { + private void breakpointChanged(TraceBreakpointLocation tb) { if (!tb.isValid(info.snap)) { return; } @@ -258,8 +256,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } } - private void breakpointLifespanChanged(TraceAddressSpace spaceIsNull, TraceBreakpoint tb, - Lifespan oldSpan, Lifespan newSpan) { + private void breakpointLifespanChanged(AddressSpace spaceIsNull, + TraceBreakpointLocation tb, Lifespan oldSpan, Lifespan newSpan) { // NOTE: User/script probably modified historical breakpoint boolean isInOld = oldSpan.contains(info.snap); boolean isInNew = newSpan.contains(info.snap); @@ -280,7 +278,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } } - private void breakpointDeleted(TraceBreakpoint tb) { + private void breakpointDeleted(TraceBreakpointLocation tb) { // Could check snap, but might as well just be sure it's gone info.forgetTraceBreakpoint(c.r, tb); } @@ -360,7 +358,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin long length, Collection kinds); protected LogicalBreakpointInternal getOrCreateLogicalBreakpointFor(AddCollector a, - Address address, TraceBreakpoint tb, long snap) throws TrackedTooSoonException { + Address address, TraceBreakpointLocation tb, long snap) + throws TrackedTooSoonException { Set set = logicalByAddress.computeIfAbsent(address, __ -> new HashSet<>()); for (LogicalBreakpointInternal lb : set) { @@ -377,7 +376,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } protected boolean removeLogicalBreakpoint(Address address, LogicalBreakpoint lb) { - for (TraceBreakpoint tb : lb.getTraceBreakpoints()) { + for (TraceBreakpointLocation tb : lb.getTraceBreakpoints()) { InfoPerTrace info = traceInfos.get(tb.getTrace()); if (info != null) { info.logicalByBreakpoint.remove(tb); @@ -435,7 +434,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } protected class InfoPerTrace extends AbstractInfo { - final Map logicalByBreakpoint = new HashMap<>(); + final Map logicalByBreakpoint = + new HashMap<>(); final Trace trace; final TraceBreakpointsListener breakpointListener; @@ -486,12 +486,12 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } protected void forgetAllBreakpoints(RemoveCollector r) { - Collection toForget = new ArrayList<>(); + Collection toForget = new ArrayList<>(); for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) { toForget.addAll( trace.getBreakpointManager().getBreakpointsIntersecting(Lifespan.ALL, range)); } - for (TraceBreakpoint tb : toForget) { + for (TraceBreakpointLocation tb : toForget) { forgetTraceBreakpoint(r, tb); } } @@ -504,16 +504,16 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin */ ControlMode mode = getMode(trace); - for (Entry ent : Set + for (Entry ent : Set .copyOf(logicalByBreakpoint.entrySet())) { - TraceBreakpoint tb = ent.getKey(); + TraceBreakpointLocation tb = ent.getKey(); LogicalBreakpoint lb = ent.getValue(); if (!mode.useEmulatedBreakpoints() && (target == null || !target.isBreakpointValid(tb))) { forgetTraceBreakpoint(r, tb); continue; } - if (!trace.getBreakpointManager().getAllBreakpoints().contains(tb)) { + if (!trace.getBreakpointManager().getAllBreakpointLocations().contains(tb)) { forgetTraceBreakpoint(r, tb); continue; } @@ -536,7 +536,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin if (!mode.useEmulatedBreakpoints() && target == null) { return; } - Collection visible = new ArrayList<>(); + Collection visible = new ArrayList<>(); for (AddressRange range : trace.getBaseAddressFactory().getAddressSet()) { visible.addAll(trace.getBreakpointManager() .getBreakpointsIntersecting(Lifespan.at(snap), range)); @@ -545,8 +545,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } protected void trackTraceBreakpoints(AddCollector a, - Collection breakpoints, ControlMode mode) { - for (TraceBreakpoint tb : breakpoints) { + Collection breakpoints, ControlMode mode) { + for (TraceBreakpointLocation tb : breakpoints) { try { /** * Sadly, even something as simple as toggling a breakpoint can cause so many @@ -562,7 +562,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } } - protected ProgramLocation computeStaticLocation(TraceBreakpoint tb) { + protected ProgramLocation computeStaticLocation(TraceBreakpointLocation tb) { if (traceManager == null || !traceManager.getOpenTraces().contains(tb.getTrace())) { /** * Mapping service will throw an exception otherwise. NB: When trace is opened, @@ -579,7 +579,8 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin new DefaultTraceLocation(trace, null, Lifespan.at(snap), minAddress)); } - protected void trackTraceBreakpoint(AddCollector a, TraceBreakpoint tb, ControlMode mode, + protected void trackTraceBreakpoint(AddCollector a, TraceBreakpointLocation tb, + ControlMode mode, boolean forceUpdate) throws TrackedTooSoonException { if (!mode.useEmulatedBreakpoints() && (target == null || !target.isBreakpointValid(tb))) { @@ -607,7 +608,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } protected LogicalBreakpointInternal removeFromLogicalBreakpoint(RemoveCollector r, - TraceBreakpoint tb) { + TraceBreakpointLocation tb) { LogicalBreakpointInternal lb = logicalByBreakpoint.remove(tb); if (lb == null || !lb.untrackBreakpoint(tb)) { return null; @@ -624,7 +625,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin return lb; } - protected void forgetTraceBreakpoint(RemoveCollector r, TraceBreakpoint tb) { + protected void forgetTraceBreakpoint(RemoveCollector r, TraceBreakpointLocation tb) { LogicalBreakpointInternal lb = removeFromLogicalBreakpoint(r, tb); if (lb == null) { return; // Warnings already logged @@ -1114,7 +1115,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } @Override - public LogicalBreakpoint getBreakpoint(TraceBreakpoint bpt) { + public LogicalBreakpoint getBreakpoint(TraceBreakpointLocation bpt) { Trace trace = bpt.getTrace(); synchronized (lock) { InfoPerTrace info = traceInfos.get(trace); @@ -1271,18 +1272,18 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } interface TargetBreakpointConsumer { - void accept(BreakpointActionSet actions, Target target, TraceBreakpoint tb); + void accept(BreakpointActionSet actions, Target target, TraceBreakpointLocation tb); } interface EmuBreakpointConsumer { - void accept(BreakpointActionSet actions, TraceBreakpoint tb, long snap); + void accept(BreakpointActionSet actions, TraceBreakpointLocation tb, long snap); } interface ProgramBreakpointConsumer { void accept(LogicalBreakpoint lb); } - private void planActOnLoc(BreakpointActionSet actions, TraceBreakpoint tb, + private void planActOnLoc(BreakpointActionSet actions, TraceBreakpointLocation tb, TargetBreakpointConsumer targetBptConsumer, EmuBreakpointConsumer emuLocConsumer) { ControlMode mode = getMode(tb.getTrace()); if (mode.useEmulatedBreakpoints()) { @@ -1293,7 +1294,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } } - private void planActOnLocTarget(BreakpointActionSet actions, TraceBreakpoint tb, + private void planActOnLocTarget(BreakpointActionSet actions, TraceBreakpointLocation tb, TargetBreakpointConsumer targetBptConsumer) { Target target = targetService == null ? null : targetService.getTarget(tb.getTrace()); if (target == null) { @@ -1302,7 +1303,7 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin targetBptConsumer.accept(actions, target, tb); } - private void planActOnLocEmu(BreakpointActionSet actions, TraceBreakpoint tb, + private void planActOnLocEmu(BreakpointActionSet actions, TraceBreakpointLocation tb, EmuBreakpointConsumer emuLocConsumer) { InfoPerTrace info = traceInfos.get(tb.getTrace()); if (info == null) { @@ -1312,12 +1313,12 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin emuLocConsumer.accept(actions, tb, info.snap); } - protected CompletableFuture actOnLocs(Collection col, + protected CompletableFuture actOnLocs(Collection col, TargetBreakpointConsumer targetBptConsumer, EmuBreakpointConsumer emuLocConsumer, ProgramBreakpointConsumer progConsumer) { BreakpointActionSet actions = new BreakpointActionSet(); - for (TraceBreakpoint tb : col) { + for (TraceBreakpointLocation tb : col) { LogicalBreakpoint lb = getBreakpoint(tb); if (col.containsAll(lb.getTraceBreakpoints())) { progConsumer.accept(lb); @@ -1328,19 +1329,19 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin } @Override - public CompletableFuture enableLocs(Collection col) { + public CompletableFuture enableLocs(Collection col) { return actOnLocs(col, BreakpointActionSet::planEnableTarget, BreakpointActionSet::planEnableEmu, LogicalBreakpoint::enableForProgram); } @Override - public CompletableFuture disableLocs(Collection col) { + public CompletableFuture disableLocs(Collection col) { return actOnLocs(col, BreakpointActionSet::planDisableTarget, BreakpointActionSet::planDisableEmu, LogicalBreakpoint::disableForProgram); } @Override - public CompletableFuture deleteLocs(Collection col) { + public CompletableFuture deleteLocs(Collection col) { return actOnLocs(col, BreakpointActionSet::planDeleteTarget, BreakpointActionSet::planDeleteEmu, lb -> { // Never delete bookmark when user requests deleting locations diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteEmuBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteEmuBreakpointActionItem.java index f4132a638c..4fbc74d8eb 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteEmuBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteEmuBreakpointActionItem.java @@ -19,20 +19,20 @@ import java.util.concurrent.CompletableFuture; import db.Transaction; import ghidra.async.AsyncUtils; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; -public record DeleteEmuBreakpointActionItem(TraceBreakpoint bpt, long snap) +public record DeleteEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap) implements BreakpointActionItem { @Override public CompletableFuture execute() { try (Transaction tx = - bpt.getTrace().openTransaction("Delete Emulated Breakpoint")) { - String emuName = PlaceEmuBreakpointActionItem.createName(bpt.getMinAddress(snap)); - if (bpt.getPath().contains(emuName)) { - bpt.delete(); + loc.getTrace().openTransaction("Delete Emulated Breakpoint")) { + String emuName = PlaceEmuBreakpointActionItem.createName(loc.getMinAddress(snap)); + if (loc.getPath().contains(emuName)) { + loc.delete(); } else { - bpt.setEmuEnabled(snap, false); + loc.setEmuEnabled(snap, false); } } return AsyncUtils.nil(); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteTargetBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteTargetBreakpointActionItem.java index 4c863bce0e..a6cb0dce5a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteTargetBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DeleteTargetBreakpointActionItem.java @@ -4,9 +4,9 @@ * 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. @@ -18,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint; import java.util.concurrent.CompletableFuture; import ghidra.debug.api.target.Target; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; -public record DeleteTargetBreakpointActionItem(Target target, TraceBreakpoint bpt) +public record DeleteTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc) implements BreakpointActionItem { @Override public CompletableFuture execute() { - return target.deleteBreakpointAsync(bpt); + return target.deleteBreakpointAsync(loc); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableEmuBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableEmuBreakpointActionItem.java index 742b084f27..ead4617d5f 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableEmuBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableEmuBreakpointActionItem.java @@ -19,15 +19,15 @@ import java.util.concurrent.CompletableFuture; import db.Transaction; import ghidra.async.AsyncUtils; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; -public record DisableEmuBreakpointActionItem(TraceBreakpoint bpt, long snap) +public record DisableEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap) implements BreakpointActionItem { @Override public CompletableFuture execute() { try (Transaction tx = - bpt.getTrace().openTransaction("Disable Emulated Breakpoint")) { - bpt.setEmuEnabled(snap, false); + loc.getTrace().openTransaction("Disable Emulated Breakpoint")) { + loc.setEmuEnabled(snap, false); } return AsyncUtils.nil(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableTargetBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableTargetBreakpointActionItem.java index 6ae89b6400..b6d1ce6145 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableTargetBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/DisableTargetBreakpointActionItem.java @@ -4,9 +4,9 @@ * 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. @@ -18,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint; import java.util.concurrent.CompletableFuture; import ghidra.debug.api.target.Target; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; -public record DisableTargetBreakpointActionItem(Target target, TraceBreakpoint bpt) +public record DisableTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc) implements BreakpointActionItem { @Override public CompletableFuture execute() { - return target.toggleBreakpointAsync(bpt, false); + return target.toggleBreakpointAsync(loc, false); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableEmuBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableEmuBreakpointActionItem.java index 24a59242cf..e0ee60eed1 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableEmuBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableEmuBreakpointActionItem.java @@ -19,15 +19,15 @@ import java.util.concurrent.CompletableFuture; import db.Transaction; import ghidra.async.AsyncUtils; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; -public record EnableEmuBreakpointActionItem(TraceBreakpoint bpt, long snap) +public record EnableEmuBreakpointActionItem(TraceBreakpointLocation loc, long snap) implements BreakpointActionItem { @Override public CompletableFuture execute() { try (Transaction tx = - bpt.getTrace().openTransaction("Enable Emulated Breakpoint")) { - bpt.setEmuEnabled(snap, true); + loc.getTrace().openTransaction("Enable Emulated Breakpoint")) { + loc.setEmuEnabled(snap, true); } return AsyncUtils.nil(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableTargetBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableTargetBreakpointActionItem.java index 556d049c96..7bec50d87f 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableTargetBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/EnableTargetBreakpointActionItem.java @@ -4,9 +4,9 @@ * 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. @@ -18,12 +18,12 @@ package ghidra.app.plugin.core.debug.service.breakpoint; import java.util.concurrent.CompletableFuture; import ghidra.debug.api.target.Target; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; -public record EnableTargetBreakpointActionItem(Target target, TraceBreakpoint bpt) +public record EnableTargetBreakpointActionItem(Target target, TraceBreakpointLocation loc) implements BreakpointActionItem { @Override public CompletableFuture execute() { - return target.toggleBreakpointAsync(bpt, true); + return target.toggleBreakpointAsync(loc, true); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java index 1c5ce972aa..a66c4ba8a5 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LogicalBreakpointInternal.java @@ -21,7 +21,7 @@ import ghidra.program.model.address.Address; import ghidra.program.model.listing.Bookmark; import ghidra.program.model.listing.Program; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; public interface LogicalBreakpointInternal extends LogicalBreakpoint { /** @@ -60,13 +60,13 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint { * @return true if it can be aggregated. * @throws TrackedTooSoonException if the containing trace is still being added to the manager */ - boolean canMerge(TraceBreakpoint breakpoint, long snap) throws TrackedTooSoonException; + boolean canMerge(TraceBreakpointLocation breakpoint, long snap) throws TrackedTooSoonException; boolean trackBreakpoint(Bookmark bookmark); - boolean trackBreakpoint(TraceBreakpoint breakpoint); + boolean trackBreakpoint(TraceBreakpointLocation breakpoint); - boolean untrackBreakpoint(TraceBreakpoint breakpoint); + boolean untrackBreakpoint(TraceBreakpointLocation breakpoint); boolean untrackBreakpoint(Program program, Bookmark bookmark); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LoneLogicalBreakpoint.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LoneLogicalBreakpoint.java index 010d12b588..724cd1055f 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LoneLogicalBreakpoint.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/LoneLogicalBreakpoint.java @@ -27,8 +27,8 @@ import ghidra.program.model.listing.Bookmark; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { private final Set justThisTrace; @@ -111,12 +111,12 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public Set getTraceBreakpoints() { + public Set getTraceBreakpoints() { return breaks.getBreakpoints(); } @Override - public Set getTraceBreakpoints(Trace trace) { + public Set getTraceBreakpoints(Trace trace) { return breaks.getTrace() != trace ? Set.of() : getTraceBreakpoints(); } @@ -165,7 +165,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public State computeStateForLocation(TraceBreakpoint loc) { + public State computeStateForLocation(TraceBreakpointLocation loc) { if (!breaks.getBreakpoints().contains(loc)) { return State.NONE; } @@ -278,7 +278,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public boolean canMerge(TraceBreakpoint breakpoint, long snap) { + public boolean canMerge(TraceBreakpointLocation breakpoint, long snap) { if (!Objects.equals(kinds, breakpoint.getKinds(snap))) { return false; } @@ -291,7 +291,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public boolean trackBreakpoint(TraceBreakpoint breakpoint) { + public boolean trackBreakpoint(TraceBreakpointLocation breakpoint) { return breaks.add(breakpoint); } @@ -301,7 +301,7 @@ public class LoneLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public boolean untrackBreakpoint(TraceBreakpoint breakpoint) { + public boolean untrackBreakpoint(TraceBreakpointLocation breakpoint) { return breaks.remove(breakpoint); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/MappedLogicalBreakpoint.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/MappedLogicalBreakpoint.java index 8f533b2358..3de1052ca1 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/MappedLogicalBreakpoint.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/MappedLogicalBreakpoint.java @@ -28,8 +28,8 @@ import ghidra.program.model.listing.Bookmark; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { @@ -309,8 +309,8 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public Set getTraceBreakpoints() { - Set result = new HashSet<>(); + public Set getTraceBreakpoints() { + Set result = new HashSet<>(); synchronized (traceBreaks) { for (TraceBreakpointSet breaks : traceBreaks.values()) { result.addAll(breaks.getBreakpoints()); @@ -320,7 +320,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public Set getTraceBreakpoints(Trace trace) { + public Set getTraceBreakpoints(Trace trace) { TraceBreakpointSet breaks; synchronized (traceBreaks) { breaks = traceBreaks.get(trace); @@ -400,7 +400,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { return progMode.combineTrace(traceMode, Perspective.TRACE); } - protected TraceMode computeTraceModeForLocation(TraceBreakpoint loc) { + protected TraceMode computeTraceModeForLocation(TraceBreakpointLocation loc) { TraceBreakpointSet breaks; synchronized (traceBreaks) { breaks = traceBreaks.get(loc.getTrace()); @@ -412,7 +412,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public State computeStateForLocation(TraceBreakpoint loc) { + public State computeStateForLocation(TraceBreakpointLocation loc) { ProgramMode progMode = progBreak.computeMode(); TraceMode traceMode = computeTraceModeForLocation(loc); return progMode.combineTrace(traceMode, Perspective.TRACE); @@ -478,7 +478,8 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public boolean canMerge(TraceBreakpoint breakpoint, long snap) throws TrackedTooSoonException { + public boolean canMerge(TraceBreakpointLocation breakpoint, long snap) + throws TrackedTooSoonException { TraceBreakpointSet breaks; synchronized (traceBreaks) { breaks = traceBreaks.get(breakpoint.getTrace()); @@ -530,7 +531,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public boolean trackBreakpoint(TraceBreakpoint breakpoint) { + public boolean trackBreakpoint(TraceBreakpointLocation breakpoint) { TraceBreakpointSet breaks; synchronized (traceBreaks) { breaks = traceBreaks.get(breakpoint.getTrace()); @@ -556,7 +557,7 @@ public class MappedLogicalBreakpoint implements LogicalBreakpointInternal { } @Override - public boolean untrackBreakpoint(TraceBreakpoint breakpoint) { + public boolean untrackBreakpoint(TraceBreakpointLocation breakpoint) { TraceBreakpointSet breaks; synchronized (traceBreaks) { breaks = traceBreaks.get(breakpoint.getTrace()); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java index c8e3007c80..4a9bf27c93 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java @@ -26,7 +26,6 @@ import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.memory.TraceMemoryRegion; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; @@ -49,42 +48,37 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre this.emuSleigh = emuSleigh; } - private TraceObjectMemoryRegion findRegion() { + private TraceMemoryRegion findRegion() { TraceMemoryRegion region = trace.getMemoryManager().getRegionContaining(snap, address); if (region != null) { - return (TraceObjectMemoryRegion) region; + return region; } AddressSpace space = address.getAddressSpace(); Collection regionsInSpace = trace.getMemoryManager() .getRegionsIntersecting(Lifespan.at(snap), new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress())); if (!regionsInSpace.isEmpty()) { - return (TraceObjectMemoryRegion) regionsInSpace.iterator().next(); + return regionsInSpace.iterator().next(); } return null; } private TraceObject findBreakpointContainer() { - TraceObjectMemoryRegion region = findRegion(); + TraceMemoryRegion region = findRegion(); if (region == null) { throw new IllegalArgumentException("Address does not belong to a memory in the trace"); } - return region.getObject() - .findSuitableContainerInterface(TraceObjectBreakpointSpec.class); + return region.getObject().findSuitableContainerInterface(TraceBreakpointSpec.class); } private String computePath() { String name = createName(address); - if (Trace.isLegacy(trace)) { - return "Breakpoints[" + name + "]"; - } TraceObject container = findBreakpointContainer(); if (container == null) { throw new IllegalArgumentException( "Address is not associated with a breakpoint container"); } - PathFilter specFilter = - container.getSchema().searchFor(TraceObjectBreakpointSpec.class, true); + PathFilter specFilter = container.getSchema().searchFor(TraceBreakpointSpec.class, true); if (specFilter == null) { throw new IllegalArgumentException("Cannot find path to breakpoint specifications"); } @@ -94,7 +88,7 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre } PathFilter locFilter = container.getSchema() .getSuccessorSchema(specRelPath) - .searchFor(TraceObjectBreakpointLocation.class, true); + .searchFor(TraceBreakpointLocation.class, true); if (locFilter == null) { throw new IllegalArgumentException("Cannot find path to breakpoint locations"); } @@ -109,11 +103,11 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre public CompletableFuture execute() { try (Transaction tx = trace.openTransaction("Place Emulated Breakpoint")) { // Defaults with emuEnable=true - TraceBreakpoint bpt = trace.getBreakpointManager() + TraceBreakpointLocation loc = trace.getBreakpointManager() .addBreakpoint(computePath(), Lifespan.at(snap), BreakpointActionItem.range(address, length), Set.of(), kinds, false, null); - bpt.setName(snap, createName(address)); - bpt.setEmuSleigh(snap, emuSleigh); + loc.setName(snap, createName(address)); + loc.setEmuSleigh(snap, emuSleigh); return AsyncUtils.nil(); } catch (DuplicateNameException e) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/TraceBreakpointSet.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/TraceBreakpointSet.java index c91b59bb36..7ec7d7e8ac 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/TraceBreakpointSet.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/TraceBreakpointSet.java @@ -28,8 +28,8 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.pcode.exec.SleighUtils; import ghidra.program.model.address.Address; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import utilities.util.IDHashed; /** @@ -45,7 +45,7 @@ class TraceBreakpointSet { private final Trace trace; private final Address address; - private final Set> breakpoints = new HashSet<>(); + private final Set> breakpoints = new HashSet<>(); private Target target; private String emuSleigh; @@ -120,8 +120,8 @@ class TraceBreakpointSet { * *

* In most cases, there is 0 or 1 trace breakpoints that "fit" the logical breakpoint. The mode - * is derived from one of {@link TraceBreakpoint#isEnabled(long)} or - * {@link TraceBreakpoint#isEmuEnabled(long)}, depending on the UI's control mode for this + * is derived from one of {@link TraceBreakpointLocation#isEnabled(long)} or + * {@link TraceBreakpointLocation#isEmuEnabled(long)}, depending on the UI's control mode for this * trace. * * @return the mode @@ -130,7 +130,7 @@ class TraceBreakpointSet { TraceMode mode = TraceMode.NONE; synchronized (breakpoints) { if (getControlMode().useEmulatedBreakpoints()) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { mode = mode.combine(computeEmuMode(bpt.obj)); if (mode == TraceMode.MISSING) { return mode; @@ -138,7 +138,7 @@ class TraceBreakpointSet { } return mode; } - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { mode = mode.combine(computeTargetMode(bpt.obj)); if (mode == TraceMode.MISSING) { return mode; @@ -152,14 +152,14 @@ class TraceBreakpointSet { * Compute the mode (enablement) of the given breakpoint * *

- * The mode is derived from one of {@link TraceBreakpoint#isEnabled(long)} or - * {@link TraceBreakpoint#isEmuEnabled(long)}, depending on the UI's control mode for this + * The mode is derived from one of {@link TraceBreakpointLocation#isEnabled(long)} or + * {@link TraceBreakpointLocation#isEmuEnabled(long)}, depending on the UI's control mode for this * trace. * * @param bpt the breakpoint * @return the mode */ - public TraceMode computeMode(TraceBreakpoint bpt) { + public TraceMode computeMode(TraceBreakpointLocation bpt) { return getControlMode().useEmulatedBreakpoints() ? computeEmuMode(bpt) : computeTargetMode(bpt); @@ -171,7 +171,7 @@ class TraceBreakpointSet { * @param bpt the breakpoint * @return the mode */ - public TraceMode computeTargetMode(TraceBreakpoint bpt) { + public TraceMode computeTargetMode(TraceBreakpointLocation bpt) { return TraceMode.fromBool(bpt.isEnabled(getSnap())); } @@ -181,7 +181,7 @@ class TraceBreakpointSet { * @param bpt the breakpoint * @return the mode */ - public TraceMode computeEmuMode(TraceBreakpoint bpt) { + public TraceMode computeEmuMode(TraceBreakpointLocation bpt) { return TraceMode.fromBool(bpt.isEmuEnabled(getSnap())); } @@ -194,7 +194,7 @@ class TraceBreakpointSet { String sleigh = null; long snap = getSnap(); synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { String s = bpt.obj.getEmuSleigh(snap); if (sleigh != null && !sleigh.equals(s)) { return null; @@ -215,7 +215,7 @@ class TraceBreakpointSet { long snap = getSnap(); try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { bpt.obj.setEmuSleigh(snap, emuSleigh); } } @@ -238,7 +238,7 @@ class TraceBreakpointSet { * * @return the breakpoints */ - public Set getBreakpoints() { + public Set getBreakpoints() { synchronized (breakpoints) { return breakpoints.stream().map(e -> e.obj).collect(Collectors.toUnmodifiableSet()); } @@ -248,13 +248,13 @@ class TraceBreakpointSet { * Add a breakpoint to this set * *

- * The caller should first call {@link #canMerge(TraceBreakpoint)} to check if the breakpoint + * The caller should first call {@link #canMerge(TraceBreakpointLocation)} to check if the breakpoint * "fits." * * @param bpt the breakpoint * @return true if the set actually changed as a result */ - public boolean add(TraceBreakpoint bpt) { + public boolean add(TraceBreakpointLocation bpt) { long snap = getSnap(); if (SleighUtils.UNCONDITIONAL_BREAK.equals(bpt.getEmuSleigh(snap)) && emuSleigh != null) { try (Transaction tx = trace.openTransaction("Set breakpoint Sleigh")) { @@ -275,7 +275,7 @@ class TraceBreakpointSet { * @param bpt the breakpoint * @return true if it fits */ - public boolean canMerge(TraceBreakpoint bpt) { + public boolean canMerge(TraceBreakpointLocation bpt) { if (trace != bpt.getTrace()) { return false; } @@ -291,7 +291,7 @@ class TraceBreakpointSet { * @param bpt the breakpoint * @return true if the set actually changes as a result */ - public boolean remove(TraceBreakpoint bpt) { + public boolean remove(TraceBreakpointLocation bpt) { synchronized (breakpoints) { return breakpoints.remove(new IDHashed<>(bpt)); } @@ -359,7 +359,7 @@ class TraceBreakpointSet { private void planEnableTarget(BreakpointActionSet actions) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { actions.planEnableTarget(target, bpt.obj); } } @@ -367,7 +367,7 @@ class TraceBreakpointSet { private void planEnableEmu(BreakpointActionSet actions) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { actions.planEnableEmu(bpt.obj, getSnap()); } } @@ -393,7 +393,7 @@ class TraceBreakpointSet { private void planDisableTarget(BreakpointActionSet actions, long length, Collection kinds) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { actions.planDisableTarget(target, bpt.obj); } } @@ -401,7 +401,7 @@ class TraceBreakpointSet { private void planDisableEmu(BreakpointActionSet actions) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { actions.planDisableEmu(bpt.obj, getSnap()); } } @@ -427,7 +427,7 @@ class TraceBreakpointSet { private void planDeleteTarget(BreakpointActionSet actions, long length, Set kinds) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { actions.planDeleteTarget(target, bpt.obj); } } @@ -435,7 +435,7 @@ class TraceBreakpointSet { private void planDeleteEmu(BreakpointActionSet actions) { synchronized (breakpoints) { - for (IDHashed bpt : breakpoints) { + for (IDHashed bpt : breakpoints) { actions.planDeleteEmu(bpt.obj, getSnap()); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java index 4e798c5837..e676146445 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java @@ -18,7 +18,7 @@ package ghidra.app.plugin.core.debug.service.emulation; import java.io.IOException; import java.util.*; import java.util.Map.Entry; -import java.util.concurrent.CompletableFuture; +import java.util.concurrent.*; import java.util.stream.Collectors; import javax.swing.Icon; @@ -45,6 +45,7 @@ import ghidra.async.AsyncLazyMap; import ghidra.debug.api.control.ControlMode; import ghidra.debug.api.emulation.DebuggerPcodeEmulatorFactory; import ghidra.debug.api.emulation.DebuggerPcodeMachine; +import ghidra.debug.api.modules.DebuggerStaticMappingChangeListener; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.annotation.AutoServiceConsumed; @@ -638,7 +639,7 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm Lifespan span = Lifespan.at(snap); TraceBreakpointManager bm = trace.getBreakpointManager(); for (AddressSpace as : trace.getBaseAddressFactory().getAddressSpaces()) { - for (TraceBreakpoint bpt : bm.getBreakpointsIntersecting(span, + for (TraceBreakpointLocation bpt : bm.getBreakpointsIntersecting(span, new AddressRangeImpl(as.getMinAddress(), as.getMaxAddress()))) { if (!bpt.isEmuEnabled(snap)) { continue; @@ -797,14 +798,43 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm } } + class TraceMappingWaiter extends CompletableFuture + implements DebuggerStaticMappingChangeListener { + private final Trace trace; + + public TraceMappingWaiter(Trace trace) { + this.trace = trace; + } + + @Override + public void mappingsChanged(Set affectedTraces, Set affectedPrograms) { + if (affectedTraces.contains(trace)) { + complete(null); + } + } + + public void softWait() { + try { + get(1, TimeUnit.SECONDS); + } + catch (InterruptedException | ExecutionException | TimeoutException e) { + Msg.warn(this, "Mappings not reported by service after 1 second"); + } + } + } + @Override public Trace launchProgram(Program program, Address address) throws IOException { Trace trace = null; try { trace = ProgramEmulationUtils.launchEmulationTrace(program, address, this); + trace.flushEvents(); + + TraceMappingWaiter waiter = new TraceMappingWaiter(trace); + staticMappings.addChangeListener(waiter); traceManager.openTrace(trace); traceManager.activateTrace(trace); - Swing.allowSwingToProcessEvents(); + waiter.softWait(); } finally { if (trace != null) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java index 226873b399..88d4400cc3 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java @@ -45,7 +45,8 @@ import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.path.*; import ghidra.trace.model.target.schema.*; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.thread.*; +import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.model.thread.TraceThreadManager; import ghidra.trace.model.time.TraceSnapshot; import ghidra.util.*; import ghidra.util.exception.DuplicateNameException; @@ -290,19 +291,13 @@ public class ProgramEmulationUtils { } public static PathPattern computePatternRegion(Trace trace) { - TraceObjectSchema root = trace.getObjectManager().getRootSchema(); - if (root == null) { - return PathFilter.parse("Memory[]"); - } - return computePattern(root, trace, TraceObjectMemoryRegion.class); + TraceObjectSchema root = trace.getObjectManager().requireRootSchema(); + return computePattern(root, trace, TraceMemoryRegion.class); } public static PathPattern computePatternThread(Trace trace) { - TraceObjectSchema root = trace.getObjectManager().getRootSchema(); - if (root == null) { - return PathFilter.parse("Threads[]"); - } - return computePattern(root, trace, TraceObjectThread.class); + TraceObjectSchema root = trace.getObjectManager().requireRootSchema(); + return computePattern(root, trace, TraceThread.class); } /** @@ -347,18 +342,16 @@ public class ProgramEmulationUtils { public static void initializeRegisters(Trace trace, long snap, TraceThread thread, Program program, Address tracePc, Address programPc, AddressRange stack) { TraceMemoryManager memory = trace.getMemoryManager(); - if (thread instanceof TraceObjectThread ot) { - TraceObject object = ot.getObject(); - PathFilter regsFilter = object.getRoot() - .getSchema() - .searchForRegisterContainer(0, object.getCanonicalPath()); - if (regsFilter.isNone()) { - throw new IllegalArgumentException("Cannot create register container"); - } - for (PathPattern regsPattern : regsFilter.getPatterns()) { - trace.getObjectManager().createObject(regsPattern.getSingletonPath()); - break; - } + TraceObject object = thread.getObject(); + PathFilter regsFilter = object.getRoot() + .getSchema() + .searchForRegisterContainer(0, object.getCanonicalPath()); + if (regsFilter.isNone()) { + throw new IllegalArgumentException("Cannot create register container"); + } + for (PathPattern regsPattern : regsFilter.getPatterns()) { + trace.getObjectManager().createObject(regsPattern.getSingletonPath()); + break; } TraceMemorySpace regSpace = memory.getMemoryRegisterSpace(thread, true); if (program != null) { @@ -606,7 +599,12 @@ public class ProgramEmulationUtils { throw new EmulatorOutOfMemoryException(); } - protected static void createObjects(Trace trace) { + /** + * Initialize a given emulation trace with some required/expected objects + * + * @param trace the trace + */ + public static void createObjects(Trace trace) { TraceObjectManager om = trace.getObjectManager(); om.createRootObject(EMU_SESSION_SCHEMA); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/target/AbstractTarget.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/target/AbstractTarget.java index 60b9c2e449..962b42280a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/target/AbstractTarget.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/target/AbstractTarget.java @@ -36,7 +36,7 @@ import ghidra.program.model.lang.RegisterValue; import ghidra.program.util.MarkerLocation; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.TraceSpan; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointCommon; import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.program.TraceProgramView; @@ -321,12 +321,12 @@ public abstract class AbstractTarget implements Target { } @Override - public void deleteBreakpoint(TraceBreakpoint breakpoint) { + public void deleteBreakpoint(TraceBreakpointCommon breakpoint) { runSync("delete breakpoint", () -> deleteBreakpointAsync(breakpoint)); } @Override - public void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled) { + public void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled) { String msg = enabled ? "enable breakpoint" : "disable breakpoint"; runSync(msg, () -> toggleBreakpointAsync(breakpoint, enabled)); } diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPluginScreenShots.java index 1617348166..254ed2f8af 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPluginScreenShots.java @@ -4,9 +4,9 @@ * 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. @@ -70,24 +70,16 @@ public class DebuggerListingPluginScreenShots extends GhidraScreenShotGenerator TraceSymbolManager symbolManager = tb.trace.getSymbolManager(); TraceNamespaceSymbol global = symbolManager.getGlobalNamespace(); - TraceSymbol mainLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400000), - "main", global, SourceType.USER_DEFINED); + TraceSymbol mainLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400000), "main", global, SourceType.USER_DEFINED); @SuppressWarnings("unused") - TraceSymbol cloneLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400060), - "clone", global, SourceType.USER_DEFINED); - TraceSymbol childLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400032), - "child", global, SourceType.USER_DEFINED); + TraceSymbol cloneLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400060), "clone", global, SourceType.USER_DEFINED); + TraceSymbol childLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400032), "child", global, SourceType.USER_DEFINED); @SuppressWarnings("unused") - TraceSymbol exitLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400061), - "exit", global, SourceType.USER_DEFINED); + TraceSymbol exitLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400061), "exit", global, SourceType.USER_DEFINED); Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView()); diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java index 0ebb04a075..db741fa970 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java @@ -4,9 +4,9 @@ * 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. @@ -72,24 +72,16 @@ public class DebuggerMemoryBytesPluginScreenShots extends GhidraScreenShotGenera TraceSymbolManager symbolManager = tb.trace.getSymbolManager(); TraceNamespaceSymbol global = symbolManager.getGlobalNamespace(); - TraceSymbol mainLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400000), - "main", global, SourceType.USER_DEFINED); + TraceSymbol mainLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400000), "main", global, SourceType.USER_DEFINED); @SuppressWarnings("unused") - TraceSymbol cloneLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400060), - "clone", global, SourceType.USER_DEFINED); - TraceSymbol childLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400034), - "child", global, SourceType.USER_DEFINED); + TraceSymbol cloneLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400060), "clone", global, SourceType.USER_DEFINED); + TraceSymbol childLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400034), "child", global, SourceType.USER_DEFINED); @SuppressWarnings("unused") - TraceSymbol exitLabel = symbolManager - .labels() - .create(snap, null, tb.addr(0x00400061), - "exit", global, SourceType.USER_DEFINED); + TraceSymbol exitLabel = symbolManager.labels() + .create(snap, tb.addr(0x00400061), "exit", global, SourceType.USER_DEFINED); Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView()); diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelPluginScreenShots.java index 830c23fddf..1229a9daa0 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelPluginScreenShots.java @@ -33,7 +33,7 @@ import ghidra.trace.database.target.DBTraceObjectValue; import ghidra.trace.model.Lifespan; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; -import ghidra.trace.model.target.iface.TraceObjectEventScope; +import ghidra.trace.model.target.iface.TraceEventScope; import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; @@ -180,7 +180,7 @@ public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator { proc.child("Modules"); } } - root.value(TraceObjectEventScope.KEY_EVENT_THREAD, l.thread); + root.value(TraceEventScope.KEY_EVENT_THREAD, l.thread); } traceManager.openTrace(tb.trace); diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperPluginScreenShots.java index f732fa1dc2..e6ea010052 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperPluginScreenShots.java @@ -4,9 +4,9 @@ * 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. @@ -29,7 +29,7 @@ import ghidra.test.ToyProgramBuilder; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemoryFlag; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule; import help.screenshot.GhidraScreenShotGenerator; @@ -66,7 +66,7 @@ public class DebuggerPcodeStepperPluginScreenShots extends GhidraScreenShotGener tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - TraceObjectThread thread = (TraceObjectThread) tb.getOrAddThread("Threads[1]", snap0); + TraceThread thread = tb.getOrAddThread("Threads[1]", snap0); tb.trace.getObjectManager() .createObject(thread.getObject().getCanonicalPath().key("Registers")); diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/platform/DebuggerPlatformPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/platform/DebuggerPlatformPluginScreenShots.java index d4ebbe5541..473b358468 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/platform/DebuggerPlatformPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/platform/DebuggerPlatformPluginScreenShots.java @@ -22,10 +22,6 @@ import db.Transaction; import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin; import ghidra.app.services.DebuggerTraceManagerService; import ghidra.trace.database.ToyDBTraceBuilder; -import ghidra.trace.database.target.DBTraceObjectManagerTest; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import help.screenshot.GhidraScreenShotGenerator; public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator { @@ -41,11 +37,9 @@ public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator @Test public void testCaptureDebuggerSelectPlatformOfferDialog() throws Throwable { - SchemaContext ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("echo", "DATA:BE:64:default")) { try (Transaction tx = tb.startTransaction()) { - tb.trace.getObjectManager() - .createRootObject(ctx.getSchema(new SchemaName("Session"))); + tb.createRootObject(); } traceManager.openTrace(tb.trace); traceManager.activateTrace(tb.trace); diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java index ef7c3fbd3a..78fd7180ff 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java @@ -45,7 +45,7 @@ import ghidra.trace.model.DefaultTraceLocation; import ghidra.trace.model.Lifespan; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.util.task.TaskMonitor; import help.screenshot.GhidraScreenShotGenerator; @@ -103,14 +103,10 @@ public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator sm.getSnapshot(13, true); DBTraceThreadManager tm = tb.trace.getThreadManager(); - TraceObjectThread t1 = - (TraceObjectThread) tm.addThread("Threads[1]", "main", Lifespan.nowOn(0)); - TraceObjectThread t2 = - (TraceObjectThread) tm.addThread("Threads[2]", "server", Lifespan.nowOn(2)); - TraceObjectThread t3 = - (TraceObjectThread) tm.addThread("Threads[3]", "handler 1", Lifespan.span(5, 10)); - TraceObjectThread t4 = - (TraceObjectThread) tm.addThread("Threads[4]", "handler 2", Lifespan.span(8, 13)); + TraceThread t1 = tm.addThread("Threads[1]", "main", Lifespan.nowOn(0)); + TraceThread t2 = tm.addThread("Threads[2]", "server", Lifespan.nowOn(2)); + TraceThread t3 = tm.addThread("Threads[3]", "handler 1", Lifespan.span(5, 10)); + TraceThread t4 = tm.addThread("Threads[4]", "handler 2", Lifespan.span(8, 13)); t1.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED"); t2.getObject().setValue(Lifespan.nowOn(0), "_state", "STOPPED"); diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesPluginScreenShots.java index 16a870a0df..a6bf3e56a3 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesPluginScreenShots.java @@ -4,9 +4,9 @@ * 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. @@ -62,7 +62,7 @@ public class DebuggerWatchesPluginScreenShots extends GhidraScreenShotGenerator tb.trace.getSymbolManager() .labels() - .create(snap1, null, tb.addr(0x7fff0004), "fiveUp", + .create(snap1, tb.addr(0x7fff0004), "fiveUp", tb.trace.getSymbolManager().getGlobalNamespace(), SourceType.USER_DEFINED); thread = tb.getOrAddThread("[1]", snap0); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/disassemble/DebuggerDisassemblyTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/disassemble/DebuggerDisassemblyTest.java index 39be632bfe..1d9296fd9b 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/disassemble/DebuggerDisassemblyTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/disassemble/DebuggerDisassemblyTest.java @@ -48,6 +48,7 @@ import ghidra.program.model.lang.*; import ghidra.program.model.listing.Instruction; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.listing.DBTraceInstruction; import ghidra.trace.database.listing.DBTraceInstructionsMemoryView; import ghidra.trace.database.memory.DBTraceMemoryManager; @@ -59,16 +60,16 @@ import ghidra.trace.model.Lifespan; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.memory.TraceMemoryFlag; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; +import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.program.TraceProgramView; -import ghidra.trace.model.stack.*; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject.ConflictResolution; -import ghidra.trace.model.target.iface.TraceObjectEnvironment; +import ghidra.trace.model.target.iface.TraceEnvironment; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.util.task.TaskMonitor; @@ -162,12 +163,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { sel, null); } - protected TraceObjectThread createPolyglotTrace(String arch, long offset, + protected TraceThread createPolyglotTrace(String arch, long offset, Supplier byteSupplier) throws Exception { return createPolyglotTrace(arch, offset, byteSupplier, true); } - protected TraceObjectThread createPolyglotTrace(String arch, long offset, + protected TraceThread createPolyglotTrace(String arch, long offset, Supplier byteSupplier, boolean pcInStack) throws Exception { createAndOpenTrace("DATA:BE:64:default"); @@ -179,13 +180,12 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { assertEquals(ctx.getSchema(new SchemaName("Environment")), env.getSchema()); Lifespan zeroOn = Lifespan.nowOn(0); env.insert(zeroOn, ConflictResolution.DENY); - env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_DEBUGGER, "test"); - env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_ARCH, arch); + env.setAttribute(zeroOn, TraceEnvironment.KEY_DEBUGGER, "test"); + env.setAttribute(zeroOn, TraceEnvironment.KEY_ARCH, arch); DBTraceObject objBinText = objects.createObject(KeyPath.parse("Targets[0].Memory[bin:.text]")); - TraceObjectMemoryRegion binText = - objBinText.queryInterface(TraceObjectMemoryRegion.class); + TraceMemoryRegion binText = objBinText.queryInterface(TraceMemoryRegion.class); binText.addFlags(zeroOn, Set.of(TraceMemoryFlag.EXECUTE)); binText.setRange(zeroOn, tb.range(offset, offset + 0xffff)); // TODO: Why doesn't setRange work after insert? @@ -196,16 +196,16 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { DBTraceObject objFrame = objects .createObject(KeyPath.parse("Targets[0].Threads[0].Stack[0]")); objFrame.insert(zeroOn, ConflictResolution.DENY); - TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class); + TraceStackFrame frame = objFrame.queryInterface(TraceStackFrame.class); frame.setProgramCounter(zeroOn, tb.addr(offset)); } else { objects.createObject( KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers")) .insert(zeroOn, ConflictResolution.DENY); - TraceObjectThread thread = objects - .getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]")) - .queryInterface(TraceObjectThread.class); + TraceThread thread = + objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]")) + .queryInterface(TraceThread.class); traceManager.activateThread(thread); DBTraceMemorySpace regs = Objects.requireNonNull(memory.getMemoryRegisterSpace(thread, true)); @@ -218,14 +218,14 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { ByteBuffer bytes = byteSupplier.get(); assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes)); } - TraceObjectThread thread = + TraceThread thread = objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]")) - .queryInterface(TraceObjectThread.class); + .queryInterface(TraceThread.class); traceManager.activateThread(thread); return thread; } - protected void setLegacyProgramCounterInStack(long offset, TraceThread thread, long snap) { + protected void setProgramCounterInStack(long offset, TraceThread thread, long snap) { try (Transaction tx = tb.startTransaction()) { DBTraceStackManager manager = tb.trace.getStackManager(); TraceStack stack = manager.getStack(thread, snap, true); @@ -234,7 +234,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { } } - protected void setLegacyProgramCounterInRegs(long offset, TraceThread thread, long snap) { + protected void setProgramCounterInRegs(long offset, TraceThread thread, long snap) { try (Transaction tx = tb.startTransaction()) { DBTraceMemoryManager memory = tb.trace.getMemoryManager(); DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); @@ -243,11 +243,19 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { } } - protected void createLegacyTrace(String langID, long offset, Supplier byteSupplier) + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + + protected void createTrace(String langID, long offset, Supplier byteSupplier) throws Throwable { createAndOpenTrace(langID); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); memory.createRegion("Memory[bin:.text]", 0, tb.range(offset, offset + 0xffff), Set.of(TraceMemoryFlag.EXECUTE, TraceMemoryFlag.READ)); @@ -275,27 +283,27 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testAutoDisasembleReDisasembleX8664Offcut() throws Throwable { enableAutoDisassembly(); - createLegacyTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0)); + createTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0)); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); } - setLegacyProgramCounterInStack(0x00400000, thread, 0); + setProgramCounterInStack(0x00400000, thread, 0); waitForPass(() -> { DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions(); assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000))); /** * Depending on preference for branch or fall-through, the disassembler may or may not - * proceed to the following instructions. I don't really care, since the test is that the - * JMP gets deleted after the update to PC. + * proceed to the following instructions. I don't really care, since the test is that + * the JMP gets deleted after the update to PC. */ }); // The jump will advance one byte. Just simulate that by updating the stack and/or regs - setLegacyProgramCounterInStack(0x00400001, thread, 1); + setProgramCounterInStack(0x00400001, thread, 1); traceManager.activateSnap(1); waitForPass(() -> { @@ -310,22 +318,23 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { public void testAutoDisassembleReDisassembleX8664OffcutByEmulation() throws Throwable { DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class); enableAutoDisassembly(); - createLegacyTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0)); + createTrace("x86:LE:64:default", 0x00400000, () -> tb.buf(0xeb, 0xff, 0xc0)); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); } - setLegacyProgramCounterInRegs(0x00400000, thread, 0); + setProgramCounterInRegs(0x00400000, thread, 0); waitForPass(() -> { DBTraceInstructionsMemoryView instructions = tb.trace.getCodeManager().instructions(); assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000))); /** * Depending on preference for branch or fall-through, the disassembler may or may not - * proceed to the following instructions. I don't really care, since the test is that the - * JMP gets deleted after the update to PC. + * proceed to the following instructions. I don't really care, since the test is that + * the JMP gets deleted after the update to PC. */ }); @@ -374,8 +383,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { assertMnemonic("JMP", instructions.getAt(0, tb.addr(0x00400000))); /** * Depending on preference for branch or fall-through, the disassembler may or may not - * proceed to the following instructions. I don't really care, since the test is that the - * JMP gets deleted after the update to PC. + * proceed to the following instructions. I don't really care, since the test is that + * the JMP gets deleted after the update to PC. */ }); @@ -411,12 +420,13 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testCurrentDisassembleActionHostArm() throws Throwable { - createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); + createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); // Fabricate the cpsr so that ARM is used. Otherwise, it will assume Cortex-M, so THUMB TraceThread thread; try (Transaction tx = tb.startTransaction()) { thread = tb.getOrAddThread("Threads[0]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); DBTraceMemorySpace regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(tb.language.getRegister("cpsr"), BigInteger.ZERO)); @@ -442,12 +452,13 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testCurrentDisassembleActionHostThumb() throws Throwable { - createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x70, 0x47)); + createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x70, 0x47)); // Fabricate the cpsr so that THUMB is used, even though we could omit as in Cortex-M TraceThread thread; try (Transaction tx = tb.startTransaction()) { thread = tb.getOrAddThread("Threads[0]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); DBTraceMemorySpace regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); regs.setValue(0, @@ -474,7 +485,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testCurrentDisassembleActionGuestArm() throws Throwable { - TraceObjectThread thread = + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); traceManager.activateThread(thread); waitForSwing(); @@ -510,7 +521,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testCurrentDisassembleActionGuestThumb() throws Throwable { - TraceObjectThread thread = + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47)); traceManager.activateThread(thread); waitForSwing(); @@ -557,7 +568,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testFixedDisassembleActionsHostArm() throws Throwable { - createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); + createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); Address start = tb.addr(0x00400000); // Ensure the mapper is added to the trace @@ -573,7 +584,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testFixedDisassembleActionsGuestArm() throws Throwable { - TraceObjectThread thread = + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x1e, 0xff, 0x2f, 0xe1)); Address start = tb.addr(0x00400000); @@ -590,7 +601,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { @Test public void testFixedDisassembleActionsGuestThumb() throws Throwable { - TraceObjectThread thread = + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x70, 0x47)); Address start = tb.addr(0x00400000); @@ -610,7 +621,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { // Assemble actions will think read-only otherwise DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); - createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00)); + createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00)); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); @@ -638,7 +649,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); // Don't cheat here and choose v8T! - createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00)); + createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf(0x00, 0x00)); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); @@ -669,7 +680,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { // Assemble actions will think read-only otherwise DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); - TraceObjectThread thread = + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00, 0x00, 0x00)); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); @@ -699,7 +710,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { // Assemble actions will think read-only otherwise DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); - TraceObjectThread thread = + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf(0x00, 0x00)); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); @@ -749,7 +760,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { // Assemble actions will think read-only otherwise DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); - createLegacyTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf()); + createTrace("ARM:LE:32:v8", 0x00400000, () -> tb.buf()); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); @@ -768,7 +779,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { // Assemble actions will think read-only otherwise DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); - TraceObjectThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf()); + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf()); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); @@ -787,7 +798,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest { // Assemble actions will think read-only otherwise DebuggerControlService controlService = addPlugin(tool, DebuggerControlServicePlugin.class); - TraceObjectThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf()); + TraceThread thread = createPolyglotTrace("armv8le", 0x00400000, () -> tb.buf()); Address start = tb.addr(0x00400000); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlanTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlanTest.java index 3e3bf474eb..e0dd857e87 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlanTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyPlanTest.java @@ -34,8 +34,6 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.copying.DebuggerCopyPlan.AllCopiers; import ghidra.app.util.viewer.listingpanel.PropertyBasedBackgroundColorModel; import ghidra.program.database.IntRangeMap; -import ghidra.program.disassemble.Disassembler; -import ghidra.program.disassemble.DisassemblerMessageListener; import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.lang.Register; @@ -75,9 +73,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { byte src[] = new byte[0x10000]; r.nextBytes(src); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.wrap(src)); } @@ -107,9 +106,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.STATE.isAvailable(view, program)); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.putBytes(0, tb.addr(0x55550000), ByteBuffer.allocate(4096)); memory.setState(0, tb.addr(0x55551000), TraceMemoryState.ERROR); } @@ -182,10 +182,14 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { AddressRange trng = tb.range(0x55550000, 0x5555ffff); Assembler asm = Assemblers.getAssembler(view); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - InstructionIterator iit = - asm.assemble(tb.addr(0x55550000), "imm r0, #123", "imm r1, #234", "add r0, r1"); + memory.createRegion("Memory[.text]", 0, trng, + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + InstructionIterator iit = asm.assemble(tb.addr(0x55550000), + "imm r0, #123", + "imm r1, #234", + "add r0, r1"); assertTrue(iit.hasNext()); } @@ -228,10 +232,14 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { AddressRange trng = tb.range(0x55550000, 0x5555ffff); Assembler asm = Assemblers.getAssembler(view); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - InstructionIterator iit = - asm.assemble(tb.addr(0x55550000), "MOV RAX, 1234", "MOV RCX, 2345", "ADD RAX, RCX"); + memory.createRegion("Memory[.text]", 0, trng, + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + InstructionIterator iit = asm.assemble(tb.addr(0x55550000), + "MOV RAX, 1234", + "MOV RCX, 2345", + "ADD RAX, RCX"); assertTrue(iit.hasNext()); } @@ -272,7 +280,7 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.INSTRUCTIONS.isAvailable(view, program)); AddressRange trng = tb.range(0x55550000, 0x5555ffff); - // Assembler asm = Assemblers.getAssembler(view); + Assembler asm = Assemblers.getAssembler(view); Register contextReg = tb.language.getContextBaseRegister(); Register longMode = tb.language.getRegister("longMode"); @@ -281,26 +289,17 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { rv = rv.assign(longMode, BigInteger.ZERO); Instruction checkCtx; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, trng, + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); tb.trace.getRegisterContextManager().setValue(tb.language, rv, Lifespan.nowOn(0), trng); - // TODO: Once GP-1426 is resolved, use the assembler - /* InstructionIterator iit = asm.assemble(tb.addr(0x55550000), "MOV EAX, 1234", "MOV ECX, 2345", "ADD EAX, ECX"); checkCtx = iit.next(); - */ - memory.putBytes(0, tb.addr(0x55550000), tb.buf(0xb8, 0xd2, 0x04, 0x00, 0x00, // MOV EAX,1234 - 0xb9, 0x29, 0x09, 0x00, 0x00, // MOV ECX,2345 - 0x01, 0xc8 // ADD EAX,ECX - )); - Disassembler - .getDisassembler(view, TaskMonitor.DUMMY, DisassemblerMessageListener.IGNORE) - .disassemble(tb.addr(0x55550000), tb.set(tb.range(0x55550000, 0x5555000b))); - checkCtx = tb.trace.getCodeManager().instructions().getAt(0, tb.addr(0x55550000)); } // Sanity pre-check RegisterValue insCtx = checkCtx.getRegisterValue(contextReg); @@ -352,8 +351,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { AddressRange trng = tb.range(0x55560000, 0x5556ffff); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".data", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); + memory.createRegion("Memory[.data]", 0, trng, + TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12)); tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34)); tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType, @@ -412,8 +413,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { AddressRange trng = tb.range(0x55560000, 0x5556ffff); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".data", 0, trng, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); + memory.createRegion("Memory[.data]", 0, trng, + TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); tb.addData(0, tb.addr(0x55560000), ByteDataType.dataType, tb.buf(0x12)); tb.addData(0, tb.addr(0x55560001), ShortDataType.dataType, tb.buf(0x12, 0x34)); tb.addData(0, tb.addr(0x55560003), IntegerDataType.dataType, @@ -479,21 +482,20 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.LABELS.isAvailable(view, program)); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); DBTraceNamespaceSymbol global = tb.trace.getSymbolManager().getGlobalNamespace(); DBTraceLabelSymbolView labels = tb.trace.getSymbolManager().labels(); - labels.create(0, null, tb.addr(0x55550000), "test_label1", global, SourceType.IMPORTED); - labels.create(0, null, tb.addr(0x55550005), "test_label2", global, - SourceType.USER_DEFINED); + labels.create(0, tb.addr(0x55550000), "test_label1", global, SourceType.IMPORTED); + labels.create(0, tb.addr(0x55550005), "test_label2", global, SourceType.USER_DEFINED); DBTraceNamespaceSymbolView namespaces = tb.trace.getSymbolManager().namespaces(); DBTraceNamespaceSymbol testNs = namespaces.add("test_ns", global, SourceType.ANALYSIS); DBTraceNamespaceSymbol testNsChild = namespaces.add("test_ns_child", testNs, SourceType.USER_DEFINED); - labels.create(0, null, tb.addr(0x55550800), "test_label3", testNsChild, - SourceType.ANALYSIS); + labels.create(0, tb.addr(0x55550800), "test_label3", testNsChild, SourceType.ANALYSIS); } Address paddr = tb.addr(stSpace, 0x00400000); @@ -550,14 +552,15 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.BREAKPOINTS.isAvailable(view, program)); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); DBTraceBreakpointManager breakpoints = tb.trace.getBreakpointManager(); - breakpoints.placeBreakpoint("[1]", 0, tb.addr(0x55550123), List.of(), + breakpoints.placeBreakpoint("Breakpoints[1]", 0, tb.addr(0x55550123), List.of(), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "Test-1"); - breakpoints.placeBreakpoint("[2]", 0, tb.addr(0x55550321), List.of(), + breakpoints.placeBreakpoint("Breakpoints[2]", 0, tb.addr(0x55550321), List.of(), Set.of(TraceBreakpointKind.SW_EXECUTE), false, "Test-2"); } @@ -603,9 +606,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.BOOKMARKS.isAvailable(view, program)); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); BookmarkManager bookmarks = view.getBookmarkManager(); bookmarks.defineType("TestType", DebuggerResources.ICON_DEBUGGER, Palette.BLUE, 1); @@ -651,11 +655,12 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.REFERENCES.isAvailable(view, program)); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); - memory.createRegion(".data", 0, tb.range(0x55560000, 0x5556ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.WRITE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.data]", 0, tb.range(0x55560000, 0x5556ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); ReferenceManager references = view.getReferenceManager(); references.addMemoryReference(tb.addr(0x55550123), tb.addr(0x55550321), @@ -702,9 +707,10 @@ public class DebuggerCopyPlanTest extends AbstractGhidraHeadedDebuggerTest { assertTrue(AllCopiers.COMMENTS.isAvailable(view, program)); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + memory.createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); Listing listing = view.getListing(); listing.setComment(tb.addr(0x55550123), CommentType.EOL, "Test EOL Comment"); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPluginTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPluginTest.java index b0c23916dc..f87cd17a53 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPluginTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPluginTest.java @@ -4,9 +4,9 @@ * 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. @@ -129,8 +129,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge public void testColorsDiffBytes() throws Throwable { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), + mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text @@ -164,8 +165,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge public void testActionPrevDiff() throws Throwable { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), + mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text @@ -201,8 +203,9 @@ public class DebuggerTraceViewDiffPluginTest extends AbstractGhidraHeadedDebugge public void testActionNextDiff() throws Throwable { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), + mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); ByteBuffer buf = ByteBuffer.allocate(0x1000); // Yes, smaller than .text diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java index cf227494b7..f6f1900ff1 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java @@ -45,7 +45,6 @@ import ghidra.program.util.ProgramSelection; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.memory.TraceMemoryRegion; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; import ghidra.trace.model.modules.TraceStaticMapping; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; @@ -80,10 +79,10 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes DebuggerRegionsProvider provider; - TraceObjectMemoryRegion regionExeText; - TraceObjectMemoryRegion regionExeData; - TraceObjectMemoryRegion regionLibText; - TraceObjectMemoryRegion regionLibData; + TraceMemoryRegion regionExeText; + TraceMemoryRegion regionExeData; + TraceMemoryRegion regionLibText; + TraceMemoryRegion regionLibData; MemoryBlock blockExeText; MemoryBlock blockExeData; @@ -109,21 +108,21 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes } } - protected TraceObjectMemoryRegion addRegion(String name, long loaded, AddressRange range) { + protected TraceMemoryRegion addRegion(String name, long loaded, AddressRange range) { boolean isData = name.endsWith(".data"); TraceObjectManager om = tb.trace.getObjectManager(); KeyPath memPath = KeyPath.parse("Memory"); Lifespan span = Lifespan.nowOn(loaded); - TraceObjectMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name)) + TraceMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name)) .insert(span, ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectMemoryRegion.class)); + .queryInterface(TraceMemoryRegion.class)); TraceObject obj = region.getObject(); - obj.setAttribute(span, TraceObjectMemoryRegion.KEY_DISPLAY, name); - obj.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE, range); - obj.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true); - obj.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE, isData); - obj.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE, !isData); + obj.setAttribute(span, TraceMemoryRegion.KEY_DISPLAY, name); + obj.setAttribute(span, TraceMemoryRegion.KEY_RANGE, range); + obj.setAttribute(span, TraceMemoryRegion.KEY_READABLE, true); + obj.setAttribute(span, TraceMemoryRegion.KEY_WRITABLE, isData); + obj.setAttribute(span, TraceMemoryRegion.KEY_EXECUTABLE, !isData); return region; } @@ -218,7 +217,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes public void testAddThenActivateTracePopulates() throws Exception { createAndOpenTrace(); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } @@ -240,7 +239,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes waitForPass(() -> assertTableSize(0)); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } @@ -257,7 +256,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes public void testRemoveRegionRemovesFromTable() throws Exception { createAndOpenTrace(); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } @@ -284,7 +283,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes public void testUndoRedo() throws Exception { createAndOpenTrace(); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } @@ -320,7 +319,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes createAndOpenTrace(); traceManager.activateTrace(tb.trace); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); waitForDomainObject(tb.trace); @@ -346,7 +345,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes createAndOpenTrace(); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } @@ -465,7 +464,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes createAndOpenTrace(); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } @@ -514,7 +513,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes createAndOpenTrace(); - TraceObjectMemoryRegion region; + TraceMemoryRegion region; try (Transaction tx = tb.startTransaction()) { region = addRegion("bin:.text", 0, tb.range(0x00400000, 0x0040ffff)); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelProviderTest.java index bf85decb18..239d45a2ca 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/DebuggerModelProviderTest.java @@ -43,13 +43,12 @@ import ghidra.trace.database.ToyDBTraceBuilder.EventSuspension; import ghidra.trace.model.Lifespan; import ghidra.trace.model.target.*; import ghidra.trace.model.target.TraceObject.ConflictResolution; -import ghidra.trace.model.target.iface.TraceObjectEventScope; +import ghidra.trace.model.target.iface.TraceEventScope; import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest { @@ -164,7 +163,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest prevThread.setAttribute(Lifespan.nowOn(i), "_next", thread); } objects.getRootObject() - .setAttribute(Lifespan.nowOn(i), TraceObjectEventScope.KEY_EVENT_THREAD, + .setAttribute(Lifespan.nowOn(i), TraceEventScope.KEY_EVENT_THREAD, thread); return thread; } @@ -700,6 +699,8 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest * sufficient events to overload the queue, the event support with clear them and just issue an * OBJ_RESTORED event instead. This test ensures we update attributes in the tree when that * happens. + * + * @throws Throwable because */ @Test public void testTreeTracksChangeAttributeWithEventsSuspended() throws Throwable { @@ -998,7 +999,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest TraceObjectManager objects = tb.trace.getObjectManager(); TraceObject threadObj0 = objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[0]")); - TraceThread thread0 = threadObj0.queryInterface(TraceObjectThread.class); + TraceThread thread0 = threadObj0.queryInterface(TraceThread.class); createStack(threadObj0); return thread0; } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java index e19188f5c1..250fbae325 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java @@ -51,12 +51,10 @@ import ghidra.framework.main.DataTreeDialog; import ghidra.plugin.importer.ImporterPlugin; import ghidra.program.model.address.*; import ghidra.program.model.mem.MemoryBlock; -import ghidra.trace.database.module.TraceObjectSection; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; -import ghidra.trace.model.modules.TraceObjectModule; -import ghidra.trace.model.modules.TraceStaticMapping; +import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.modules.*; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObjectManager; @@ -109,13 +107,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes DebuggerModulesProvider provider; - protected TraceObjectModule modExe; - protected TraceObjectSection secExeText; - protected TraceObjectSection secExeData; + protected TraceModule modExe; + protected TraceSection secExeText; + protected TraceSection secExeData; - protected TraceObjectModule modLib; - protected TraceObjectSection secLibText; - protected TraceObjectSection secLibData; + protected TraceModule modLib; + protected TraceSection secLibText; + protected TraceSection secLibData; protected SchemaContext ctx; @@ -145,13 +143,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes try (Transaction tx = tb.startTransaction()) { TraceObject root = om.getRootObject(); for (TraceObject module : (Iterable) () -> root - .findSuccessorsInterface(Lifespan.at(0), TraceObjectModule.class, true) + .findSuccessorsInterface(Lifespan.at(0), TraceModule.class, true) .map(p -> p.getDestination(root)) .iterator()) { String moduleName = module.getCanonicalPath().index(); Lifespan span = module.getLife().bound(); for (TraceObject section : (Iterable) () -> module - .findSuccessorsInterface(Lifespan.at(0), TraceObjectSection.class, + .findSuccessorsInterface(Lifespan.at(0), TraceSection.class, true) .map(p -> p.getDestination(root)) .iterator()) { @@ -161,42 +159,42 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes .getSingletonPath()) .insert(span, ConflictResolution.TRUNCATE) .getDestination(root); - region.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE, - section.getAttribute(0, TraceObjectSection.KEY_RANGE).getValue()); - region.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true); - region.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE, + region.setAttribute(span, TraceMemoryRegion.KEY_RANGE, + section.getAttribute(0, TraceSection.KEY_RANGE).getValue()); + region.setAttribute(span, TraceMemoryRegion.KEY_READABLE, true); + region.setAttribute(span, TraceMemoryRegion.KEY_WRITABLE, ".data".equals(sectionName)); - region.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE, + region.setAttribute(span, TraceMemoryRegion.KEY_EXECUTABLE, ".text".equals(sectionName)); } } } } - protected TraceObjectModule addModule(String name, AddressRange range, Lifespan span) { + protected TraceModule addModule(String name, AddressRange range, Lifespan span) { PathPattern modulePattern = PathFilter.parse("Processes[1].Modules[]"); TraceObjectManager om = tb.trace.getObjectManager(); - TraceObjectModule module = Objects.requireNonNull( + TraceModule module = Objects.requireNonNull( om.createObject(modulePattern.applyKeys(name).getSingletonPath()) .insert(span, ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectModule.class)); - module.getObject().setAttribute(span, TraceObjectModule.KEY_MODULE_NAME, name); - module.getObject().setAttribute(span, TraceObjectModule.KEY_RANGE, range); + .queryInterface(TraceModule.class)); + module.getObject().setAttribute(span, TraceModule.KEY_MODULE_NAME, name); + module.getObject().setAttribute(span, TraceModule.KEY_RANGE, range); return module; } - protected TraceObjectSection addSection(TraceObjectModule module, String name, + protected TraceSection addSection(TraceModule module, String name, AddressRange range) { TraceObjectManager om = tb.trace.getObjectManager(); Lifespan span = module.getObject().getLife().bound(); - TraceObjectSection section = Objects.requireNonNull(om + TraceSection section = Objects.requireNonNull(om .createObject( module.getObject().getCanonicalPath().key("Sections").index(name)) .insert(span, ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectSection.class)); - section.getObject().setAttribute(span, TraceObjectSection.KEY_RANGE, range); + .queryInterface(TraceSection.class)); + section.getObject().setAttribute(span, TraceSection.KEY_RANGE, range); return section; } @@ -719,7 +717,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes for (ValueRow row : visibleSections()) { assertEquals(modExe.getObject(), row.getValue() .getChild() - .findCanonicalAncestorsInterface(TraceObjectModule.class) + .findCanonicalAncestorsInterface(TraceModule.class) .findFirst() .orElse(null)); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java index 36847a9a01..54178b4031 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java @@ -4,9 +4,9 @@ * 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. @@ -115,8 +115,9 @@ public class DebuggerStaticMappingProviderTest extends AbstractGhidraHeadedDebug intoProject(program); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.trace.getMemoryManager() - .addRegion(".text", Lifespan.nowOn(0), + .addRegion("Memory[.text]", Lifespan.nowOn(0), tb.range(0xdeadbeefL, 0xdeadbeefL + 0xff), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java index 54f1f2d52f..06eb9218cb 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProviderTest.java @@ -4,9 +4,9 @@ * 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. @@ -26,7 +26,8 @@ import org.junit.Test; import db.Transaction; import generic.Unique; -import generic.theme.*; +import generic.theme.ApplicationThemeManager; +import generic.theme.ThemeManager; import ghidra.app.plugin.assembler.Assembler; import ghidra.app.plugin.assembler.Assemblers; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; @@ -46,8 +47,10 @@ import ghidra.pcode.exec.trace.TraceSleighUtils; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Instruction; import ghidra.program.model.listing.InstructionIterator; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemoryFlag; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule; @@ -79,15 +82,25 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg createTrace(); } + SchemaContext buildContext() { + return new ToySchemaBuilder() + .useRegistersPerFrame() + .noRegisterGroups() + .build(); + } + protected void populateTrace() throws Exception { start = tb.addr(0x00400000); InstructionIterator iit; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .addRegion("echo:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + .addRegion("Memory[echo:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); PcodeExecutor init = TraceSleighUtils.buildByteExecutor(tb.trace, 0, thread, 0); init.executeSleigh("pc = 0x00400000;"); @@ -124,7 +137,7 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg public void testCloseCurrentTraceEmpty() throws Exception { populateTrace(); - TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1"); + TraceSchedule schedule1 = TraceSchedule.parse("0:.t%d-1".formatted(thread.getKey())); traceManager.openTrace(tb.trace); traceManager.activateThread(thread); waitForPass(() -> assertDecodeStep()); @@ -166,13 +179,13 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg }); // Just one p-code step to load injection (decode step) - TraceSchedule schedule1 = TraceSchedule.parse("0:.t0-1"); + TraceSchedule schedule1 = TraceSchedule.parse("0:.t%d-1".formatted(thread.getKey())); traceManager.openTrace(tb.trace); traceManager.activateThread(thread); traceManager.activateTime(schedule1); waitForPass(() -> assertEquals(schedule1, pcodeProvider.current.getTime())); - waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.getModelData() + waitForPass(() -> assertTrue(pcodeProvider.pcodeTableModel.copyModelData() .stream() .anyMatch(r -> r.getCode().contains("stepper_test_userop")))); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackProviderTest.java index 7deb2b34b3..587eb56211 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackProviderTest.java @@ -41,9 +41,9 @@ import ghidra.program.model.listing.Function; import ghidra.program.model.symbol.SourceType; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.*; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObjectManager; @@ -51,7 +51,7 @@ import ghidra.trace.model.target.path.*; import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.util.table.GhidraTable; import ghidra.util.task.TaskMonitor; @@ -167,7 +167,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest } } - protected TraceObjectThread addThread(int n) { + protected TraceThread addThread(int n) { PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]"); KeyPath threadPath = threadPattern.applyIntKeys(n).getSingletonPath(); try (Transaction tx = tb.startTransaction()) { @@ -175,26 +175,26 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest .createObject(threadPath) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectThread.class)); + .queryInterface(TraceThread.class)); } } - protected TraceObjectStack addStack(TraceObjectThread thread) { + protected TraceStack addStack(TraceThread thread) { KeyPath stackPath = thread.getObject().getCanonicalPath().extend("Stack"); try (Transaction tx = tb.startTransaction()) { return Objects.requireNonNull(tb.trace.getObjectManager() .createObject(stackPath) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectStack.class)); + .queryInterface(TraceStack.class)); } } - protected void addStackFrames(TraceObjectStack stack) { + protected void addStackFrames(TraceStack stack) { addStackFrames(stack, 2); } - protected void addStackFrames(TraceObjectStack stack, int count) { + protected void addStackFrames(TraceStack stack, int count) { KeyPath stackPath = stack.getObject().getCanonicalPath(); TraceObjectManager om = tb.trace.getObjectManager(); try (Transaction tx = tb.startTransaction()) { @@ -202,7 +202,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest TraceObject frame = om.createObject(stackPath.index(i)) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .getDestination(null); - frame.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC, + frame.setAttribute(Lifespan.nowOn(0), TraceStackFrame.KEY_PC, tb.addr(0x00400100 + 0x100 * i)); } } @@ -262,7 +262,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testActivateThreadNoStackEmpty() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); + TraceThread thread = addThread(1); waitForDomainObject(tb.trace); traceManager.activateObject(thread.getObject()); @@ -275,7 +275,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testActivateThreadThenAddEmptyStackEmpty() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); + TraceThread thread = addThread(1); addStack(thread); waitForDomainObject(tb.trace); @@ -289,9 +289,9 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testActivateThreadThenAddStackPopulatesProvider() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); + TraceThread thread = addThread(1); traceManager.activateObject(thread.getObject()); - TraceObjectStack stack = addStack(thread); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); waitForTasks(); @@ -303,8 +303,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testAddStackThenActivateThreadPopulatesProvider() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -316,12 +316,14 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest /** * Because keys are strings, we need to ensure they get sorted numerically + * + * @throws Exception because */ @Test public void testTableSortedCorrectly() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack, 15); waitForDomainObject(tb.trace); @@ -341,8 +343,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testAppendStackUpdatesProvider() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -356,7 +358,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest .createObject(stack.getObject().getCanonicalPath().index(2)) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .getDestination(null); - frame2.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC, + frame2.setAttribute(Lifespan.nowOn(0), TraceStackFrame.KEY_PC, tb.addr(0x00400300)); } waitForDomainObject(tb.trace); @@ -374,8 +376,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testRemoveFrameUpdatesProvider() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -400,8 +402,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testRemoveStackUpdatesProvider() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -423,9 +425,9 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testActivateOtherThreadEmptiesProvider() throws Exception { createAndOpenTrace(); - TraceObjectThread thread1 = addThread(1); - TraceObjectThread thread2 = addThread(2); - TraceObjectStack stack1 = addStack(thread1); + TraceThread thread1 = addThread(1); + TraceThread thread2 = addThread(2); + TraceStack stack1 = addStack(thread1); addStackFrames(stack1); waitForDomainObject(tb.trace); @@ -444,8 +446,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testActivateSnap() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -477,8 +479,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testCloseCurrentTraceEmpty() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -497,8 +499,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testActivateFrameSelectsRow() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -524,8 +526,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest public void testDoubleClickRowActivateFrame() throws Exception { createAndOpenTrace(); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -557,8 +559,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest traceManager.openTrace(tb.trace); programManager.openProgram(program); - TraceObjectThread thread = addThread(1); - TraceObjectStack stack = addStack(thread); + TraceThread thread = addThread(1); + TraceStack stack = addStack(thread); addStackFrames(stack); waitForDomainObject(tb.trace); @@ -580,13 +582,13 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest waitForDomainObject(program); try (Transaction tx = tb.startTransaction()) { - TraceObjectMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager() + TraceMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager() .createObject(KeyPath.parse("Processes[1].Memory[bin:.text]")) .insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectMemoryRegion.class)); + .queryInterface(TraceMemoryRegion.class)); region.getObject() - .setAttribute(Lifespan.nowOn(0), TraceObjectMemoryRegion.KEY_RANGE, + .setAttribute(Lifespan.nowOn(0), TraceMemoryRegion.KEY_RANGE, tb.drng(0x00400000, 0x00400fff)); TraceLocation dloc = diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java index b3dc4a001a..bdc2162578 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java @@ -34,13 +34,13 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.trace.model.*; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObjectManager; -import ghidra.trace.model.target.iface.TraceObjectExecutionStateful; +import ghidra.trace.model.target.iface.TraceExecutionStateful; import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.path.PathPattern; import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.TraceTimeManager; import ghidra.util.table.GhidraTable; @@ -71,8 +71,8 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes DebuggerThreadsProvider provider; - protected TraceObjectThread thread1; - protected TraceObjectThread thread2; + protected TraceThread thread1; + protected TraceThread thread2; protected SchemaContext ctx; @@ -95,18 +95,18 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes } } - protected TraceObjectThread addThread(int index, Lifespan lifespan, String comment) { + protected TraceThread addThread(int index, Lifespan lifespan, String comment) { TraceObjectManager om = tb.trace.getObjectManager(); PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]"); - TraceObjectThread thread = Objects.requireNonNull(om.createObject( + TraceThread thread = Objects.requireNonNull(om.createObject( threadPattern.applyIntKeys(index).getSingletonPath()) .insert(lifespan, ConflictResolution.TRUNCATE) .getDestination(null) - .queryInterface(TraceObjectThread.class)); + .queryInterface(TraceThread.class)); thread.getObject() - .setAttribute(lifespan, TraceObjectExecutionStateful.KEY_STATE, + .setAttribute(lifespan, TraceExecutionStateful.KEY_STATE, TraceExecutionState.STOPPED.name()); - thread.getObject().setAttribute(lifespan, TraceObjectThread.KEY_COMMENT, comment); + thread.getObject().setAttribute(lifespan, TraceThread.KEY_COMMENT, comment); return thread; } @@ -160,7 +160,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes assertNull(provider.panel.getSelectedItem()); } - protected void assertThreadSelected(TraceObjectThread thread) { + protected void assertThreadSelected(TraceThread thread) { ValueRow row = provider.panel.getSelectedItem(); assertNotNull(row); assertEquals(thread.getObject(), row.getValue().getChild()); @@ -329,7 +329,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes waitForTasks(); waitForPass(() -> assertEquals("A different comment", - thread1.getObject().getAttribute(0, TraceObjectThread.KEY_COMMENT).getValue())); + thread1.getObject().getAttribute(0, TraceThread.KEY_COMMENT).getValue())); } // @Test // Not gonna with write-behind cache diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/time/DebuggerTimeProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/time/DebuggerTimeProviderTest.java index 322344d6d9..2430318163 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/time/DebuggerTimeProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/time/DebuggerTimeProviderTest.java @@ -92,7 +92,7 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest { // Timestamp is left unchecked, since default is current time } - @Test // TODO: Technically, this is a plugin action.... Different test case? + @Test // Technically, this is a plugin action.... Different test case? public void testActionRenameSnapshot() throws Exception { // More often than not, this action will be used from the dynamic listing addPlugin(tool, DebuggerListingPlugin.class); @@ -125,7 +125,7 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest { DBTraceSnapshot snapshot = tb.trace.getTimeManager().getSnapshot(10, false); assertEquals("My Snapshot", snapshot.getDescription()); - // TODO: Test cancelled has no effect + // LATER?: Test cancelled has no effect } @Test @@ -153,7 +153,8 @@ public class DebuggerTimeProviderTest extends AbstractGhidraHeadedDebuggerTest { createSnaplessTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - thread = tb.trace.getThreadManager().createThread("Thread 1", 0); + tb.createRootObject("Target"); + thread = tb.trace.getThreadManager().createThread("Threads[1]", 0); } traceManager.openTrace(tb.trace); traceManager.activateThread(thread); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/MockTarget.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/MockTarget.java index 4f0ebe5bd8..8bf73a9552 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/MockTarget.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/MockTarget.java @@ -29,8 +29,7 @@ import ghidra.program.model.lang.Register; import ghidra.program.model.lang.RegisterValue; import ghidra.trace.model.Trace; import ghidra.trace.model.TraceExecutionState; -import ghidra.trace.model.breakpoint.TraceBreakpoint; -import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; @@ -233,27 +232,27 @@ public class MockTarget implements Target { } @Override - public boolean isBreakpointValid(TraceBreakpoint breakpoint) { + public boolean isBreakpointValid(TraceBreakpointLocation breakpoint) { return true; } @Override - public CompletableFuture deleteBreakpointAsync(TraceBreakpoint breakpoint) { + public CompletableFuture deleteBreakpointAsync(TraceBreakpointCommon breakpoint) { return AsyncUtils.nil(); } @Override - public void deleteBreakpoint(TraceBreakpoint breakpoint) { + public void deleteBreakpoint(TraceBreakpointCommon breakpoint) { } @Override - public CompletableFuture toggleBreakpointAsync(TraceBreakpoint breakpoint, + public CompletableFuture toggleBreakpointAsync(TraceBreakpointCommon breakpoint, boolean enabled) { return AsyncUtils.nil(); } @Override - public void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled) { + public void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled) { } @Override diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServiceTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServiceTest.java index 5ec079b998..88060f2732 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServiceTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServiceTest.java @@ -52,16 +52,18 @@ import ghidra.program.model.listing.ProgramContext; import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryBlock; import ghidra.program.util.ProgramLocation; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.memory.TraceMemoryManager; import ghidra.trace.model.memory.TraceMemorySpace; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.TraceSnapshot; @@ -249,6 +251,13 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe mem.getViewValue(scratch, regW1).getUnsignedValue()); } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + @Test public void testPureEmulationRelocated() throws Throwable { createAndOpenTrace("x86:LE:64:default"); @@ -282,7 +291,9 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe TraceThread thread; TraceMemorySpace regs; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); thread = tb.getOrAddThread("Threads[0]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(program.getLanguage().getProgramCounter(), BigInteger.valueOf(0x55550000))); @@ -295,8 +306,8 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe waitForSwing(); waitOn(settled); - long scratch = - emulationPlugin.emulate(tb.trace, TraceSchedule.parse("0:t0-1"), TaskMonitor.DUMMY); + long scratch = emulationPlugin.emulate(tb.trace, + TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), TaskMonitor.DUMMY); assertEquals("deadbeefcafebabe", regs.getViewValue(scratch, tb.reg("RAX")).getUnsignedValue().toString(16)); @@ -315,7 +326,9 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe TraceMemoryManager mem = tb.trace.getMemoryManager(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); thread = tb.getOrAddThread("Threads[0]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); buf.assemble("MOV RAX, qword ptr [0x00600800]"); mem.putBytes(0, tb.addr(0x00400000), ByteBuffer.wrap(buf.getBytes())); mem.putBytes(0, tb.addr(0x00600800), @@ -344,8 +357,8 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe tb.exec(platform, 0, thread, 0, "RIP = 0x00400000;"); } - long scratch = - emulationPlugin.emulate(platform, TraceSchedule.parse("0:t0-1"), TaskMonitor.DUMMY); + long scratch = emulationPlugin.emulate(platform, + TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), TaskMonitor.DUMMY); TraceMemorySpace regs = mem.getMemoryRegisterSpace(thread, false); assertEquals("deadbeefcafebabe", regs.getViewValue(platform, scratch, tb.reg(platform, "RAX")) @@ -494,7 +507,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe trace.getBreakpointManager() .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); - TraceBreakpoint tb = trace.getBreakpointManager() + TraceBreakpointLocation tb = trace.getBreakpointManager() .addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); // Force "partial instruction" @@ -568,7 +581,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe trace.getBreakpointManager() .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrText, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); - TraceBreakpoint tb = trace.getBreakpointManager() + TraceBreakpointLocation tb = trace.getBreakpointManager() .addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); // Force "partial instruction" @@ -634,7 +647,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe TraceThread thread = Unique.assertOne(trace.getThreadManager().getAllThreads()); try (Transaction tx = trace.openTransaction("Add breakpoint")) { - TraceBreakpoint tb = trace.getBreakpointManager() + TraceBreakpointLocation tb = trace.getBreakpointManager() .addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), addrI1, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); // Force "partial instruction" @@ -709,7 +722,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe TraceMemorySpace regs = trace.getMemoryManager().getMemoryRegisterSpace(thread, false); try (Transaction tx = trace.openTransaction("Add breakpoint")) { - TraceBreakpoint tb = trace.getBreakpointManager() + TraceBreakpointLocation tb = trace.getBreakpointManager() .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); tb.setEmuSleigh(0, """ @@ -854,7 +867,7 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe // Inject some logic that would require a cache refresh to materialize try (Transaction tx = trace.openTransaction("Add breakpoint")) { - TraceBreakpoint tb = trace.getBreakpointManager() + TraceBreakpointLocation tb = trace.getBreakpointManager() .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), addrI2, Set.of(thread), Set.of(TraceBreakpointKind.SW_EXECUTE), true, "test"); tb.setEmuSleigh(0, """ @@ -986,10 +999,10 @@ public class DebuggerEmulationServiceTest extends AbstractGhidraHeadedDebuggerTe public void testEmuSchemaHasWorkingStackFrames() throws Exception { TraceObjectSchema rootSchema = ProgramEmulationUtils.EMU_SESSION_SCHEMA; TraceObjectSchema threadSchema = rootSchema.getSuccessorSchema(KeyPath.parse("Threads[1]")); - KeyPath found = threadSchema.searchForCanonicalContainer(TraceObjectStackFrame.class); + KeyPath found = threadSchema.searchForCanonicalContainer(TraceStackFrame.class); assertEquals(KeyPath.parse("Stack"), found); - PathFilter stackFilter = threadSchema.searchFor(TraceObjectStack.class, false); + PathFilter stackFilter = threadSchema.searchFor(TraceStack.class, false); assertNotNull("Non-unique Stack", stackFilter.getSingletonPath()); } } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServiceTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServiceTest.java index 1d077bca86..319205bcfa 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServiceTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingServiceTest.java @@ -635,13 +635,14 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg TraceMemoryRegion echoText, echoData, libText, libData; DBTraceMemoryManager mm = tb.trace.getMemoryManager(); try (Transaction tx = tb.startTransaction()) { - echoText = mm.createRegion("Memory.Regions[/bin/echo (0x00400000)]", + tb.createRootObject("Target"); + echoText = mm.createRegion("Memory[/bin/echo (0x00400000)]", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - echoData = mm.createRegion("Memory.Regions[/bin/echo (0x00600000)]", + echoData = mm.createRegion("Memory[/bin/echo (0x00600000)]", 0, tb.range(0x00600000, 0x00600fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); - libText = mm.createRegion("Memory.Regions[/lib/libc.so (0x7ff00000)]", + libText = mm.createRegion("Memory[/lib/libc.so (0x7ff00000)]", 0, tb.range(0x7ff00000, 0x7ff0ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - libData = mm.createRegion("Memory.Regions[/lib/libc.so (0x7ff20000)]", + libData = mm.createRegion("Memory[/lib/libc.so (0x7ff20000)]", 0, tb.range(0x7ff20000, 0x7ff20fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); } @@ -688,7 +689,7 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY); } - TraceModule modBash = objModBash.queryInterface(TraceObjectModule.class); + TraceModule modBash = objModBash.queryInterface(TraceModule.class); assertEquals(Map.of(), mappingService.proposeModuleMaps(List.of(modBash), 0, List.of(program))); } diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/stack/StackUnwinderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/stack/StackUnwinderTest.java index eedcc5c3eb..ef58704c3b 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/stack/StackUnwinderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/stack/StackUnwinderTest.java @@ -80,8 +80,8 @@ import ghidra.program.model.symbol.SourceType; import ghidra.program.util.*; import ghidra.trace.model.Lifespan; import ghidra.trace.model.TraceLocation; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.listing.TraceData; import ghidra.trace.model.memory.TraceMemorySpace; import ghidra.trace.model.thread.TraceThread; @@ -888,7 +888,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest { waitOn(frameAtSetup.setReturnAddress(editor, tb.addr(0xdeadbeef))); waitForTasks(); - TraceBreakpoint bptUnwind; + TraceBreakpointLocation bptUnwind; try (Transaction tx = tb.startTransaction()) { bptUnwind = tb.trace.getBreakpointManager() .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(), @@ -976,7 +976,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest { Register sp = program.getCompilerSpec().getStackPointer(); long spAtSetup = regs.getValue(0, sp).getUnsignedValue().longValueExact(); - TraceBreakpoint bptUnwind; + TraceBreakpointLocation bptUnwind; try (Transaction tx = tb.startTransaction()) { bptUnwind = tb.trace.getBreakpointManager() .addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), entry, Set.of(), diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java index 69240ad4ea..36021a0204 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java @@ -300,11 +300,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace } @DependentService - protected DBTraceBreakpointManager createBreakpointManager(DBTraceThreadManager threadManager) + protected DBTraceBreakpointManager createBreakpointManager(DBTraceObjectManager objectManager) throws CancelledException, IOException { return createTraceManager("Breakpoint Manager", (openMode, monitor) -> new DBTraceBreakpointManager(dbh, openMode, rwLock, monitor, - baseLanguage, this, threadManager)); + this, objectManager)); } @DependentService @@ -367,10 +367,11 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace } @DependentService - protected DBTraceModuleManager createModuleManager() throws CancelledException, IOException { + protected DBTraceModuleManager createModuleManager(DBTraceObjectManager objectManager) + throws CancelledException, IOException { return createTraceManager("Module Manager", - (openMode, monitor) -> new DBTraceModuleManager(dbh, openMode, rwLock, monitor, - baseLanguage, this)); + (openMode, monitor) -> new DBTraceModuleManager(dbh, openMode, rwLock, monitor, this, + objectManager)); } @DependentService @@ -670,16 +671,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace if (recordChanges) { traceChangeSet.sourceArchiveAdded(sourceArchiveID.getValue()); } - setChanged( - new TraceChangeRecord<>(TraceEvents.SOURCE_TYPE_ARCHIVE_ADDED, null, sourceArchiveID)); + setChanged(new TraceChangeRecord<>(TraceEvents.SOURCE_TYPE_ARCHIVE_ADDED, null, + sourceArchiveID)); } public void dataTypeChanged(long changedID, DataType changedType) { if (recordChanges) { traceChangeSet.dataTypeChanged(changedID); } - setChanged( - new TraceChangeRecord<>(TraceEvents.DATA_TYPE_CHANGED, null, changedID, changedType)); + setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_CHANGED, null, changedID, + changedType)); } public void dataTypeAdded(long addedID, DataType addedType) { @@ -701,16 +702,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace if (recordChanges) { traceChangeSet.dataTypeChanged(movedID); } - setChanged( - new TraceChangeRecord<>(TraceEvents.DATA_TYPE_MOVED, null, movedID, oldPath, newPath)); + setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_MOVED, null, movedID, + oldPath, newPath)); } public void dataTypeNameChanged(long renamedID, String oldName, String newName) { if (recordChanges) { traceChangeSet.dataTypeChanged(renamedID); } - setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_RENAMED, null, renamedID, oldName, - newName)); + setChanged(new TraceChangeRecord<>(TraceEvents.DATA_TYPE_RENAMED, null, renamedID, + oldName, newName)); } public void dataTypeDeleted(long deletedID, DataTypePath deletedPath) { @@ -725,16 +726,16 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace if (recordChanges) { traceChangeSet.categoryAdded(addedID); } - setChanged( - new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_ADDED, null, addedID, addedCategory)); + setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_ADDED, null, addedID, + addedCategory)); } public void categoryMoved(long movedID, CategoryPath oldPath, CategoryPath newPath) { if (recordChanges) { traceChangeSet.categoryChanged(movedID); } - setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_MOVED, null, movedID, oldPath, - newPath)); + setChanged(new TraceChangeRecord<>(TraceEvents.TYPE_CATEGORY_MOVED, null, movedID, + oldPath, newPath)); } public void categoryRenamed(long renamedID, String oldName, String newName) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceUtils.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceUtils.java index c51869e46c..3af772d06c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceUtils.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceUtils.java @@ -433,18 +433,9 @@ public enum DBTraceUtils { * * @param baseName the base name of the table group * @param space the address space - * @param threadKey the thread key, -1 usually indicating "no thread" - * @param frameLevel the frame level * @return the table name */ - public static String tableName(String baseName, AddressSpace space, long threadKey, - int frameLevel) { - if (space.isRegisterSpace()) { - if (frameLevel == 0) { - return baseName + "_" + space.getName() + "_" + threadKey; - } - return baseName + "_" + space.getName() + "_" + threadKey + "_" + frameLevel; - } + public static String tableName(String baseName, AddressSpace space) { return baseName + "_" + space.getName(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/address/DBTraceOverlaySpaceAdapter.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/address/DBTraceOverlaySpaceAdapter.java index deb6676e0d..5cd95584c5 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/address/DBTraceOverlaySpaceAdapter.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/address/DBTraceOverlaySpaceAdapter.java @@ -4,9 +4,9 @@ * 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. @@ -222,7 +222,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager { keyToRecordMap.remove(key); } - // Add any remaing overlay which are missing from factory + // Add any remaining overlays which are missing from factory for (long key : keyToRecordMap.keySet()) { DBTraceOverlaySpaceEntry ent = keyToRecordMap.get(key); String spaceName = ent.name; @@ -268,7 +268,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager { ent.set(space.getName(), base.getName()); trace.updateViewsAddSpaceBlock(space); trace.setChanged( - new TraceChangeRecord<>(TraceEvents.OVERLAY_ADDED, null, trace, null, space)); + new TraceChangeRecord<>(TraceEvents.OVERLAY_ADDED, space, trace, null, space)); return space; } @@ -315,7 +315,7 @@ public class DBTraceOverlaySpaceAdapter implements DBTraceManager { factory.removeOverlaySpace(name); trace.updateViewsDeleteSpaceBlock(space); trace.setChanged( - new TraceChangeRecord<>(TraceEvents.OVERLAY_DELETED, null, trace, space, null)); + new TraceChangeRecord<>(TraceEvents.OVERLAY_DELETED, space, trace, space, null)); invalidateCache(true); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmark.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmark.java index d3b0c910e7..bcfc019d27 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmark.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmark.java @@ -4,9 +4,9 @@ * 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. @@ -50,8 +50,8 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD @DBAnnotatedColumn(COMMENT_COLUMN_NAME) static DBObjectColumn COMMENT_COLUMN; - static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField(column = TYPE_COLUMN_NAME, indexed = true) @@ -104,7 +104,7 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD @Override public long getId() { - return DBTraceBookmarkManager.packId(key, space); + return DBTraceBookmarkManager.packId(key, range.getAddressSpace()); } @Override @@ -140,14 +140,14 @@ public class DBTraceBookmark extends AbstractDBTraceAddressSnapRangePropertyMapD update(CATEGORY_COLUMN, COMMENT_COLUMN); } space.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.BOOKMARK_CHANGED, space, this)); + new TraceChangeRecord<>(TraceEvents.BOOKMARK_CHANGED, space.space, this)); } @Override public void delete() { space.bookmarkMapSpace.deleteData(this); space.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.BOOKMARK_DELETED, space, this)); + new TraceChangeRecord<>(TraceEvents.BOOKMARK_DELETED, space.space, this)); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkManager.java index d8ee1722a7..d03a5e3ab8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkManager.java @@ -4,9 +4,9 @@ * 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. @@ -29,7 +29,8 @@ import ghidra.program.model.address.*; import ghidra.program.model.lang.Language; import ghidra.trace.database.DBTrace; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; -import ghidra.trace.database.space.*; +import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager; +import ghidra.trace.database.space.DBTraceDelegatingManager; import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.model.Lifespan; import ghidra.trace.model.bookmark.TraceBookmarkManager; @@ -55,14 +56,6 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager> SPACE_ID_SHIFT) & SPACE_ID_MASK); } - protected static long unpackMemKey(long id) { + protected static long unpackKey(long id) { return (id >> MEM_KEY_SHIFT) & MEM_KEY_MASK; } - protected static long unpackRegThread(long id) { - return (id >> REG_THREAD_SHIFT) & REG_THREAD_MASK; - } - - protected static int unpackRegFrame(long id) { - return (int) ((id >> REG_FRAME_SHIFT) & REG_FRAME_MASK); - } - - protected static long unpackRegKey(long id) { - return (id >> REG_KEY_SHIFT) & REG_KEY_MASK; - } - - protected static DBTraceSpaceKey unpackSpaceKey(long id, Language baseLanguage, - DBTraceThreadManager threadManager) { + protected static AddressSpace unpackSpace(long id, AddressFactory addressFactory) { int spaceId = unpackSpaceId(id); - AddressSpace space = baseLanguage.getAddressFactory().getAddressSpace(spaceId); - if (space == null) { - return null; - } - return space.isRegisterSpace() ? unpackRegSpaceKey(space, threadManager, id) - : unpackMemSpaceKey(space, id); - } - - protected static DBTraceSpaceKey unpackMemSpaceKey(AddressSpace space, long id) { - return DBTraceSpaceKey.create(space, null, 0); - } - - protected static DBTraceSpaceKey unpackRegSpaceKey(AddressSpace space, - DBTraceThreadManager threadManager, long id) { - long threadKey = unpackRegThread(id); - TraceThread thread = threadManager.getThread(threadKey); - assert thread != null; - int frameLevel = unpackRegFrame(id); - return DBTraceSpaceKey.create(space, thread, frameLevel); + return addressFactory.getAddressSpace(spaceId); } protected final Map typesByName = new HashMap<>(); @@ -178,13 +104,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager getCategoriesForType(TraceBookmarkType type) { - return delegateHashSet(getActiveMemorySpaces(), m -> m.getCategoriesForType(type)); + return delegateHashSet(getActiveSpaces(), m -> m.getCategoriesForType(type)); } @Override @@ -300,7 +219,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager getAllBookmarks() { - return delegateCollection(getActiveMemorySpaces(), m -> m.getAllBookmarks()); + return delegateCollection(getActiveSpaces(), m -> m.getAllBookmarks()); } @Override @@ -329,7 +248,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager result = new ArrayList<>(); - for (DBTraceBookmarkSpace space : memSpaces.values()) { + for (DBTraceBookmarkSpace space : spaces.values()) { result.addAll(space.bookmarkMapSpace .reduce(TraceAddressSnapRangeQuery.added(from, to, space.getAddressSpace())) .values()); @@ -343,7 +262,7 @@ public class DBTraceBookmarkManager extends AbstractDBTraceSpaceBasedManager result = new ArrayList<>(); - for (DBTraceBookmarkSpace space : memSpaces.values()) { + for (DBTraceBookmarkSpace space : spaces.values()) { result.addAll(space.bookmarkMapSpace .reduce(TraceAddressSnapRangeQuery.removed(from, to, space.getAddressSpace())) .values()); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkSpace.java index 25d531cc5a..4bd6f2a017 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/bookmark/DBTraceBookmarkSpace.java @@ -4,9 +4,9 @@ * 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. @@ -25,9 +25,9 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; import ghidra.trace.database.space.DBTraceSpaceBased; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.Trace; import ghidra.trace.model.bookmark.TraceBookmarkSpace; import ghidra.trace.model.bookmark.TraceBookmarkType; -import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; @@ -39,47 +39,37 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas protected final ReadWriteLock lock; protected final DBTrace trace; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final DBTraceAddressSnapRangePropertyMapSpace bookmarkMapSpace; protected final DBCachedObjectIndex bookmarksByTypeName; protected final Collection bookmarkView; - public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space, - TraceThread thread, int frameLevel) + public DBTraceBookmarkSpace(DBTraceBookmarkManager manager, AddressSpace space) throws VersionException, IOException { this.manager = manager; this.lock = manager.getLock(); this.trace = manager.getTrace(); this.space = space; - this.thread = thread; - this.frameLevel = frameLevel; this.bookmarkMapSpace = - new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space, -1, 0), - trace.getStoreFactory(), lock, space, null, 0, DBTraceBookmark.class, + new DBTraceAddressSnapRangePropertyMapSpace<>(DBTraceBookmark.tableName(space), trace, + trace.getStoreFactory(), lock, space, DBTraceBookmark.class, (t, s, r) -> new DBTraceBookmark(this, t, s, r)); this.bookmarksByTypeName = bookmarkMapSpace.getUserIndex(String.class, DBTraceBookmark.TYPE_COLUMN); this.bookmarkView = Collections.unmodifiableCollection(bookmarkMapSpace.values()); } + @Override + public Trace getTrace() { + return trace; + } + @Override public AddressSpace getAddressSpace() { return space; } - @Override - public TraceThread getThread() { - return thread; - } - - @Override - public int getFrameLevel() { - return frameLevel; - } - protected DBTraceBookmarkType assertInTrace(TraceBookmarkType type) { if (!(type instanceof DBTraceBookmarkType)) { throw new IllegalArgumentException("Given type is not part of this trace"); @@ -110,7 +100,7 @@ public class DBTraceBookmarkSpace implements TraceBookmarkSpace, DBTraceSpaceBas try (LockHold hold = LockHold.lock(lock.writeLock())) { DBTraceBookmark bookmark = bookmarkMapSpace.put(address, lifespan, null); bookmark.set(type.getTypeString(), category, comment); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.BOOKMARK_ADDED, this, bookmark)); + trace.setChanged(new TraceChangeRecord<>(TraceEvents.BOOKMARK_ADDED, space, bookmark)); return bookmark; } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpoint.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpoint.java deleted file mode 100644 index 5144ced862..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpoint.java +++ /dev/null @@ -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 - 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 kinds = EnumSet.noneOf(TraceBreakpointKind.class); - private final Set kindsView = Collections.unmodifiableSet(kinds); - private boolean enabled; - private boolean emuEnabled; - - protected final DBTraceBreakpointSpace space; - - public DBTraceBreakpoint(DBTraceBreakpointSpace space, - DBTraceAddressSnapRangePropertyMapTree 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 threads, - Collection 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 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 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 kinds) { - byte flags = 0; - for (TraceBreakpointKind k : kinds) { - flags |= k.getBits(); - } - if (enabled) { - flags |= ENABLED_MASK; - } - return flags; - } - - protected void doSetFlags(boolean enabled, Collection 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 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 kinds) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - doSetKinds(kinds); - } - space.trace - .setChanged(new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, this)); - } - - @Override - public Set 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); - } - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceObjectBreakpointLocation.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointLocation.java similarity index 73% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceObjectBreakpointLocation.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointLocation.java index 9b55e7a037..7d49d9baad 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceObjectBreakpointLocation.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointLocation.java @@ -19,54 +19,55 @@ import java.util.*; import java.util.stream.Collectors; import ghidra.pcode.exec.SleighUtils; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRange; +import ghidra.program.model.address.*; import ghidra.trace.database.target.*; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.*; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.breakpoint.TraceBreakpointSpec; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectTogglable; +import ghidra.trace.model.target.iface.TraceTogglable; import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.model.thread.*; +import ghidra.trace.model.thread.TraceProcess; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.*; import ghidra.util.LockHold; -public class DBTraceObjectBreakpointLocation - implements TraceObjectBreakpointLocation, DBTraceObjectInterface { +public class DBTraceBreakpointLocation + implements TraceBreakpointLocation, DBTraceObjectInterface { - protected static class BreakpointChangeTranslator extends Translator { + protected static class BreakpointChangeTranslator extends Translator { private static final Map> KEYS_BY_SCHEMA = new WeakHashMap<>(); private final Set keys; - protected BreakpointChangeTranslator(DBTraceObject object, TraceBreakpoint iface) { + protected BreakpointChangeTranslator(DBTraceObject object, TraceBreakpointLocation iface) { super(KEY_RANGE, object, iface); TraceObjectSchema schema = object.getSchema(); synchronized (KEYS_BY_SCHEMA) { keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( schema.checkAliasedAttribute(KEY_RANGE), schema.checkAliasedAttribute(KEY_DISPLAY), - schema.checkAliasedAttribute(TraceObjectTogglable.KEY_ENABLED), + schema.checkAliasedAttribute(TraceTogglable.KEY_ENABLED), schema.checkAliasedAttribute(KEY_COMMENT))); } } @Override - protected TraceEvent getAddedType() { + protected TraceEvent getAddedType() { return TraceEvents.BREAKPOINT_ADDED; } @Override - protected TraceEvent getLifespanChangedType() { + protected TraceEvent getLifespanChangedType() { return TraceEvents.BREAKPOINT_LIFESPAN_CHANGED; } @Override - protected TraceEvent getChangedType() { + protected TraceEvent getChangedType() { return TraceEvents.BREAKPOINT_CHANGED; } @@ -76,7 +77,7 @@ public class DBTraceObjectBreakpointLocation } @Override - protected TraceEvent getDeletedType() { + protected TraceEvent getDeletedType() { return TraceEvents.BREAKPOINT_DELETED; } } @@ -84,7 +85,7 @@ public class DBTraceObjectBreakpointLocation private final DBTraceObject object; private final BreakpointChangeTranslator translator; - public DBTraceObjectBreakpointLocation(DBTraceObject object) { + public DBTraceBreakpointLocation(DBTraceObject object) { this.object = object; translator = new BreakpointChangeTranslator(object, this); @@ -107,9 +108,7 @@ public class DBTraceObjectBreakpointLocation @Override public void setName(long snap, String name) { - try (LockHold hold = object.getTrace().lockWrite()) { - setName(Lifespan.nowOn(snap), name); - } + setName(Lifespan.nowOn(snap), name); } @Override @@ -121,7 +120,7 @@ public class DBTraceObjectBreakpointLocation return display; } TraceObject spec = - object.findCanonicalAncestorsInterface(TraceObjectBreakpointSpec.class) + object.findCanonicalAncestorsInterface(TraceBreakpointSpec.class) .findFirst() .orElse(null); if (spec == null) { @@ -169,21 +168,19 @@ public class DBTraceObjectBreakpointLocation @Override public void setEnabled(Lifespan lifespan, boolean enabled) { - object.setValue(lifespan, TraceObjectTogglable.KEY_ENABLED, enabled); + object.setValue(lifespan, TraceTogglable.KEY_ENABLED, enabled); } @Override public void setEnabled(long snap, boolean enabled) { - try (LockHold hold = object.getTrace().lockWrite()) { - setEnabled(Lifespan.nowOn(snap), enabled); - } + setEnabled(Lifespan.nowOn(snap), enabled); } @Override public boolean isEnabled(long snap) { try (LockHold hold = object.getTrace().lockRead()) { Boolean locEn = TraceObjectInterfaceUtils.getValue(object, snap, - TraceObjectTogglable.KEY_ENABLED, Boolean.class, null); + TraceTogglable.KEY_ENABLED, Boolean.class, null); if (locEn != null) { return locEn && getSpecification().isEnabled(snap); } @@ -191,31 +188,6 @@ public class DBTraceObjectBreakpointLocation } } - @Override - public void setKinds(Lifespan lifespan, Collection 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 kinds) { - try (LockHold hold = object.getTrace().lockWrite()) { - setKinds(Lifespan.nowOn(snap), kinds); - } - } - - @Override - public Set getKinds(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return getSpecification().getKinds(snap); - } - } - @Override public Set getThreads(long snap) { // TODO: Delete this? It's sort of deprecated out the gate anyway.... @@ -223,17 +195,17 @@ public class DBTraceObjectBreakpointLocation TraceObjectSchema schema = manager.getRootSchema(); try (LockHold hold = object.getTrace().lockRead()) { Set threads = - object.queryAncestorsInterface(Lifespan.at(snap), TraceObjectThread.class) + object.queryAncestorsInterface(Lifespan.at(snap), TraceThread.class) .collect(Collectors.toSet()); if (!threads.isEmpty()) { return threads; } - PathFilter procFilter = schema.searchFor(TraceObjectProcess.class, false); + PathFilter procFilter = schema.searchFor(TraceProcess.class, false); Lifespan lifespan = Lifespan.at(snap); return object.getAncestorsRoot(lifespan, procFilter) .flatMap(proc -> proc.getSource(object) - .querySuccessorsInterface(lifespan, TraceObjectThread.class, true)) + .querySuccessorsInterface(lifespan, TraceThread.class, true)) .collect(Collectors.toSet()); } } @@ -245,9 +217,7 @@ public class DBTraceObjectBreakpointLocation @Override public void setComment(long snap, String comment) { - try (LockHold hold = object.getTrace().lockWrite()) { - setComment(Lifespan.nowOn(snap), comment); - } + setComment(Lifespan.nowOn(snap), comment); } @Override @@ -258,11 +228,11 @@ public class DBTraceObjectBreakpointLocation if (!comment.isBlank()) { return comment; } - TraceObjectBreakpointSpec spec = getSpecification(); + TraceBreakpointSpec spec = getSpecification(); if (spec == null) { return ""; } - return spec.getExpression(snap); + return spec.getComment(snap); } } @@ -340,20 +310,20 @@ public class DBTraceObjectBreakpointLocation return object; } - public TraceObjectBreakpointSpec getOrCreateSpecification() { - return object.queryOrCreateCanonicalAncestorInterface(TraceObjectBreakpointSpec.class); + public TraceBreakpointSpec getOrCreateSpecification() { + return object.queryOrCreateCanonicalAncestorInterface(TraceBreakpointSpec.class); } @Override - public TraceObjectBreakpointSpec getSpecification() { + public TraceBreakpointSpec getSpecification() { try (LockHold hold = object.getTrace().lockRead()) { - return object.queryCanonicalAncestorsInterface(TraceObjectBreakpointSpec.class) + return object.queryCanonicalAncestorsInterface(TraceBreakpointSpec.class) .findAny() .orElseThrow(); } } - public TraceAddressSpace getTraceAddressSpace(long snap) { + public AddressSpace getAddressSpace(long snap) { return spaceForValue(snap, KEY_RANGE); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManager.java index e8e80ec1c8..7bfd9eef70 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManager.java @@ -17,146 +17,89 @@ package ghidra.trace.database.breakpoint; import java.io.IOException; import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import db.DBHandle; import ghidra.framework.data.OpenMode; -import ghidra.program.model.address.*; -import ghidra.program.model.lang.Language; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressRange; import ghidra.trace.database.DBTrace; -import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager; -import ghidra.trace.database.space.DBTraceDelegatingManager; -import ghidra.trace.database.thread.DBTraceThreadManager; +import ghidra.trace.database.DBTraceManager; +import ghidra.trace.database.target.DBTraceObjectManager; import ghidra.trace.model.Lifespan; import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.thread.TraceThread; -import ghidra.util.LockHold; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; -public class DBTraceBreakpointManager - extends AbstractDBTraceSpaceBasedManager - implements TraceBreakpointManager, DBTraceDelegatingManager { - protected static final String NAME = "Breakpoint"; +public class DBTraceBreakpointManager implements TraceBreakpointManager, DBTraceManager { + protected final ReadWriteLock lock; + protected final DBTrace trace; + protected final DBTraceObjectManager objectManager; public DBTraceBreakpointManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock, - TaskMonitor monitor, Language baseLanguage, DBTrace trace, - DBTraceThreadManager threadManager) throws VersionException, IOException { - super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager); - - loadSpaces(); - } - - @Override - protected DBTraceBreakpointSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) + TaskMonitor monitor, DBTrace trace, DBTraceObjectManager objectManager) throws VersionException, IOException { - return new DBTraceBreakpointSpace(this, dbh, space, ent); + this.lock = lock; + this.trace = trace; + this.objectManager = objectManager; } @Override - protected DBTraceBreakpointSpace createRegisterSpace(AddressSpace space, TraceThread thread, - DBTraceSpaceEntry ent) throws VersionException, IOException { - throw new UnsupportedOperationException(); + public void dbError(IOException e) { + trace.dbError(e); } @Override - public DBTraceBreakpointSpace getForSpace(AddressSpace space, boolean createIfAbsent) { - return super.getForSpace(space, createIfAbsent); + public void invalidateCache(boolean all) { + // NOTE: This is only a wrapper around the object manager } @Override - public Lock readLock() { - return lock.readLock(); - } - - @Override - public Lock writeLock() { - return lock.writeLock(); - } - - protected void checkDuplicatePath(TraceBreakpoint ignore, String path, Lifespan lifespan) - throws DuplicateNameException { - for (TraceBreakpoint pc : getBreakpointsByPath(path)) { - if (pc == ignore) { - continue; - } - if (!pc.isAlive(lifespan)) { - continue; - } - throw new DuplicateNameException("A breakpoint having path '" + path + - "' already exists within an overlapping snap"); - } - } - - @Override - public TraceBreakpoint addBreakpoint(String path, Lifespan lifespan, AddressRange range, + public TraceBreakpointLocation addBreakpoint(String path, Lifespan lifespan, AddressRange range, Collection threads, Collection kinds, boolean enabled, String comment) throws DuplicateNameException { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment); - } - checkDuplicatePath(null, path, lifespan); - return delegateWrite(range.getAddressSpace(), - m -> m.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment)); + return objectManager.addBreakpoint(path, lifespan, range, threads, kinds, enabled, comment); } @Override - public Collection getAllBreakpoints() { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getAllObjects(TraceObjectBreakpointLocation.class); - } - return delegateCollection(getActiveMemorySpaces(), m -> m.getAllBreakpoints()); + public Collection getAllBreakpointSpecifications() { + return objectManager.getAllObjects(TraceBreakpointSpec.class); } @Override - public Collection getBreakpointsByPath(String path) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsByPath(path, TraceObjectBreakpointLocation.class); - } - return delegateCollection(getActiveMemorySpaces(), m -> m.getBreakpointsByPath(path)); + public Collection getAllBreakpointLocations() { + return objectManager.getAllObjects(TraceBreakpointLocation.class); } @Override - public TraceBreakpoint getPlacedBreakpointByPath(long snap, String path) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectByPath(snap, path, TraceObjectBreakpointLocation.class); - } - try (LockHold hold = LockHold.lock(lock.readLock())) { - return getBreakpointsByPath(path).stream() - .filter(b -> b.isValid(snap)) - .findAny() - .orElse(null); - } + public Collection getBreakpointSpecificationsByPath( + String path) { + return objectManager.getObjectsByPath(path, TraceBreakpointSpec.class); } @Override - public Collection getBreakpointsAt(long snap, Address address) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsContaining(snap, address, - TraceObjectBreakpointLocation.KEY_RANGE, - TraceObjectBreakpointLocation.class); - } - return delegateRead(address.getAddressSpace(), m -> m.getBreakpointsAt(snap, address), - Collections.emptyList()); + public Collection getBreakpointLocationsByPath(String path) { + return objectManager.getObjectsByPath(path, TraceBreakpointLocation.class); } @Override - public Collection getBreakpointsIntersecting(Lifespan span, + public TraceBreakpointLocation getPlacedBreakpointByPath(long snap, String path) { + return objectManager.getObjectByPath(snap, path, TraceBreakpointLocation.class); + } + + @Override + public Collection getBreakpointsAt(long snap, + Address address) { + return objectManager.getObjectsContaining(snap, address, TraceBreakpointLocation.KEY_RANGE, + TraceBreakpointLocation.class); + } + + @Override + public Collection getBreakpointsIntersecting(Lifespan span, AddressRange range) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsIntersecting(span, range, - TraceObjectBreakpointLocation.KEY_RANGE, - TraceObjectBreakpointLocation.class); - } - return delegateRead(range.getAddressSpace(), m -> m.getBreakpointsIntersecting(span, range), - Collections.emptyList()); + return objectManager.getObjectsIntersecting(span, range, TraceBreakpointLocation.KEY_RANGE, + TraceBreakpointLocation.class); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointSpace.java deleted file mode 100644 index 9cf931ec41..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointSpace.java +++ /dev/null @@ -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 breakpointMapSpace; - protected final DBCachedObjectIndex breakpointsByPath; - protected final Collection 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.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 threads, Collection 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 getAllBreakpoints() { - return breakpointMapSpace.values(); - } - - public Collection getBreakpointsByPath(String name) { - return Collections.unmodifiableCollection(breakpointsByPath.get(name)); - } - - public Collection getBreakpointsAt(long snap, Address address) { - return Collections.unmodifiableCollection( - breakpointMapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).values()); - } - - public Collection 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(); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceObjectBreakpointSpec.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointSpec.java similarity index 59% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceObjectBreakpointSpec.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointSpec.java index b07424a0c9..b32d06961c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceObjectBreakpointSpec.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/breakpoint/DBTraceBreakpointSpec.java @@ -18,8 +18,7 @@ package ghidra.trace.database.breakpoint; import java.util.*; import java.util.stream.Collectors; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRange; +import ghidra.program.model.address.AddressSpace; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.Lifespan; @@ -28,17 +27,15 @@ import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.iface.TraceObjectTogglable; +import ghidra.trace.model.target.iface.TraceTogglable; import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.*; +import ghidra.trace.util.TraceChangeRecord; +import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; import ghidra.util.Msg; -public class DBTraceObjectBreakpointSpec - implements TraceObjectBreakpointSpec, DBTraceObjectInterface { +public class DBTraceBreakpointSpec implements TraceBreakpointSpec, DBTraceObjectInterface { private static final Map> KEYS_BY_SCHEMA = new WeakHashMap<>(); private final DBTraceObject object; @@ -46,13 +43,13 @@ public class DBTraceObjectBreakpointSpec private TraceBreakpointKindSet kinds = TraceBreakpointKindSet.of(); - public DBTraceObjectBreakpointSpec(DBTraceObject object) { + public DBTraceBreakpointSpec(DBTraceObject object) { this.object = object; TraceObjectSchema schema = object.getSchema(); synchronized (KEYS_BY_SCHEMA) { keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, - s -> Set.of(schema.checkAliasedAttribute(TraceObjectBreakpointSpec.KEY_KINDS), - schema.checkAliasedAttribute(TraceObjectTogglable.KEY_ENABLED))); + s -> Set.of(schema.checkAliasedAttribute(KEY_KINDS), + schema.checkAliasedAttribute(TraceTogglable.KEY_ENABLED))); } } @@ -66,51 +63,35 @@ public class DBTraceObjectBreakpointSpec return object.getCanonicalPath().toString(); } + @Override + public void setName(Lifespan lifespan, String name) { + object.setValue(lifespan, KEY_DISPLAY, name); + } + @Override public void setName(long snap, String name) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(Lifespan.nowOn(snap), TraceObjectInterface.KEY_DISPLAY, name); - } + setName(Lifespan.nowOn(snap), name); } @Override public String getName(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectInterface.KEY_DISPLAY, - String.class, ""); + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, ""); } @Override - public AddressRange getRange(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); - } - - @Override - public Address getMinAddress(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); - } - - @Override - public Address getMaxAddress(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); - } - - @Override - public long getLength(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); + public void setEnabled(Lifespan lifespan, boolean enabled) { + object.setValue(lifespan, TraceTogglable.KEY_ENABLED, enabled ? true : null); } @Override public void setEnabled(long snap, boolean enabled) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(Lifespan.nowOn(snap), TraceObjectTogglable.KEY_ENABLED, - enabled ? true : null); - } + setEnabled(Lifespan.nowOn(snap), enabled); } @Override public boolean isEnabled(long snap) { return TraceObjectInterfaceUtils.getValue(object, snap, - TraceObjectTogglable.KEY_ENABLED, Boolean.class, false); + TraceTogglable.KEY_ENABLED, Boolean.class, false); } @Override @@ -118,8 +99,7 @@ public class DBTraceObjectBreakpointSpec // TODO: More efficient encoding // TODO: Target-Trace mapping is implied by encoded name. Seems bad. try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(lifespan, TraceObjectBreakpointSpec.KEY_KINDS, - TraceBreakpointKindSet.encode(kinds)); + object.setValue(lifespan, KEY_KINDS, TraceBreakpointKindSet.encode(kinds)); this.kinds = TraceBreakpointKindSet.copyOf(kinds); } } @@ -133,8 +113,8 @@ public class DBTraceObjectBreakpointSpec @Override public Set getKinds(long snap) { - String kindsStr = TraceObjectInterfaceUtils.getValue(object, snap, - TraceObjectBreakpointSpec.KEY_KINDS, String.class, null); + String kindsStr = + TraceObjectInterfaceUtils.getValue(object, snap, KEY_KINDS, String.class, null); if (kindsStr == null) { return kinds; } @@ -149,43 +129,24 @@ public class DBTraceObjectBreakpointSpec @Override public String getExpression(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, - TraceObjectBreakpointSpec.KEY_EXPRESSION, String.class, null); + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_EXPRESSION, String.class, null); } @Override - public Set getThreads(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); + public void setComment(Lifespan lifespan, String comment) { + object.setValue(lifespan, KEY_COMMENT, comment); } @Override public void setComment(long snap, String comment) { - throw new UnsupportedOperationException("Set on a location instead"); + setComment(Lifespan.nowOn(snap), comment); } @Override public String getComment(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); - } - - @Override - public void setEmuEnabled(long snap, boolean enabled) { - throw new UnsupportedOperationException("Set on a location instead"); - } - - @Override - public boolean isEmuEnabled(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); - } - - @Override - public void setEmuSleigh(long snap, String sleigh) { - throw new UnsupportedOperationException("Set on a location instead"); - } - - @Override - public String getEmuSleigh(long snap) { - throw new UnsupportedOperationException("Ask a location instead"); + try (LockHold hold = object.getTrace().lockRead()) { + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_COMMENT, String.class, ""); + } } @Override @@ -217,15 +178,15 @@ public class DBTraceObjectBreakpointSpec return object; } - protected Collection getLocations(Lifespan span) { + protected Collection getLocations(Lifespan span) { try (LockHold hold = object.getTrace().lockRead()) { - return object.querySuccessorsInterface(span, TraceObjectBreakpointLocation.class, true) + return object.querySuccessorsInterface(span, TraceBreakpointLocation.class, true) .collect(Collectors.toSet()); } } @Override - public Collection getLocations(long snap) { + public Collection getLocations(long snap) { return getLocations(Lifespan.at(snap)); } @@ -243,9 +204,9 @@ public class DBTraceObjectBreakpointSpec if (object.getCanonicalParent(affected.getMaxSnap()) == null) { return null; // Incomplete object } - for (TraceObjectBreakpointLocation loc : getLocations(affected.getLifespan())) { - DBTraceObjectBreakpointLocation dbLoc = (DBTraceObjectBreakpointLocation) loc; - TraceAddressSpace space = dbLoc.getTraceAddressSpace(affected.getMinSnap()); + for (TraceBreakpointLocation loc : getLocations(affected.getLifespan())) { + DBTraceBreakpointLocation dbLoc = (DBTraceBreakpointLocation) loc; + AddressSpace space = dbLoc.getAddressSpace(affected.getMinSnap()); TraceChangeRecord evt = new TraceChangeRecord<>(TraceEvents.BREAKPOINT_CHANGED, space, loc, null, null); object.getTrace().setChanged(evt); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextManager.java index 83fc334ac4..7708a7a706 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextManager.java @@ -4,9 +4,9 @@ * 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. @@ -101,14 +101,7 @@ public class DBTraceRegisterContextManager @Override protected DBTraceRegisterContextSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException { - return new DBTraceRegisterContextSpace(this, dbh, space, ent, null); - } - - @Override - protected DBTraceRegisterContextSpace createRegisterSpace(AddressSpace space, - TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { - // TODO: Should I just forbid this? It doesn't seem sane. Then again, what do I know? - return new DBTraceRegisterContextSpace(this, dbh, space, ent, thread); + return new DBTraceRegisterContextSpace(this, dbh, space, ent); } @Override @@ -205,7 +198,7 @@ public class DBTraceRegisterContextManager @Override public AddressSetView getRegisterValueAddressRanges(Language language, Register register, long snap) { - return delegateAddressSet(getActiveMemorySpaces(), + return delegateAddressSet(getActiveSpaces(), m -> m.getRegisterValueAddressRanges(language, register, snap)); } @@ -218,8 +211,7 @@ public class DBTraceRegisterContextManager @Override public boolean hasRegisterValue(Language language, Register register, long snap) { - return delegateAny(getActiveMemorySpaces(), - m -> m.hasRegisterValue(language, register, snap)); + return delegateAny(getActiveSpaces(), m -> m.hasRegisterValue(language, register, snap)); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextSpace.java index 8aa1b79ebf..e5580944b5 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/context/DBTraceRegisterContextSpace.java @@ -4,9 +4,9 @@ * 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. @@ -39,7 +39,6 @@ import ghidra.trace.database.space.DBTraceSpaceBased; import ghidra.trace.model.*; import ghidra.trace.model.context.TraceRegisterContextSpace; import ghidra.trace.model.guest.TracePlatform; -import ghidra.trace.model.thread.TraceThread; import ghidra.util.LockHold; import ghidra.util.database.*; import ghidra.util.database.annot.*; @@ -79,8 +78,6 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D protected final DBTraceRegisterContextManager manager; protected final DBHandle dbh; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final ReadWriteLock lock; protected final Language baseLanguage; protected final DBTrace trace; @@ -91,13 +88,10 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D new HashMap<>(); public DBTraceRegisterContextSpace(DBTraceRegisterContextManager manager, DBHandle dbh, - AddressSpace space, DBTraceSpaceEntry ent, TraceThread thread) - throws VersionException, IOException { + AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException { this.manager = manager; this.dbh = dbh; this.space = space; - this.thread = thread; - this.frameLevel = ent.getFrameLevel(); this.lock = manager.getLock(); this.baseLanguage = manager.getBaseLanguage(); this.trace = manager.getTrace(); @@ -105,8 +99,7 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - registerStore = factory.getOrCreateCachedStore( - DBTraceUtils.tableName(TABLE_NAME, space, ent.getThreadKey(), ent.getFrameLevel()), + registerStore = factory.getOrCreateCachedStore(DBTraceUtils.tableName(TABLE_NAME, space), DBTraceRegisterEntry.class, DBTraceRegisterEntry::new, true); loadRegisterValueMaps(); @@ -125,28 +118,18 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D } } + @Override + public DBTrace getTrace() { + return trace; + } + @Override public AddressSpace getAddressSpace() { return space; } - @Override - public TraceThread getThread() { - return thread; - } - - protected long getThreadKey() { - TraceThread thread = getThread(); - return thread == null ? -1 : thread.getKey(); - } - - @Override - public int getFrameLevel() { - return frameLevel; - } - protected String tableName(Language language, Register register) { - return DBTraceUtils.tableName(TABLE_NAME, space, getThreadKey(), getFrameLevel()) + "_" + + return DBTraceUtils.tableName(TABLE_NAME, space) + "_" + language.getLanguageID().getIdAsString() + "_" + register.getName(); } @@ -154,9 +137,9 @@ public class DBTraceRegisterContextSpace implements TraceRegisterContextSpace, D Pair lr) throws VersionException { String name = tableName(lr.getLeft(), lr.getRight()); try { - return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace.getStoreFactory(), - lock, space, thread, frameLevel, DBTraceRegisterContextEntry.class, - DBTraceRegisterContextEntry::new); + return new DBTraceAddressSnapRangePropertyMapSpace<>(name, trace, + trace.getStoreFactory(), lock, space, + DBTraceRegisterContextEntry.class, DBTraceRegisterContextEntry::new); } catch (IOException e) { manager.dbError(e); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/data/DBTraceDataSettingsAdapter.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/data/DBTraceDataSettingsAdapter.java index 566a974547..10d6a21424 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/data/DBTraceDataSettingsAdapter.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/data/DBTraceDataSettingsAdapter.java @@ -4,9 +4,9 @@ * 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. @@ -158,12 +158,12 @@ public class DBTraceDataSettingsAdapter public class DBTraceDataSettingsSpace extends DBTraceAddressSnapRangePropertyMapSpace implements DBTraceDataSettingsOperations { - public DBTraceDataSettingsSpace(String tableName, DBCachedObjectStoreFactory storeFactory, - ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel, + public DBTraceDataSettingsSpace(String tableName, DBTrace trace, + DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space, Class dataType, DBTraceAddressSnapRangePropertyMapDataFactory dataFactory) throws VersionException, IOException { - super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory); + super(tableName, trace, storeFactory, lock, space, dataType, dataFactory); } @Override @@ -187,17 +187,8 @@ public class DBTraceDataSettingsAdapter @Override protected DBTraceDataSettingsSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException { - return new DBTraceDataSettingsSpace( - tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), - lock, space, null, 0, dataType, dataFactory); - } - - @Override - protected DBTraceDataSettingsSpace createRegisterSpace(AddressSpace space, TraceThread thread, - DBTraceSpaceEntry ent) throws VersionException, IOException { - return new DBTraceDataSettingsSpace( - tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), - lock, space, thread, ent.getFrameLevel(), dataType, dataFactory); + return new DBTraceDataSettingsSpace(tableName(space), trace, trace.getStoreFactory(), lock, + space, dataType, dataFactory); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceGuestPlatform.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceGuestPlatform.java index 6336111657..468a8a0803 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceGuestPlatform.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceGuestPlatform.java @@ -227,8 +227,8 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject hostAddressSet.delete(hostRange); guestAddressSet.delete(guestRange); } - manager.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.PLATFORM_MAPPING_DELETED, null, this, range, null)); + manager.trace.setChanged(new TraceChangeRecord<>(TraceEvents.PLATFORM_MAPPING_DELETED, + range.getHostRange().getAddressSpace(), this, range, null)); } @Override @@ -280,8 +280,8 @@ public class DBTraceGuestPlatform extends DBAnnotatedObject hostAddressSet.add(mappedRange.getHostRange()); guestAddressSet.add(mappedRange.getGuestRange()); } - manager.trace.setChanged(new TraceChangeRecord<>(TraceEvents.PLATFORM_MAPPING_ADDED, null, - this, null, mappedRange)); + manager.trace.setChanged(new TraceChangeRecord<>(TraceEvents.PLATFORM_MAPPING_ADDED, + hostStart.getAddressSpace(), this, null, mappedRange)); return mappedRange; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupport.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupport.java index 2f53cd60b8..97a6b0f6ad 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupport.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupport.java @@ -51,7 +51,7 @@ public enum DBTraceObjectRegisterSupport { protected AddressSpace findRegisterOverlay(TraceObject object) { TraceObject container = object - .findCanonicalAncestorsInterface(TraceObjectRegisterContainer.class) + .findCanonicalAncestorsInterface(TraceRegisterContainer.class) .findFirst() .orElse(null); if (container == null) { @@ -124,7 +124,7 @@ public enum DBTraceObjectRegisterSupport { return; } for (TraceObjectValue registerValue : it(registerObject.getOrderedValues(Lifespan.ALL, - TraceObjectRegister.KEY_VALUE, true))) { + TraceRegister.KEY_VALUE, true))) { transferValueToPlatformRegister(registerValue, platform, mem, register); } } @@ -132,7 +132,7 @@ public enum DBTraceObjectRegisterSupport { protected void onSpaceAddedCheckTransferToPlatformRegisters(TracePlatform platform, TraceObject regContainer, TraceMemorySpace mem) { for (TraceObjectValPath path : it( - regContainer.findSuccessorsInterface(Lifespan.ALL, TraceObjectRegister.class, + regContainer.findSuccessorsInterface(Lifespan.ALL, TraceRegister.class, true))) { TraceObject registerObject = path.getDestination(platform.getTrace().getObjectManager().getRootObject()); @@ -174,7 +174,7 @@ public enum DBTraceObjectRegisterSupport { TraceMemorySpace mem = getMemorySpace(registerObject, label); Address address = mem.getAddressSpace().getOverlayAddress(label.getAddress()); for (TraceObjectValue registerValue : it(registerObject.getOrderedValues( - label.getLifespan(), TraceObjectRegister.KEY_VALUE, true))) { + label.getLifespan(), TraceRegister.KEY_VALUE, true))) { RegisterValueConverter rvc = new RegisterValueConverter(registerValue); try { long minSnap = registerValue.getMinSnap(); @@ -225,8 +225,8 @@ public enum DBTraceObjectRegisterSupport { protected boolean isRegisterValue(TraceObjectValue objectValue) { TraceObject parent = objectValue.getParent(); return parent != null && - parent.getSchema().getInterfaces().contains(TraceObjectRegister.class) && - TraceObjectRegister.KEY_VALUE.equals(objectValue.getEntryKey()); + parent.getSchema().getInterfaces().contains(TraceRegister.class) && + TraceRegister.KEY_VALUE.equals(objectValue.getEntryKey()); } public void onValueCreatedCheckTransfer(TraceObjectValue objectValue) { @@ -246,7 +246,7 @@ public enum DBTraceObjectRegisterSupport { if (schema == null) { return; } - PathFilter filter = schema.searchFor(TraceObjectRegister.class, true); + PathFilter filter = schema.searchFor(TraceRegister.class, true); PathFilter applied = filter.applyKeys(Align.RIGHT, List.of(label.getName())); for (TraceObjectValPath path : it( objectManager.getValuePaths(label.getLifespan(), applied))) { @@ -292,7 +292,7 @@ public enum DBTraceObjectRegisterSupport { KeyPath.parse(mem.getAddressSpace().getName())); if (regContainer == null || !regContainer.getSchema() .getInterfaces() - .contains(TraceObjectRegisterContainer.class)) { + .contains(TraceRegisterContainer.class)) { return; } TracePlatformManager platformManager = trace.getPlatformManager(); @@ -320,7 +320,7 @@ public enum DBTraceObjectRegisterSupport { .getMemoryManager() .getMemorySpace(hostAddr.getAddressSpace(), true); for (TraceObjectValue registerValue : it(registerObject.getOrderedValues(Lifespan.ALL, - TraceObjectRegister.KEY_VALUE, true))) { + TraceRegister.KEY_VALUE, true))) { transferValueToPlatformRegister(registerValue, guest, mem, register); } } @@ -328,7 +328,7 @@ public enum DBTraceObjectRegisterSupport { public void onMappingAddedCheckTransferMemoryMapped(TraceObject root, TraceGuestPlatformMappedRange mapped) { for (TraceObjectValPath path : it( - root.findSuccessorsInterface(Lifespan.ALL, TraceObjectRegister.class, true))) { + root.findSuccessorsInterface(Lifespan.ALL, TraceRegister.class, true))) { TraceObject registerObject = path.getDestination(root); onMappingAddedCheckTransferRegisterObjectMemoryMapped(registerObject, mapped); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java index 0004099c6e..5bd73eddc8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java @@ -22,7 +22,7 @@ import ghidra.program.model.lang.*; import ghidra.program.model.symbol.SourceType; import ghidra.trace.database.guest.DBTraceGuestPlatform.DBTraceGuestLanguage; import ghidra.trace.model.guest.TracePlatform; -import ghidra.trace.model.memory.TraceObjectRegister; +import ghidra.trace.model.memory.TraceRegister; import ghidra.trace.model.symbol.*; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.path.*; @@ -103,7 +103,7 @@ public interface InternalTracePlatform extends TracePlatform, ProgramArchitectur TraceSymbolManager symbolManager = getTrace().getSymbolManager(); TraceNamespaceSymbol nsRegMap = symbolManager.namespaces().getGlobalNamed(regMap(register)); Collection labels = symbolManager.labels() - .getAt(0, null, pmin, false) + .getAt(0, pmin, false) .stream() .filter(s -> s.getParentNamespace() == nsRegMap) .map(TraceSymbol::getName) @@ -117,7 +117,7 @@ public interface InternalTracePlatform extends TracePlatform, ProgramArchitectur @Override default PathFilter getConventionalRegisterPath(TraceObjectSchema schema, KeyPath path, Collection names) { - PathFilter filter = schema.searchFor(TraceObjectRegister.class, path, true); + PathFilter filter = schema.searchFor(TraceRegister.class, path, true); if (filter.isNone()) { return PathFilter.NONE; } @@ -166,12 +166,12 @@ public interface InternalTracePlatform extends TracePlatform, ProgramArchitectur nsRegMap = namespaces.add(regMap, globals, SourceType.USER_DEFINED); } TraceLabelSymbol exists = symbolManager.labels() - .getChildWithNameAt(objectName, getIntKey(), null, hostAddr, nsRegMap); + .getChildWithNameAt(objectName, getIntKey(), hostAddr, nsRegMap); if (exists != null) { return exists; } return symbolManager.labels() - .create(0, null, hostAddr, objectName, nsRegMap, SourceType.USER_DEFINED); + .create(0, hostAddr, objectName, nsRegMap, SourceType.USER_DEFINED); } catch (DuplicateNameException | InvalidInputException e) { // I checked for the namespace first and with a write lock diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceCodeUnitsMemoryView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceCodeUnitsMemoryView.java index 51684102d6..71d948abff 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceCodeUnitsMemoryView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceCodeUnitsMemoryView.java @@ -226,7 +226,7 @@ public abstract class AbstractBaseDBTraceCodeUnitsMemoryView(TraceEvents.CODE_REMOVED, space, unit.getBounds(), unit, null)); + space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.CODE_REMOVED, space.space, + unit.getBounds(), unit, null)); } /** @@ -353,8 +353,8 @@ public abstract class AbstractBaseDBTraceDefinedUnitsView(TraceEvents.CODE_LIFESPAN_CHANGED, space, - unit, oldSpan, unit.getLifespan())); + space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.CODE_LIFESPAN_CHANGED, + space.space, unit, oldSpan, unit.getLifespan())); } /** diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractDBTraceCodeUnit.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractDBTraceCodeUnit.java index 24f8b900cd..40bcdf1664 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractDBTraceCodeUnit.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractDBTraceCodeUnit.java @@ -4,9 +4,9 @@ * 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. @@ -24,7 +24,6 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData; import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; import ghidra.util.LockHold; import ghidra.util.database.DBCachedObjectStore; @@ -59,11 +58,6 @@ public abstract class AbstractDBTraceCodeUnit byteCache.position()) { byteCache.limit(Math.min(byteCache.capacity(), end)); // TODO: Retrieve the memory space at code space construction time - DBTraceMemorySpace mem = space.trace.getMemoryManager().get(space, false); + DBTraceMemorySpace mem = space.trace.getMemoryManager().get(space.space, false); mem.getViewBytes(getStartSnap(), address.add(byteCache.position()), byteCache); } // Copy from the cache @@ -135,7 +129,7 @@ public abstract class AbstractDBTraceCodeUnit> changes = new ArrayList<>(); - for (DBTraceCodeSpace space : memSpaces.values()) { + for (DBTraceCodeSpace space : spaces.values()) { changes.addAll( space.dataMapSpace.reduce(TraceAddressSnapRangeQuery.added(from, to, space.space)) .values()); @@ -642,7 +621,7 @@ public class DBTraceCodeManager extends AbstractDBTraceSpaceBasedManager> changes = new ArrayList<>(); - for (DBTraceCodeSpace space : memSpaces.values()) { + for (DBTraceCodeSpace space : spaces.values()) { changes.addAll( space.dataMapSpace.reduce(TraceAddressSnapRangeQuery.removed(from, to, space.space)) .values()); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeSpace.java index f0966db6ff..348bbd1773 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeSpace.java @@ -58,8 +58,6 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased { protected final DBTraceCodeManager manager; protected final DBHandle dbh; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final ReadWriteLock lock; protected final Language baseLanguage; protected final DBTrace trace; @@ -85,17 +83,14 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased { * @param dbh the database handle * @param space the address space * @param ent an entry describing this space - * @param thread a thread, if applicable, for a per-thread/frame space * @throws VersionException if there is already a table of a different version * @throws IOException if there is trouble accessing the database */ public DBTraceCodeSpace(DBTraceCodeManager manager, DBHandle dbh, AddressSpace space, - DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException { + DBTraceSpaceEntry ent) throws VersionException, IOException { this.manager = manager; this.dbh = dbh; this.space = space; - this.thread = thread; - this.frameLevel = ent.getFrameLevel(); this.lock = manager.getLock(); this.baseLanguage = manager.getBaseLanguage(); this.trace = manager.getTrace(); @@ -105,14 +100,11 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased { DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - long threadKey = ent.getThreadKey(); - int frameLevel = ent.getFrameLevel(); - instructionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceInstruction.tableName(space, threadKey), factory, lock, space, null, 0, + DBTraceInstruction.tableName(space), trace, factory, lock, space, DBTraceInstruction.class, (t, s, r) -> new DBTraceInstruction(this, t, s, r)); dataMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceData.tableName(space, threadKey, frameLevel), factory, lock, space, null, 0, + DBTraceData.tableName(space), trace, factory, lock, space, DBTraceData.class, (t, s, r) -> new DBTraceData(this, t, s, r)); instructions = createInstructionsView(); @@ -211,21 +203,16 @@ public class DBTraceCodeSpace implements TraceCodeSpace, DBTraceSpaceBased { } } + @Override + public DBTrace getTrace() { + return trace; + } + @Override public AddressSpace getAddressSpace() { return space; } - @Override - public TraceThread getThread() { - return thread; - } - - @Override - public int getFrameLevel() { - return frameLevel; - } - @Override public DBTraceCodeUnitsView codeUnits() { return codeUnits; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeUnitAdapter.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeUnitAdapter.java index ef6abe410d..5372c0fd6c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeUnitAdapter.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCodeUnitAdapter.java @@ -15,16 +15,16 @@ */ package ghidra.trace.database.listing; -import static ghidra.lifecycle.Unfinished.*; +import static ghidra.lifecycle.Unfinished.TODO; import java.nio.ByteBuffer; -import java.util.*; +import java.util.Collection; +import java.util.Iterator; import java.util.Map.Entry; import org.apache.commons.collections4.IteratorUtils; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRangeImpl; +import ghidra.program.model.address.*; import ghidra.program.model.lang.Register; import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.CommentType; @@ -39,7 +39,6 @@ import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.property.*; import ghidra.trace.model.symbol.TraceReference; import ghidra.trace.model.symbol.TraceSymbol; -import ghidra.trace.model.thread.TraceThread; import ghidra.util.LockHold; import ghidra.util.Saveable; import ghidra.util.exception.NoValueException; @@ -58,13 +57,7 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { @Override default TraceProgramView getProgram() { - TraceThread thread = getThread(); - TraceProgramView view = getTrace().getProgramView(); - if (thread == null) { - return view; - } - // Non-null: How could a unit be here otherwise? - return Objects.requireNonNull(view.getViewRegisters(thread, false)); + return getTrace().getProgramView(); } // TODO: Do I delete comments when code unit is deleted? @@ -88,12 +81,17 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { } } + default AddressSpace getAddressSpace() { + return getAddress().getAddressSpace(); + } + @Override default void setProperty(String name, Class valueClass, T value) { try (LockHold hold = LockHold.lock(getTrace().getReadWriteLock().writeLock())) { TracePropertyMap map = getTrace().getInternalAddressPropertyManager() .getOrCreatePropertyMapSuper(name, valueClass); - TracePropertyMapSpace space = map.getPropertyMapSpace(getTraceSpace(), true); + TracePropertyMapSpace space = + map.getPropertyMapSpace(getAddressSpace(), true); space.set(getLifespan(), getAddress(), value); } } @@ -107,7 +105,6 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { @Override default void setProperty(String name, Saveable value) { - // TODO: It'd be better if the CodeUnit interface took a valueClass variable... setTypedProperty(name, value); } @@ -135,7 +132,7 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { return null; } TracePropertyMapSpace space = - map.getPropertyMapSpace(getTraceSpace(), false); + map.getPropertyMapSpace(getAddressSpace(), false); if (space == null) { return null; } @@ -185,7 +182,7 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { if (map == null) { return false; } - TracePropertyMapSpace space = map.getPropertyMapSpace(getTraceSpace(), false); + TracePropertyMapSpace space = map.getPropertyMapSpace(getAddressSpace(), false); if (space == null) { return false; } @@ -224,9 +221,8 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { @Override default Symbol[] getSymbols() { try (LockHold hold = getTrace().lockRead()) { - Collection at = getTrace().getSymbolManager() - .labels() - .getAt(getStartSnap(), getThread(), getAddress(), true); + Collection at = + getTrace().getSymbolManager().labels().getAt(getStartSnap(), getAddress(), true); return at.toArray(new TraceSymbol[at.size()]); } } @@ -234,9 +230,8 @@ public interface DBTraceCodeUnitAdapter extends TraceCodeUnit, MemBufferMixin { @Override default Symbol getPrimarySymbol() { try (LockHold hold = getTrace().lockRead()) { - Collection at = getTrace().getSymbolManager() - .labels() - .getAt(getStartSnap(), getThread(), getAddress(), true); + Collection at = + getTrace().getSymbolManager().labels().getAt(getStartSnap(), getAddress(), true); if (at.isEmpty()) { return null; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCommentAdapter.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCommentAdapter.java index ef8e115444..ee373953b0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCommentAdapter.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceCommentAdapter.java @@ -34,7 +34,6 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMap; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; -import ghidra.trace.database.space.DBTraceSpaceKey; import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.model.*; import ghidra.trace.util.TraceChangeRecord; @@ -103,9 +102,6 @@ public class DBTraceCommentAdapter } } - /** - * Construct the adapter - */ public DBTraceCommentAdapter(DBHandle dbh, OpenMode openMode, ReadWriteLock lock, TaskMonitor monitor, Language baseLanguage, DBTrace trace, DBTraceThreadManager threadManager) throws IOException, VersionException { @@ -131,7 +127,8 @@ public class DBTraceCommentAdapter * * @param lifespan the lifespan * @param address the address - * @param commentType the type of comment as in {@link Listing#setComment(Address, int, String)} + * @param commentType the type of comment as in + * {@link Listing#setComment(Address, CommentType, String)} * @param comment the comment */ public void setComment(Lifespan lifespan, Address address, CommentType commentType, @@ -155,10 +152,9 @@ public class DBTraceCommentAdapter entry.set((byte) commentType.ordinal(), comment); } } - trace.setChanged(new TraceChangeRecord( - TraceEvents.byCommentType(commentType), - DBTraceSpaceKey.create(address.getAddressSpace(), null, 0), - new ImmutableTraceAddressSnapRange(address, lifespan), oldValue, comment)); + trace.setChanged(new TraceChangeRecord<>(TraceEvents.byCommentType(commentType), + address.getAddressSpace(), new ImmutableTraceAddressSnapRange(address, lifespan), + oldValue, comment)); } /** diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceData.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceData.java index 40bdce0a0e..eca019236a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceData.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceData.java @@ -52,8 +52,8 @@ public class DBTraceData extends AbstractDBTraceCodeUnit @DBAnnotatedColumn(DATATYPE_COLUMN_NAME) static DBObjectColumn DATATYPE_COLUMN; - static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField(column = PLATFORM_COLUMN_NAME) @@ -269,7 +269,7 @@ public class DBTraceData extends AbstractDBTraceCodeUnit @Override public DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent) { return (DBTraceDataSettingsOperations) getTrace().getDataSettingsAdapter() - .get(space, createIfAbsent); + .get(space.space, createIfAbsent); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataAdapter.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataAdapter.java index 7141534eda..e0420c4b28 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataAdapter.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataAdapter.java @@ -4,9 +4,9 @@ * 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. @@ -96,7 +96,7 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM getSettingsSpace(true).setLong(getLifespan(), getAddress(), name, value); } getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.CODE_DATA_SETTINGS_CHANGED, - getTraceSpace(), this.getBounds(), null, null)); + getAddressSpace(), this.getBounds(), null, null)); } @Override @@ -120,7 +120,7 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM getSettingsSpace(true).setString(getLifespan(), getAddress(), name, value); } getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.CODE_DATA_SETTINGS_CHANGED, - getTraceSpace(), this.getBounds(), null, null)); + getAddressSpace(), this.getBounds(), null, null)); } @Override @@ -145,7 +145,7 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM getSettingsSpace(true).setValue(getLifespan(), getAddress(), name, value); } getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.CODE_DATA_SETTINGS_CHANGED, - getTraceSpace(), this.getBounds(), null, null)); + getAddressSpace(), this.getBounds(), null, null)); } @Override @@ -173,7 +173,7 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM space.clear(getLifespan(), getAddress(), name); } getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.CODE_DATA_SETTINGS_CHANGED, - getTraceSpace(), this.getBounds(), null, null)); + getAddressSpace(), this.getBounds(), null, null)); } @Override @@ -186,7 +186,7 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM space.clear(getLifespan(), getAddress(), null); } getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.CODE_DATA_SETTINGS_CHANGED, - getTraceSpace(), this.getBounds(), null, null)); + getAddressSpace(), this.getBounds(), null, null)); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataArrayElementComponent.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataArrayElementComponent.java index 842acb62d6..bac3c6e285 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataArrayElementComponent.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataArrayElementComponent.java @@ -4,9 +4,9 @@ * 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. @@ -20,7 +20,6 @@ import ghidra.program.model.data.DataType; import ghidra.trace.database.DBTrace; import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange; -import ghidra.trace.util.TraceAddressSpace; /** * The implementation of an array-element data component in a {@link DBTrace} @@ -42,11 +41,6 @@ public class DBTraceDataArrayElementComponent extends AbstractDBTraceDataCompone super(root, parent, index, address, dataType, length); } - @Override - public TraceAddressSpace getTraceSpace() { - return parent.getTraceSpace(); - } - @Override public String getFieldName() { return "[" + index + "]"; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataCompositeFieldComponent.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataCompositeFieldComponent.java index 3e4953e536..e6b8c8bf79 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataCompositeFieldComponent.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDataCompositeFieldComponent.java @@ -4,9 +4,9 @@ * 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. @@ -20,7 +20,6 @@ import ghidra.program.model.data.DataTypeComponent; import ghidra.trace.database.DBTrace; import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange; -import ghidra.trace.util.TraceAddressSpace; /** * The implementation of a field data component in a {@link DBTrace} @@ -33,7 +32,6 @@ public class DBTraceDataCompositeFieldComponent extends AbstractDBTraceDataCompo * * @param root the root data unit * @param parent the parent component, possibly the root - * @param index the index of this component in its parent * @param address the minimum address of this component * @param dtc the data type component, giving the index, data type, and length */ @@ -43,11 +41,6 @@ public class DBTraceDataCompositeFieldComponent extends AbstractDBTraceDataCompo this.dtc = dtc; } - @Override - public TraceAddressSpace getTraceSpace() { - return parent.getTraceSpace(); - } - @Override public String getFieldName() { String fieldName = dtc.getFieldName(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDefinedDataView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDefinedDataView.java index c24a208004..37506e2038 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDefinedDataView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDefinedDataView.java @@ -76,7 +76,7 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView< throw new IllegalArgumentException("Platform is not part of this trace"); } try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - DBTraceMemorySpace memSpace = space.trace.getMemoryManager().get(space, true); + DBTraceMemorySpace memSpace = space.trace.getMemoryManager().get(space.space, true); // NOTE: User-given length could be ignored.... // Check start address first. After I know length, I can check for other existing units long startSnap = lifespan.lmin(); @@ -158,11 +158,11 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView< dataType instanceof Dynamic) { // TODO: Track composites? space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.COMPOSITE_DATA_ADDED, - space, tasr, created)); + space.space, tasr, created)); } space.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.CODE_ADDED, space, tasr, created)); + new TraceChangeRecord<>(TraceEvents.CODE_ADDED, space.space, tasr, created)); return created; } catch (AddressOverflowException e) { @@ -177,7 +177,7 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView< if (dataType instanceof Composite || dataType instanceof Array || dataType instanceof Dynamic) { space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.COMPOSITE_DATA_REMOVED, - space, unit.getBounds(), unit, null)); + space.space, unit.getBounds(), unit, null)); } } @@ -189,7 +189,7 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView< dataType instanceof Dynamic) { space.trace.setChanged( new TraceChangeRecord<>(TraceEvents.COMPOSITE_DATA_LIFESPAN_CHANGED, - space, unit, oldSpan, unit.getLifespan())); + space.space, unit, oldSpan, unit.getLifespan())); } } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java index 4e2bbb1502..729d46bca2 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java @@ -4,9 +4,9 @@ * 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. @@ -80,8 +80,8 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit(TraceEvents.INSTRUCTION_FLOW_OVERRIDE_CHANGED, space, this, - oldFlowOverride, flowOverride)); + space.trace.setChanged(new TraceChangeRecord<>( + TraceEvents.INSTRUCTION_FLOW_OVERRIDE_CHANGED, space.space, this, oldFlowOverride, + flowOverride)); } @Override @@ -602,9 +602,9 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit(TraceEvents.INSTRUCTION_LENGTH_OVERRIDE_CHANGED, space, this, - oldLengthOverride, length)); + space.trace.setChanged(new TraceChangeRecord<>( + TraceEvents.INSTRUCTION_LENGTH_OVERRIDE_CHANGED, space.space, this, oldLengthOverride, + length)); } private void updateLengthOverride(int length) { @@ -671,7 +671,7 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit { - DBTraceReferenceSpace refSpace = space.referenceManager.get(space, false); + DBTraceReferenceSpace refSpace = space.referenceManager.get(space.space, false); if (refSpace == null) { return; } @@ -729,9 +729,9 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit(TraceEvents.INSTRUCTION_FALL_THROUGH_OVERRIDE_CHANGED, space, - this, !overridden, overridden)); + space.trace.setChanged(new TraceChangeRecord<>( + TraceEvents.INSTRUCTION_FALL_THROUGH_OVERRIDE_CHANGED, space.space, this, !overridden, + overridden)); } @Override @@ -750,7 +750,7 @@ public class DBTraceInstruction extends AbstractDBTraceCodeUnit(TraceEvents.CODE_ADDED, space, created, created)); + new TraceChangeRecord<>(TraceEvents.CODE_ADDED, space.space, created, created)); return created; } catch (AddressOverflowException e) { @@ -603,9 +603,9 @@ public class DBTraceInstructionsView extends AbstractBaseDBTraceDefinedUnitsView if (lastInstruction != null) { Address maxAddress = DBTraceCodeManager.instructionMax(lastInstruction, true); result.addRange(block.getStartAddress(), maxAddress); - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.CODE_ADDED, space, - new ImmutableTraceAddressSnapRange(block.getStartAddress(), maxAddress, - lifespan))); + space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.CODE_ADDED, + space.space, new ImmutableTraceAddressSnapRange(block.getStartAddress(), + maxAddress, lifespan))); } } return result; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceUndefinedDataView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceUndefinedDataView.java index f74d40c36e..b8b72e9e7d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceUndefinedDataView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceUndefinedDataView.java @@ -4,9 +4,9 @@ * 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. @@ -142,7 +142,12 @@ public class DBTraceUndefinedDataView extends boolean forward) { Iterator

ait = getAddressSetView(snap, new AddressRangeImpl(min, max)).getAddresses(forward); - return () -> IteratorUtils.transformedIterator(ait, a -> doCreateUnit(snap, a)); + /** + * a should NEVER be null, but if it happens, I'd rather the caller deal with the null than + * throw an exception here. + */ + return () -> IteratorUtils.transformedIterator(ait, + a -> a == null ? null : doCreateUnit(snap, a)); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/InternalBaseCodeUnitsView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/InternalBaseCodeUnitsView.java index 64a7d65d74..c09f11e38b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/InternalBaseCodeUnitsView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/InternalBaseCodeUnitsView.java @@ -4,9 +4,9 @@ * 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. @@ -64,4 +64,11 @@ public interface InternalBaseCodeUnitsView } return candidate; } + + @Override + default Iterable get(TracePlatform platform, long snap, Register register, + boolean forward) { + AddressRange range = platform.getConventionalRegisterRange(getSpace(), register); + return get(snap, range, forward); + } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/UndefinedDBTraceData.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/UndefinedDBTraceData.java index 425ced0584..ea436391a7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/UndefinedDBTraceData.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/UndefinedDBTraceData.java @@ -4,9 +4,9 @@ * 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. @@ -27,12 +27,11 @@ import ghidra.program.model.listing.Data; import ghidra.trace.database.DBTrace; import ghidra.trace.database.data.DBTraceDataSettingsOperations; import ghidra.trace.database.memory.DBTraceMemorySpace; -import ghidra.trace.database.space.DBTraceSpaceKey; import ghidra.trace.model.*; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.listing.TraceData; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; +import ghidra.trace.util.TraceSpaceMixin; /** * The implementation for an undefined {@link TraceData} for {@link DBTrace} @@ -41,7 +40,7 @@ import ghidra.trace.util.TraceAddressSpace; * These are not backed by a table. They are generated ephemerally. Each is exactly one unit in size * in both time and space. */ -public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey { +public class UndefinedDBTraceData implements DBTraceDataAdapter, TraceSpaceMixin { protected final DBTrace trace; protected final long snap; protected final Lifespan lifespan; @@ -68,11 +67,6 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey this.frameLevel = frameLevel; } - @Override - public TraceAddressSpace getTraceSpace() { - return this; - } - @Override public AddressSpace getAddressSpace() { return address.getAddressSpace(); @@ -169,7 +163,7 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey @Override public int getBytes(ByteBuffer buffer, int addressOffset) { - DBTraceMemorySpace mem = trace.getMemoryManager().get(this, false); + DBTraceMemorySpace mem = trace.getMemoryManager().get(getAddressSpace(), false); if (mem == null) { // TODO: 0-fill instead? Will need to check memory space bounds. return 0; @@ -289,7 +283,7 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey @Override public DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent) { return (DBTraceDataSettingsOperations) getTrace().getDataSettingsAdapter() - .get(this, createIfAbsent); + .get(getAddressSpace(), createIfAbsent); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/AbstractDBTracePropertyMap.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/AbstractDBTracePropertyMap.java index cc3597a971..f108a5603c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/AbstractDBTracePropertyMap.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/AbstractDBTracePropertyMap.java @@ -123,17 +123,8 @@ public abstract class AbstractDBTracePropertyMap implements TracePropertyMapSpace { - public DBTracePropertyMapSpace(String tableName, DBCachedObjectStoreFactory storeFactory, - ReadWriteLock lock, AddressSpace space, TraceThread thread, int frameLevel, + public DBTracePropertyMapSpace(String tableName, DBTrace trace, + DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space, Class dataType, DBTraceAddressSnapRangePropertyMapDataFactory dataFactory) throws VersionException, IOException { - super(tableName, storeFactory, lock, space, thread, frameLevel, dataType, dataFactory); + super(tableName, trace, storeFactory, lock, space, dataType, dataFactory); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMap.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMap.java index 952848a4a3..d613356df8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMap.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMap.java @@ -4,9 +4,9 @@ * 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. @@ -78,17 +78,8 @@ public class DBTraceAddressSnapRangePropertyMap createSpace(AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException { - return new DBTraceAddressSnapRangePropertyMapSpace<>( - tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), - lock, space, null, ent.getFrameLevel(), dataType, dataFactory); - } - - @Override - protected DBTraceAddressSnapRangePropertyMapSpace createRegisterSpace(AddressSpace space, - TraceThread thread, DBTraceSpaceEntry ent) throws VersionException, IOException { - return new DBTraceAddressSnapRangePropertyMapSpace<>( - tableName(space, ent.getThreadKey(), ent.getFrameLevel()), trace.getStoreFactory(), - lock, space, thread, ent.getFrameLevel(), dataType, dataFactory); + return new DBTraceAddressSnapRangePropertyMapSpace<>(tableName(space), trace, + trace.getStoreFactory(), lock, space, dataType, dataFactory); } @Override @@ -160,7 +151,7 @@ public class DBTraceAddressSnapRangePropertyMap space : getActiveMemorySpaces()) { + for (DBTraceAddressSnapRangePropertyMapSpace space : getActiveSpaces()) { count += space.size(); } return count; @@ -168,37 +159,37 @@ public class DBTraceAddressSnapRangePropertyMap !m.isEmpty()); + return !delegateAny(spacesView, m -> !m.isEmpty()); } @Override public Collection> entries() { - return delegateCollection(memSpacesView, m -> m.entries()); + return delegateCollection(spacesView, m -> m.entries()); } @Override public Collection> orderedEntries() { - return delegateCollection(memSpacesView, m -> m.orderedEntries()); + return delegateCollection(spacesView, m -> m.orderedEntries()); } @Override public Collection keys() { - return delegateCollection(memSpacesView, m -> m.keys()); + return delegateCollection(spacesView, m -> m.keys()); } @Override public Collection orderedKeys() { - return delegateCollection(memSpacesView, m -> m.orderedKeys()); + return delegateCollection(spacesView, m -> m.orderedKeys()); } @Override public Collection values() { - return delegateCollection(memSpacesView, m -> m.values()); + return delegateCollection(spacesView, m -> m.values()); } @Override public Collection orderedValues() { - return delegateCollection(memSpacesView, m -> m.orderedValues()); + return delegateCollection(spacesView, m -> m.orderedValues()); } @Override @@ -209,22 +200,22 @@ public class DBTraceAddressSnapRangePropertyMap firstEntry() { - return delegateFirst(memSpacesView, m -> m.firstEntry()); + return delegateFirst(spacesView, m -> m.firstEntry()); } @Override public TraceAddressSnapRange firstKey() { - return delegateFirst(memSpacesView, m -> m.firstKey()); + return delegateFirst(spacesView, m -> m.firstKey()); } @Override public T firstValue() { - return delegateFirst(memSpacesView, m -> m.firstValue()); + return delegateFirst(spacesView, m -> m.firstValue()); } @Override public void clear() { - for (DBTraceAddressSnapRangePropertyMapSpace space : memSpacesView) { + for (DBTraceAddressSnapRangePropertyMapSpace space : spacesView) { space.clear(); } } @@ -232,7 +223,7 @@ public class DBTraceAddressSnapRangePropertyMap predicate) { return new UnionAddressSetView( - memSpaces.values().stream().map(m -> m.getAddressSetView(span, predicate)).toList()); + spaces.values().stream().map(m -> m.getAddressSetView(span, predicate)).toList()); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpace.java index 355384e867..27b71332b6 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpace.java @@ -4,9 +4,9 @@ * 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. @@ -23,14 +23,13 @@ import java.util.function.Predicate; import ghidra.lifecycle.Internal; import ghidra.program.model.address.*; +import ghidra.trace.database.DBTrace; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMap.DBTraceAddressSnapRangePropertyMapDataFactory; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; import ghidra.trace.database.space.DBTraceSpaceBased; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.TraceAddressSnapRange; +import ghidra.trace.model.*; import ghidra.trace.model.map.TraceAddressSnapRangePropertyMapSpace; -import ghidra.trace.model.thread.TraceThread; import ghidra.util.LockHold; import ghidra.util.database.*; import ghidra.util.database.spatial.AbstractConstraintsTreeSpatialMap; @@ -42,22 +41,20 @@ public class DBTraceAddressSnapRangePropertyMapSpace, TraceAddressSnapRangePropertyMapSpace { + protected final DBTrace trace; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final ReadWriteLock lock; protected final DBTraceAddressSnapRangePropertyMapTree tree; protected final AbstractConstraintsTreeSpatialMap map; protected final AddressRangeImpl fullSpace; - public DBTraceAddressSnapRangePropertyMapSpace(String tableName, + public DBTraceAddressSnapRangePropertyMapSpace(String tableName, DBTrace trace, DBCachedObjectStoreFactory storeFactory, ReadWriteLock lock, AddressSpace space, - TraceThread thread, int frameLevel, Class dataType, + Class dataType, DBTraceAddressSnapRangePropertyMapDataFactory dataFactory) throws VersionException, IOException { + this.trace = trace; this.space = space; - this.thread = thread; - this.frameLevel = frameLevel; this.lock = lock; this.tree = new DBTraceAddressSnapRangePropertyMapTree<>(storeFactory, tableName, this, @@ -67,21 +64,16 @@ public class DBTraceAddressSnapRangePropertyMapSpace DBCachedObjectIndex getUserIndex(Class fieldClass, DBObjectColumn column) { return tree.getUserIndex(fieldClass, column); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceEmptyMemBuffer.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceEmptyMemBuffer.java new file mode 100644 index 0000000000..4c7ce9042a --- /dev/null +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceEmptyMemBuffer.java @@ -0,0 +1,72 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.trace.database.memory; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.mem.MemBufferMixin; +import ghidra.program.model.mem.Memory; +import ghidra.trace.database.DBTrace; +import ghidra.util.MathUtilities; + +public class DBTraceEmptyMemBuffer implements MemBufferMixin { + private final DBTrace trace; + private final Address start; + private final ByteOrder byteOrder; + + public DBTraceEmptyMemBuffer(DBTrace trace, Address start, ByteOrder byteOrder) { + this.trace = trace; + this.start = start; + this.byteOrder = byteOrder; + } + + @Override + public Address getAddress() { + return start; + } + + @Override + public Memory getMemory() { + // NOTE: This may be problematic for non-canonical views + return trace.getProgramView().getMemory(); + } + + @Override + public boolean isBigEndian() { + return byteOrder == ByteOrder.BIG_ENDIAN; + } + + @Override + public int getBytes(ByteBuffer buffer, int offset) { + try { + long toRead = + start.getAddressSpace().getMaxAddress().subtract(start.addNoWrap(offset)) + 1; + toRead = MathUtilities.unsignedMin(toRead, buffer.remaining()); + toRead = MathUtilities.unsignedMin(toRead, Integer.MAX_VALUE); + int result = (int) toRead; + int end = buffer.position() + result; + Arrays.fill(buffer.array(), buffer.position(), end, (byte) 0); + return result; + } + catch (AddressOverflowException e) { + return 0; + } + } +} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemBuffer.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemBuffer.java index bc2ac3c2a0..a6c7aa4b88 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemBuffer.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemBuffer.java @@ -4,9 +4,9 @@ * 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. @@ -44,7 +44,7 @@ public class DBTraceMemBuffer implements MemBufferMixin { @Override public Memory getMemory() { - // TODO: This may be problematic for non-canonical views + // NOTE: This may be problematic for non-canonical views return space.trace.getProgramView().getMemory(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBlockEntry.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBlockEntry.java index 5d37cfd180..2763463db1 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBlockEntry.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBlockEntry.java @@ -4,9 +4,9 @@ * 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. @@ -42,8 +42,8 @@ class DBTraceMemoryBlockEntry extends DBAnnotatedObject { @DBAnnotatedColumn(BLOCK_COLUMN_NAME) static DBObjectColumn BLOCK_COLUMN; - static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField( diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBufferEntry.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBufferEntry.java index df3ac3ec85..40c1bbd7ea 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBufferEntry.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBufferEntry.java @@ -4,9 +4,9 @@ * 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. @@ -41,8 +41,8 @@ public class DBTraceMemoryBufferEntry extends DBAnnotatedObject { @DBAnnotatedColumn(COMPRESSED_COLUMN_NAME) static DBObjectColumn COMPRESSED_COLUMN; - static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField(column = IN_USE_COLUMN_NAME) diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryManager.java index c30b10af8a..2f95ebbb0c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryManager.java @@ -41,7 +41,8 @@ import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.thread.TraceThread; import ghidra.util.MathUtilities; import ghidra.util.UnionAddressSetView; -import ghidra.util.exception.*; +import ghidra.util.exception.DuplicateNameException; +import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager @@ -86,13 +87,7 @@ public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager flags) - throws TraceOverlappedRegionException, DuplicateNameException { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().addMemoryRegion(path, lifespan, range, flags); - } - try { - return delegateWrite(range.getAddressSpace(), - m -> m.addRegion(path, lifespan, range, flags)); - } - catch (TraceOverlappedRegionException | DuplicateNameException e) { - throw e; - } - catch (UsrException e) { - throw new AssertionError(e); // Should never happen - } + Collection flags) throws TraceOverlappedRegionException { + return trace.getObjectManager().addMemoryRegion(path, lifespan, range, flags); } @Override public Collection getAllRegions() { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getAllObjects(TraceObjectMemoryRegion.class); - } - return delegateCollection(getActiveMemorySpaces(), m -> m.getAllRegions()); + return trace.getObjectManager().getAllObjects(TraceMemoryRegion.class); } @Override public TraceMemoryRegion getLiveRegionByPath(long snap, String path) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectByPath(snap, path, TraceObjectMemoryRegion.class); - } - // Not efficient, but I don't anticipate many regions - return delegateFirst(getActiveMemorySpaces(), m -> m.getLiveRegionByPath(snap, path)); + return trace.getObjectManager().getObjectByPath(snap, path, TraceMemoryRegion.class); } @Override public TraceMemoryRegion getRegionContaining(long snap, Address address) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectContaining(snap, address, TraceObjectMemoryRegion.KEY_RANGE, - TraceObjectMemoryRegion.class); - } - return delegateRead(address.getAddressSpace(), m -> m.getRegionContaining(snap, address)); + return trace.getObjectManager() + .getObjectContaining(snap, address, TraceMemoryRegion.KEY_RANGE, + TraceMemoryRegion.class); } @Override public Collection getRegionsIntersecting(Lifespan lifespan, AddressRange range) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsIntersecting(lifespan, range, - TraceObjectMemoryRegion.KEY_RANGE, TraceObjectMemoryRegion.class); - } - return delegateRead(range.getAddressSpace(), m -> m.getRegionsIntersecting(lifespan, range), - Collections.emptyList()); + return trace.getObjectManager() + .getObjectsIntersecting(lifespan, range, TraceMemoryRegion.KEY_RANGE, + TraceMemoryRegion.class); } @Override public Collection getRegionsAtSnap(long snap) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getObjectsAtSnap(snap, TraceObjectMemoryRegion.class); - } - return delegateCollection(memSpaces.values(), m -> m.getRegionsAtSnap(snap)); - } - - public Collection getRegionsWithPathInLifespan(Lifespan lifespan, - String regionPath) { - // Not efficient, but I don't anticipate many regions - Collection result = new HashSet<>(); - for (DBTraceMemorySpace m : getActiveMemorySpaces()) { - for (TraceMemoryRegion region : m.getRegionsIntersecting(lifespan, new AddressRangeImpl( - m.getAddressSpace().getMinAddress(), m.getAddressSpace().getMaxAddress()))) { - if (regionPath.equals(region.getPath())) { - result.add(region); - } - } - } - return Collections.unmodifiableCollection(result); + return trace.getObjectManager().getObjectsAtSnap(snap, TraceMemoryRegion.class); } @Override public AddressSetView getRegionsAddressSet(long snap) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsAddressSet(snap, TraceObjectMemoryRegion.KEY_RANGE, - TraceObjectMemoryRegion.class, r -> true); - } - return new UnionAddressSetView( - getActiveMemorySpaces().stream().map(m -> m.getRegionsAddressSet(snap)).toList()); + return trace.getObjectManager() + .getObjectsAddressSet(snap, TraceMemoryRegion.KEY_RANGE, + TraceMemoryRegion.class, r -> true); } @Override public AddressSetView getRegionsAddressSetWith(long snap, Predicate predicate) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsAddressSet(snap, TraceObjectMemoryRegion.KEY_RANGE, - TraceObjectMemoryRegion.class, predicate); - } - return new UnionAddressSetView(getActiveMemorySpaces().stream() - .map(m -> m.getRegionsAddressSetWith(snap, predicate)) - .toList()); + return trace.getObjectManager() + .getObjectsAddressSet(snap, TraceMemoryRegion.KEY_RANGE, + TraceMemoryRegion.class, predicate); } @Override @@ -295,13 +235,13 @@ public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager predicate) { - return delegateAddressSet(getActiveMemorySpaces(), + return delegateAddressSet(getActiveSpaces(), m -> m.getAddressesWithState(snap, set, predicate)); } @Override public AddressSetView getAddressesWithState(long snap, Predicate predicate) { - return new UnionAddressSetView(getActiveMemorySpaces().stream() + return new UnionAddressSetView(getActiveSpaces().stream() .map(m -> m.getAddressesWithState(snap, predicate)) .toList()); } @@ -309,7 +249,7 @@ public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager predicate) { - return new UnionAddressSetView(getActiveMemorySpaces().stream() + return new UnionAddressSetView(getActiveSpaces().stream() .map(m -> m.getAddressesWithState(lifespan, predicate)) .toList()); } @@ -374,8 +314,12 @@ public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager m.getBufferAt(snap, start, byteOrder)); + MemBuffer buffer = + delegateRead(start.getAddressSpace(), m -> m.getBufferAt(snap, start, byteOrder)); + if (buffer == null) { + return new DBTraceEmptyMemBuffer(trace, start, byteOrder); + } + return buffer; } @Override @@ -394,34 +338,6 @@ public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager m.pack()); } - @Override - public Collection getRegionsAdded(long from, long to) { - if (from == to) { - return Collections.emptySet(); - } - Collection result = new ArrayList<>(); - for (DBTraceMemorySpace space : memSpaces.values()) { - result.addAll( - space.regionMapSpace.reduce(TraceAddressSnapRangeQuery.added(from, to, space.space)) - .values()); - } - return result; - } - - @Override - public Collection getRegionsRemoved(long from, long to) { - if (from == to) { - return Collections.emptySet(); - } - Collection result = new ArrayList<>(); - for (DBTraceMemorySpace space : memSpaces.values()) { - result.addAll(space.regionMapSpace - .reduce(TraceAddressSnapRangeQuery.removed(from, to, space.space)) - .values()); - } - return result; - } - @Override public Collection> getStateChanges(long from, long to) { @@ -430,7 +346,7 @@ public class DBTraceMemoryManager extends AbstractDBTraceSpaceBasedManager> result = new ArrayList<>(); - for (DBTraceMemorySpace space : memSpaces.values()) { + for (DBTraceMemorySpace space : spaces.values()) { AddressRange rng = new AddressRangeImpl(space.space.getMinAddress(), space.space.getMaxAddress()); result.addAll( diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryRegion.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryRegion.java index c6e54fe29b..1e2b34071d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryRegion.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryRegion.java @@ -15,282 +15,336 @@ */ package ghidra.trace.database.memory; -import java.io.IOException; import java.util.*; -import db.DBRecord; 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.target.DBTraceObject; +import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.memory.*; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; +import ghidra.trace.model.Trace; +import ghidra.trace.model.memory.TraceMemoryFlag; +import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.TraceObjectValue; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; +import ghidra.trace.model.target.path.KeyPath; +import ghidra.trace.model.target.schema.TraceObjectSchema; +import ghidra.trace.util.*; import ghidra.util.LockHold; -import ghidra.util.database.DBCachedObjectStore; -import ghidra.util.database.DBObjectColumn; -import ghidra.util.database.annot.*; -import ghidra.util.exception.DuplicateNameException; -@DBAnnotatedObjectInfo(version = 0) -public class DBTraceMemoryRegion - extends AbstractDBTraceAddressSnapRangePropertyMapData - implements TraceMemoryRegion { - public static final String TABLE_NAME = "MemoryRegions"; +public class DBTraceMemoryRegion implements TraceMemoryRegion, DBTraceObjectInterface { - public static final String PATH_COLUMN_NAME = "Path"; - public static final String NAME_COLUMN_NAME = "Name"; - public static final String FLAGS_COLUMN_NAME = "Flags"; - - @DBAnnotatedColumn(PATH_COLUMN_NAME) - static DBObjectColumn PATH_COLUMN; - @DBAnnotatedColumn(NAME_COLUMN_NAME) - static DBObjectColumn NAME_COLUMN; - @DBAnnotatedColumn(FLAGS_COLUMN_NAME) - static DBObjectColumn FLAGS_COLUMN; - - 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 = FLAGS_COLUMN_NAME) - private byte flagsByte = 0; - - private final DBTraceMemorySpace space; - - private final EnumSet flags = EnumSet.noneOf(TraceMemoryFlag.class); - - public DBTraceMemoryRegion(DBTraceMemorySpace space, - DBTraceAddressSnapRangePropertyMapTree 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; + protected record Keys(Set all, String range, String display, + Set flags) { + static Keys fromSchema(TraceObjectSchema schema) { + String keyRange = schema.checkAliasedAttribute(KEY_RANGE); + String keyDisplay = schema.checkAliasedAttribute(KEY_DISPLAY); + String keyReadable = schema.checkAliasedAttribute(KEY_READABLE); + String keyWritable = schema.checkAliasedAttribute(KEY_WRITABLE); + String keyExecutable = schema.checkAliasedAttribute(KEY_EXECUTABLE); + return new Keys(Set.of(keyRange, keyDisplay, keyReadable, keyWritable, keyExecutable), + keyRange, keyDisplay, Set.of(keyReadable, keyWritable, keyExecutable)); } - flags.clear(); - TraceMemoryFlag.fromBits(flags, flagsByte); - } - @Override - protected void setRecordValue(DBTraceMemoryRegion value) { - // Nothing. The value is the record. - } - - @Override - protected DBTraceMemoryRegion getRecordValue() { - return this; - } - - void set(String path, String name, Collection flags) { - this.path = path; - this.name = name; - this.flagsByte = 0; - this.flags.clear(); - for (TraceMemoryFlag f : flags) { - this.flagsByte |= f.getBits(); - this.flags.add(f); + public boolean isRange(String key) { + return range.equals(key); + } + + public boolean isDisplay(String key) { + return display.equals(key); + } + + public boolean isFlag(String key) { + return flags.contains(key); } - update(PATH_COLUMN, NAME_COLUMN, FLAGS_COLUMN); } - @SuppressWarnings("hiding") - protected void checkOverlapConflicts(Lifespan lifespan, AddressRange range) - throws TraceOverlappedRegionException { - Collection overlapConflicts = - space.getRegionsIntersecting(lifespan, range); - for (TraceMemoryRegion c : overlapConflicts) { - if (c == this) { - continue; + protected class RegionChangeTranslator extends Translator { + private static final Map KEYS_BY_SCHEMA = + new WeakHashMap<>(); + + private final Keys keys; + + protected RegionChangeTranslator(DBTraceObject object, TraceMemoryRegion iface) { + super(KEY_RANGE, object, iface); + TraceObjectSchema schema = object.getSchema(); + synchronized (KEYS_BY_SCHEMA) { + keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, Keys::fromSchema); } - throw new TraceOverlappedRegionException(overlapConflicts); + } + + @Override + protected TraceEvent getAddedType() { + return TraceEvents.REGION_ADDED; + } + + @Override + protected TraceEvent getLifespanChangedType() { + return TraceEvents.REGION_LIFESPAN_CHANGED; + } + + @Override + protected TraceEvent getChangedType() { + return TraceEvents.REGION_CHANGED; + } + + @Override + protected boolean appliesToKey(String key) { + return keys.all.contains(key); + } + + @Override + protected TraceEvent getDeletedType() { + return TraceEvents.REGION_DELETED; + } + + @Override + protected void emitExtraAdded() { + updateViewsAdded(); + } + + @Override + protected void emitExtraLifespanChanged(Lifespan oldLifespan, Lifespan newLifespan) { + updateViewsLifespanChanged(oldLifespan, newLifespan); + } + + @Override + protected void emitExtraValueChanged(Lifespan lifespan, String key, Object oldValue, + Object newValue) { + updateViewsValueChanged(lifespan, key, oldValue, newValue); + } + + @Override + protected void emitExtraDeleted() { + updateViewsDeleted(); } } - @SuppressWarnings("hiding") - protected void checkPathConflicts(Lifespan lifespan, String path) - throws DuplicateNameException { - Collection pathConflicts = - space.manager.getRegionsWithPathInLifespan(lifespan, path); - for (TraceMemoryRegion c : pathConflicts) { - if (c == this) { - continue; - } - throw new DuplicateNameException( - "Only one region with a given path may occupy the same snap"); - } + private final DBTraceObject object; + private final RegionChangeTranslator translator; + + public DBTraceMemoryRegion(DBTraceObject object) { + this.object = object; + + translator = new RegionChangeTranslator(object, this); } @Override - public DBTrace getTrace() { - return space.trace; + public Trace getTrace() { + return object.getTrace(); } @Override public String getPath() { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return path; - } + return object.getCanonicalPath().toString(); + } + + @Override + public void setName(Lifespan lifespan, String name) { + object.setValue(lifespan, TraceObjectInterface.KEY_DISPLAY, name); } @Override public void setName(long snap, String name) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - this.name = name; - update(NAME_COLUMN); - space.trace.updateViewsChangeRegionBlockName(this); + try (LockHold hold = object.getTrace().lockWrite()) { + setName(Lifespan.nowOn(snap), name); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.REGION_CHANGED, space, this)); } @Override public String getName(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return name; + String key = object.getCanonicalPath().key(); + String index = KeyPath.parseIfIndex(key); + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, index); + } + + @Override + public void setRange(Lifespan lifespan, AddressRange newRange) { + try (LockHold hold = object.getTrace().lockWrite()) { + object.setValue(lifespan, KEY_RANGE, newRange); } } @Override - public void setRange(long snap, AddressRange newRange) throws TraceOverlappedRegionException { - AddressRange oldRange; - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - if (range.equals(newRange)) { - return; - } - oldRange = range; - checkOverlapConflicts(lifespan, newRange); - doSetRange(newRange); - space.trace.updateViewsChangeRegionBlockRange(this, oldRange, newRange); + public void setRange(long snap, AddressRange newRange) { + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(Lifespan.nowOn(snap), newRange); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.REGION_CHANGED, space, this)); } @Override public AddressRange getRange(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range; + try (LockHold hold = object.getTrace().lockRead()) { + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_RANGE, AddressRange.class, + null); } } @Override - public void setMinAddress(long snap, Address min) throws TraceOverlappedRegionException { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - setRange(snap, DBTraceUtils.toRange(min, range.getMaxAddress())); + public void setMinAddress(long snap, Address min) { + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(Lifespan.nowOn(snap), DBTraceUtils.toRange(min, getMaxAddress(snap))); } } @Override public Address getMinAddress(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range.getMinAddress(); - } + AddressRange range = getRange(snap); + return range == null ? null : range.getMinAddress(); } @Override - public void setMaxAddress(long snap, Address max) throws TraceOverlappedRegionException { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - setRange(snap, DBTraceUtils.toRange(range.getMinAddress(), max)); + public void setMaxAddress(long snap, Address max) { + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(Lifespan.nowOn(snap), DBTraceUtils.toRange(getMinAddress(snap), max)); } } @Override public Address getMaxAddress(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range.getMaxAddress(); - } + AddressRange range = getRange(snap); + return range == null ? null : range.getMaxAddress(); } @Override - public void setLength(long snap, long length) - throws AddressOverflowException, TraceOverlappedRegionException { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - Address minAddress = range.getMinAddress(); - setRange(snap, DBTraceUtils.toRange(minAddress, minAddress.addNoWrap(length - 1))); + public void setLength(long snap, long length) throws AddressOverflowException { + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(Lifespan.nowOn(snap), new AddressRangeImpl(getMinAddress(snap), length)); } } @Override public long getLength(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range.getLength(); + AddressRange range = getRange(snap); + return range == null ? 0 : range.getLength(); + } + + protected static String keyForFlag(TraceMemoryFlag flag) { + return switch (flag) { + case READ -> KEY_READABLE; + case WRITE -> KEY_WRITABLE; + case EXECUTE -> KEY_EXECUTABLE; + case VOLATILE -> KEY_VOLATILE; + default -> throw new AssertionError(); + }; + } + + @Override + public void setFlags(Lifespan lifespan, Collection flags) { + try (LockHold hold = object.getTrace().lockWrite()) { + for (TraceMemoryFlag flag : TraceMemoryFlag.values()) { + object.setValue(lifespan, keyForFlag(flag), flags.contains(flag)); + } + } + } + + @Override + public void addFlags(Lifespan lifespan, Collection flags) { + try (LockHold hold = object.getTrace().lockWrite()) { + for (TraceMemoryFlag flag : flags) { + object.setValue(lifespan, keyForFlag(flag), true); + } + } + } + + @Override + public void clearFlags(Lifespan lifespan, Collection flags) { + try (LockHold hold = object.getTrace().lockWrite()) { + for (TraceMemoryFlag flag : flags) { + object.setValue(lifespan, keyForFlag(flag), false); + } } } @Override public void setFlags(long snap, Collection flags) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - this.flagsByte = TraceMemoryFlag.toBits(flags); - this.flags.clear(); - this.flags.addAll(flags); - update(FLAGS_COLUMN); - space.trace.updateViewsChangeRegionBlockFlags(this, lifespan); + try (LockHold hold = object.getTrace().lockWrite()) { + setFlags(Lifespan.nowOn(snap), flags); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.REGION_CHANGED, space, this)); } - @SuppressWarnings("hiding") @Override public void addFlags(long snap, Collection flags) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - this.flagsByte |= TraceMemoryFlag.toBits(flags); - this.flags.addAll(flags); - update(FLAGS_COLUMN); - space.trace.updateViewsChangeRegionBlockFlags(this, lifespan); + try (LockHold hold = object.getTrace().lockWrite()) { + addFlags(Lifespan.nowOn(snap), flags); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.REGION_CHANGED, space, this)); } - @SuppressWarnings("hiding") @Override public void clearFlags(long snap, Collection flags) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - this.flagsByte &= ~TraceMemoryFlag.toBits(flags); - this.flags.removeAll(flags); - update(FLAGS_COLUMN); - space.trace.updateViewsChangeRegionBlockFlags(this, lifespan); + try (LockHold hold = object.getTrace().lockWrite()) { + clearFlags(Lifespan.nowOn(snap), flags); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.REGION_CHANGED, space, this)); } @Override public Set getFlags(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return Set.copyOf(flags); + EnumSet result = EnumSet.noneOf(TraceMemoryFlag.class); + for (TraceMemoryFlag flag : TraceMemoryFlag.values()) { + TraceObjectValue value = object.getValue(snap, keyForFlag(flag)); + if (value != null && value.getValue() == Boolean.TRUE) { + result.add(flag); + } } + return result; } @Override public void delete() { - space.deleteRegion(this); + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.ALL); + } } @Override public void remove(long snap) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - if (snap <= lifespan.lmin()) { - space.deleteRegion(this); - } - else if (snap <= lifespan.lmax()) { - doSetLifespan(lifespan.withMax(snap - 1)); - } + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.nowOn(snap)); } } @Override public boolean isValid(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return lifespan.contains(snap); + return object.isAlive(snap); + } + + @Override + public TraceObject getObject() { + return object; + } + + @Override + public TraceChangeRecord translateEvent(TraceChangeRecord rec) { + return translator.translate(rec); + } + + protected void updateViewsAdded() { + object.getTrace().updateViewsAddRegionBlock(this); + } + + protected void updateViewsLifespanChanged(Lifespan oldLifespan, Lifespan newLifespan) { + object.getTrace().updateViewsChangeRegionBlockLifespan(this, oldLifespan, newLifespan); + } + + protected void updateViewsValueChanged(Lifespan lifespan, String key, Object oldValue, + Object newValue) { + DBTrace trace = object.getTrace(); + if (translator.keys.isRange(key)) { + // NB. old/newValue are null here. The CREATED event just has the new entry. + trace.updateViewsRefreshBlocks(); + } + else if (translator.keys.isDisplay(key)) { + trace.updateViewsChangeRegionBlockName(this); + } + else if (translator.keys.isFlag(key)) { + trace.updateViewsChangeRegionBlockFlags(this, lifespan); } } + + protected void updateViewsDeleted() { + object.getTrace().updateViewsDeleteRegionBlock(this); + } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java index 464ce82666..0b8047496d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java @@ -36,8 +36,8 @@ import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAdd import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpaceEntry; import ghidra.trace.database.space.DBTraceSpaceBased; import ghidra.trace.model.*; -import ghidra.trace.model.memory.*; -import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.model.memory.TraceMemorySpace; +import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; import ghidra.util.*; @@ -45,7 +45,6 @@ import ghidra.util.AddressIteratorAdapter; import ghidra.util.database.*; import ghidra.util.database.spatial.rect.Rectangle2DDirection; import ghidra.util.datastruct.FixedSizeHashMap; -import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; @@ -64,17 +63,9 @@ public class DBTraceMemorySpace protected final DBTraceMemoryManager manager; protected final DBHandle dbh; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final ReadWriteLock lock; protected final DBTrace trace; - protected final DBTraceAddressSnapRangePropertyMapSpace regionMapSpace; - protected final DBCachedObjectIndex regionsByPath; - protected final Collection regionView; - protected final Map regionCache = - new FixedSizeHashMap<>(10); - protected final DBTraceAddressSnapRangePropertyMapSpace stateMapSpace; protected final DBCachedObjectStore bufferStore; @@ -86,40 +77,26 @@ public class DBTraceMemorySpace protected final DBTraceTimeViewport viewport; public DBTraceMemorySpace(DBTraceMemoryManager manager, DBHandle dbh, AddressSpace space, - DBTraceSpaceEntry ent, TraceThread thread) throws IOException, VersionException { + DBTraceSpaceEntry ent) throws IOException, VersionException { this.manager = manager; this.dbh = dbh; this.space = space; - this.thread = thread; - this.frameLevel = ent.getFrameLevel(); this.lock = manager.getLock(); this.trace = manager.getTrace(); DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - long threadKey = ent.getThreadKey(); - int frameLevel = ent.getFrameLevel(); - this.regionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceMemoryRegion.tableName(space, threadKey), factory, lock, space, thread, - frameLevel, DBTraceMemoryRegion.class, - (t, s, r) -> new DBTraceMemoryRegion(this, t, s, r)); - this.regionView = Collections.unmodifiableCollection(regionMapSpace.values()); - this.regionsByPath = - regionMapSpace.getUserIndex(String.class, DBTraceMemoryRegion.PATH_COLUMN); - this.stateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceMemoryStateEntry.tableName(space, threadKey, frameLevel), factory, lock, space, - thread, frameLevel, DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new); + DBTraceMemoryStateEntry.tableName(space), trace, factory, lock, space, + DBTraceMemoryStateEntry.class, DBTraceMemoryStateEntry::new); this.bufferStore = factory.getOrCreateCachedStore( - DBTraceMemoryBufferEntry.tableName(space, threadKey, frameLevel), - DBTraceMemoryBufferEntry.class, (s, r) -> new DBTraceMemoryBufferEntry(dbh, s, r), - true); + DBTraceMemoryBufferEntry.tableName(space), DBTraceMemoryBufferEntry.class, + (s, r) -> new DBTraceMemoryBufferEntry(dbh, s, r), true); this.blockStore = factory.getOrCreateCachedStore( - DBTraceMemoryBlockEntry.tableName(space, threadKey, frameLevel), - DBTraceMemoryBlockEntry.class, (s, r) -> new DBTraceMemoryBlockEntry(this, s, r), - true); + DBTraceMemoryBlockEntry.tableName(space), DBTraceMemoryBlockEntry.class, + (s, r) -> new DBTraceMemoryBlockEntry(this, s, r), true); this.blocksByOffset = blockStore.getIndex(OffsetSnap.class, DBTraceMemoryBlockEntry.LOCATION_COLUMN); @@ -141,117 +118,8 @@ public class DBTraceMemorySpace return trace; } - @Override - public DBTraceMemoryRegion addRegion(String path, Lifespan lifespan, - AddressRange range, Collection flags) - throws TraceOverlappedRegionException, DuplicateNameException { - try (LockHold hold = LockHold.lock(lock.writeLock())) { - Collection conflicts = - getRegionsIntersecting(lifespan, range); - if (!conflicts.isEmpty()) { - throw new TraceOverlappedRegionException(conflicts); - } - if (!manager.getRegionsWithPathInLifespan(lifespan, path).isEmpty()) { - throw new DuplicateNameException( - "A region having path '" + path + - "' already exists within an overlapping snap"); - } - DBTraceMemoryRegion region = - regionMapSpace.put(new ImmutableTraceAddressSnapRange(range, lifespan), null); - region.set(path, path, flags); - trace.updateViewsAddRegionBlock(region); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.REGION_ADDED, this, region)); - return region; - } - } - - @Override - public Collection getAllRegions() { - return regionView; - } - - @Override - public DBTraceMemoryRegion getLiveRegionByPath(long snap, String path) { - try (LockHold hold = LockHold.lock(lock.readLock())) { - for (DBTraceMemoryRegion region : regionCache.keySet()) { - if (!region.getLifespan().contains(snap)) { - continue; - } - if (!path.equals(region.getPath())) { - continue; - } - return region; - } - for (DBTraceMemoryRegion region : regionsByPath.get(path)) { - if (!region.getLifespan().contains(snap)) { - continue; - } - regionCache.put(region, region); - return region; - } - return null; - } - } - - @Override - public DBTraceMemoryRegion getRegionContaining(long snap, Address address) { - try (LockHold hold = LockHold.lock(lock.readLock())) { - for (DBTraceMemoryRegion region : regionCache.keySet()) { - if (!region.getShape().contains(address, snap)) { - continue; - } - return region; - } - DBTraceMemoryRegion region = - regionMapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).firstValue(); - if (region != null) { - regionCache.put(region, region); - } - return region; - } - } - - @Override - public Collection getRegionsIntersecting(Lifespan lifespan, - AddressRange range) { - return Collections.unmodifiableCollection(regionMapSpace.reduce( - TraceAddressSnapRangeQuery.intersecting(range, lifespan)).values()); - } - - @Override - public Collection getRegionsAtSnap(long snap) { - return Collections.unmodifiableCollection( - regionMapSpace.reduce(TraceAddressSnapRangeQuery.atSnap(snap, space)).values()); - } - - @Override - public AddressSetView getRegionsAddressSet(long snap) { - return getRegionsAddressSetWith(snap, r -> true); - } - - @Override - public AddressSetView getRegionsAddressSetWith(long snap, - Predicate predicate) { - return new DBTraceAddressSnapRangePropertyMapAddressSetView<>(space, lock, - regionMapSpace.reduce(TraceAddressSnapRangeQuery.atSnap(snap, space)), - predicate); - } - - void deleteRegion(DBTraceMemoryRegion region) { - try (LockHold hold = LockHold.lock(lock.writeLock())) { - regionMapSpace.deleteData(region); - regionCache.remove(region); - trace.updateViewsDeleteRegionBlock(region); - trace.setChanged( - new TraceChangeRecord<>(TraceEvents.REGION_DELETED, this, region)); - } - } - @Override public DBTraceCodeSpace getCodeSpace(boolean createIfAbsent) { - if (space.isRegisterSpace() && !space.isOverlaySpace()) { - return trace.getCodeManager().getCodeRegisterSpace(thread, frameLevel, createIfAbsent); - } return trace.getCodeManager().getCodeSpace(space, createIfAbsent); } @@ -260,16 +128,6 @@ public class DBTraceMemorySpace return space; } - @Override - public TraceThread getThread() { - return thread; - } - - @Override - public int getFrameLevel() { - return frameLevel; - } - protected void doSetState(long snap, Address start, Address end, TraceMemoryState state) { if (state == null) { throw new NullPointerException(); @@ -315,7 +173,7 @@ public class DBTraceMemorySpace }.set(start, end, state); if (l.changed) { - trace.setChanged(new TraceChangeRecord<>(TraceEvents.BYTES_STATE_CHANGED, this, + trace.setChanged(new TraceChangeRecord<>(TraceEvents.BYTES_STATE_CHANGED, space, new ImmutableTraceAddressSnapRange(start, end, snap, snap), state)); } } @@ -677,11 +535,11 @@ public class DBTraceMemorySpace oldBuf.get(0, oldBytes); ImmutableTraceAddressSnapRange tasr = new ImmutableTraceAddressSnapRange(start, start.add(result - 1), snap, lastSnap.snap); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.BYTES_CHANGED, this, tasr, + trace.setChanged(new TraceChangeRecord<>(TraceEvents.BYTES_CHANGED, space, tasr, oldBytes, bytes)); // Fixup affected code units - DBTraceCodeSpace codeSpace = trace.getCodeManager().get(this, false); + DBTraceCodeSpace codeSpace = trace.getCodeManager().get(space, false); if (codeSpace != null) { codeSpace.bytesChanged(changed, snap, start, oldBytes, bytes); } @@ -1009,12 +867,12 @@ public class DBTraceMemorySpace // Fire event trace.setChanged(new TraceChangeRecord<>( - TraceEvents.BYTES_CHANGED, this, new ImmutableTraceAddressSnapRange(start, + TraceEvents.BYTES_CHANGED, space, new ImmutableTraceAddressSnapRange(start, start.add(newBytes.position() - 1), snap, lastSnap.snap), oldBytes.array(), newBytes.array())); // Fixup affected code units - DBTraceCodeSpace codeSpace = trace.getCodeManager().get(this, false); + DBTraceCodeSpace codeSpace = trace.getCodeManager().get(space, false); if (codeSpace != null) { codeSpace.bytesChanged(changed, snap, start, oldBytes.array(), newBytes.array()); } @@ -1046,8 +904,6 @@ public class DBTraceMemorySpace @Override public void invalidateCache() { try (LockHold hold = LockHold.lock(lock.writeLock())) { - regionMapSpace.invalidateCache(); - regionCache.clear(); trace.updateViewsRefreshBlocks(); trace.updateViewsBytesChanged(null); stateMapSpace.invalidateCache(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryStateEntry.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryStateEntry.java index 3852dc0653..7d43f6f035 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryStateEntry.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryStateEntry.java @@ -4,9 +4,9 @@ * 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. @@ -40,8 +40,8 @@ class DBTraceMemoryStateEntry @DBAnnotatedColumn(STATE_COLUMN_NAME) static DBObjectColumn STATE_COLUMN; - static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField(column = STATE_COLUMN_NAME) diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemory.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemory.java index 49b50875e7..db0e90015d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemory.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemory.java @@ -17,11 +17,11 @@ package ghidra.trace.database.memory; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; -import ghidra.trace.model.memory.TraceObjectMemory; +import ghidra.trace.model.memory.TraceMemory; import ghidra.trace.model.target.TraceObject; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectMemory implements TraceObjectMemory, DBTraceObjectInterface { +public class DBTraceObjectMemory implements TraceMemory, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectMemory(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemoryRegion.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemoryRegion.java deleted file mode 100644 index eb3b07bd43..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectMemoryRegion.java +++ /dev/null @@ -1,350 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.database.memory; - -import java.util.*; - -import ghidra.program.model.address.*; -import ghidra.trace.database.DBTrace; -import ghidra.trace.database.DBTraceUtils; -import ghidra.trace.database.target.DBTraceObject; -import ghidra.trace.database.target.DBTraceObjectInterface; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.Trace; -import ghidra.trace.model.memory.*; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.TraceObjectValue; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; -import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.util.*; -import ghidra.util.LockHold; - -public class DBTraceObjectMemoryRegion implements TraceObjectMemoryRegion, DBTraceObjectInterface { - - protected record Keys(Set all, String range, String display, - Set flags) { - static Keys fromSchema(TraceObjectSchema schema) { - String keyRange = schema.checkAliasedAttribute(TraceObjectMemoryRegion.KEY_RANGE); - String keyDisplay = schema.checkAliasedAttribute(TraceObjectInterface.KEY_DISPLAY); - String keyReadable = - schema.checkAliasedAttribute(TraceObjectMemoryRegion.KEY_READABLE); - String keyWritable = - schema.checkAliasedAttribute(TraceObjectMemoryRegion.KEY_WRITABLE); - String keyExecutable = - schema.checkAliasedAttribute(TraceObjectMemoryRegion.KEY_EXECUTABLE); - return new Keys(Set.of(keyRange, keyDisplay, keyReadable, keyWritable, keyExecutable), - keyRange, keyDisplay, Set.of(keyReadable, keyWritable, keyExecutable)); - } - - public boolean isRange(String key) { - return range.equals(key); - } - - public boolean isDisplay(String key) { - return display.equals(key); - } - - public boolean isFlag(String key) { - return flags.contains(key); - } - } - - protected class RegionChangeTranslator extends Translator { - private static final Map KEYS_BY_SCHEMA = - new WeakHashMap<>(); - - private final Keys keys; - - protected RegionChangeTranslator(DBTraceObject object, TraceMemoryRegion iface) { - super(TraceObjectMemoryRegion.KEY_RANGE, object, iface); - TraceObjectSchema schema = object.getSchema(); - synchronized (KEYS_BY_SCHEMA) { - keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, Keys::fromSchema); - } - } - - @Override - protected TraceEvent getAddedType() { - return TraceEvents.REGION_ADDED; - } - - @Override - protected TraceEvent getLifespanChangedType() { - return TraceEvents.REGION_LIFESPAN_CHANGED; - } - - @Override - protected TraceEvent getChangedType() { - return TraceEvents.REGION_CHANGED; - } - - @Override - protected boolean appliesToKey(String key) { - return keys.all.contains(key); - } - - @Override - protected TraceEvent getDeletedType() { - return TraceEvents.REGION_DELETED; - } - - @Override - protected void emitExtraAdded() { - updateViewsAdded(); - } - - @Override - protected void emitExtraLifespanChanged(Lifespan oldLifespan, Lifespan newLifespan) { - updateViewsLifespanChanged(oldLifespan, newLifespan); - } - - @Override - protected void emitExtraValueChanged(Lifespan lifespan, String key, Object oldValue, - Object newValue) { - updateViewsValueChanged(lifespan, key, oldValue, newValue); - } - - @Override - protected void emitExtraDeleted() { - updateViewsDeleted(); - } - } - - private final DBTraceObject object; - private final RegionChangeTranslator translator; - - public DBTraceObjectMemoryRegion(DBTraceObject object) { - this.object = object; - - translator = new RegionChangeTranslator(object, this); - } - - @Override - public Trace getTrace() { - return object.getTrace(); - } - - @Override - public String getPath() { - return object.getCanonicalPath().toString(); - } - - @Override - public void setName(Lifespan lifespan, String name) { - object.setValue(lifespan, TraceObjectInterface.KEY_DISPLAY, name); - } - - @Override - public void setName(long snap, String name) { - try (LockHold hold = object.getTrace().lockWrite()) { - setName(Lifespan.nowOn(snap), name); - } - } - - @Override - public String getName(long snap) { - TraceObjectValue value = object.getValue(snap, TraceObjectInterface.KEY_DISPLAY); - return value == null ? "" : (String) value.getValue(); - } - - @Override - public void setRange(Lifespan lifespan, AddressRange newRange) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(lifespan, TraceObjectMemoryRegion.KEY_RANGE, newRange); - } - } - - @Override - public void setRange(long snap, AddressRange newRange) { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(Lifespan.nowOn(snap), newRange); - } - } - - @Override - public AddressRange getRange(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return TraceObjectInterfaceUtils.getValue(object, snap, - TraceObjectMemoryRegion.KEY_RANGE, AddressRange.class, null); - } - } - - @Override - public void setMinAddress(long snap, Address min) { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(Lifespan.nowOn(snap), DBTraceUtils.toRange(min, getMaxAddress(snap))); - } - } - - @Override - public Address getMinAddress(long snap) { - AddressRange range = getRange(snap); - return range == null ? null : range.getMinAddress(); - } - - @Override - public void setMaxAddress(long snap, Address max) { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(Lifespan.nowOn(snap), DBTraceUtils.toRange(getMinAddress(snap), max)); - } - } - - @Override - public Address getMaxAddress(long snap) { - AddressRange range = getRange(snap); - return range == null ? null : range.getMaxAddress(); - } - - @Override - public void setLength(long snap, long length) throws AddressOverflowException { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(Lifespan.nowOn(snap), new AddressRangeImpl(getMinAddress(snap), length)); - } - } - - @Override - public long getLength(long snap) { - AddressRange range = getRange(snap); - return range == null ? 0 : range.getLength(); - } - - protected static String keyForFlag(TraceMemoryFlag flag) { - return switch (flag) { - case READ -> TraceObjectMemoryRegion.KEY_READABLE; - case WRITE -> TraceObjectMemoryRegion.KEY_WRITABLE; - case EXECUTE -> TraceObjectMemoryRegion.KEY_EXECUTABLE; - case VOLATILE -> KEY_VOLATILE; - default -> throw new AssertionError(); - }; - } - - @Override - public void setFlags(Lifespan lifespan, Collection flags) { - try (LockHold hold = object.getTrace().lockWrite()) { - for (TraceMemoryFlag flag : TraceMemoryFlag.values()) { - object.setValue(lifespan, keyForFlag(flag), flags.contains(flag)); - } - } - } - - @Override - public void addFlags(Lifespan lifespan, Collection flags) { - try (LockHold hold = object.getTrace().lockWrite()) { - for (TraceMemoryFlag flag : flags) { - object.setValue(lifespan, keyForFlag(flag), true); - } - } - } - - @Override - public void clearFlags(Lifespan lifespan, Collection flags) { - try (LockHold hold = object.getTrace().lockWrite()) { - for (TraceMemoryFlag flag : flags) { - object.setValue(lifespan, keyForFlag(flag), false); - } - } - } - - @Override - public void setFlags(long snap, Collection flags) { - try (LockHold hold = object.getTrace().lockWrite()) { - setFlags(Lifespan.nowOn(snap), flags); - } - } - - @Override - public void addFlags(long snap, Collection flags) { - try (LockHold hold = object.getTrace().lockWrite()) { - addFlags(Lifespan.nowOn(snap), flags); - } - } - - @Override - public void clearFlags(long snap, Collection flags) { - try (LockHold hold = object.getTrace().lockWrite()) { - clearFlags(Lifespan.nowOn(snap), flags); - } - } - - @Override - public Set getFlags(long snap) { - EnumSet result = EnumSet.noneOf(TraceMemoryFlag.class); - for (TraceMemoryFlag flag : TraceMemoryFlag.values()) { - TraceObjectValue value = object.getValue(snap, keyForFlag(flag)); - if (value != null && value.getValue() == Boolean.TRUE) { - result.add(flag); - } - } - return result; - } - - @Override - public void delete() { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.ALL); - } - } - - @Override - public void remove(long snap) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.nowOn(snap)); - } - } - - @Override - public boolean isValid(long snap) { - return object.isAlive(snap); - } - - @Override - public TraceObject getObject() { - return object; - } - - @Override - public TraceChangeRecord translateEvent(TraceChangeRecord rec) { - return translator.translate(rec); - } - - protected void updateViewsAdded() { - object.getTrace().updateViewsAddRegionBlock(this); - } - - protected void updateViewsLifespanChanged(Lifespan oldLifespan, Lifespan newLifespan) { - object.getTrace().updateViewsChangeRegionBlockLifespan(this, oldLifespan, newLifespan); - } - - protected void updateViewsValueChanged(Lifespan lifespan, String key, Object oldValue, - Object newValue) { - DBTrace trace = object.getTrace(); - if (translator.keys.isRange(key)) { - // NB. old/newValue are null here. The CREATED event just has the new entry. - trace.updateViewsRefreshBlocks(); - } - else if (translator.keys.isDisplay(key)) { - trace.updateViewsChangeRegionBlockName(this); - } - else if (translator.keys.isFlag(key)) { - trace.updateViewsChangeRegionBlockFlags(this, lifespan); - } - } - - protected void updateViewsDeleted() { - object.getTrace().updateViewsDeleteRegionBlock(this); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java index 9690888de4..ef84cc4eb7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java @@ -22,15 +22,15 @@ import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemoryState; -import ghidra.trace.model.memory.TraceObjectRegister; +import ghidra.trace.model.memory.TraceRegister; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectRegister implements TraceObjectRegister, DBTraceObjectInterface { +public class DBTraceObjectRegister implements TraceRegister, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectRegister(DBTraceObject object) { @@ -43,8 +43,8 @@ public class DBTraceObjectRegister implements TraceObjectRegister, DBTraceObject } @Override - public TraceObjectThread getThread() { - return object.queryCanonicalAncestorsInterface(TraceObjectThread.class) + public TraceThread getThread() { + return object.queryCanonicalAncestorsInterface(TraceThread.class) .findAny() .orElseThrow(); } @@ -57,7 +57,7 @@ public class DBTraceObjectRegister implements TraceObjectRegister, DBTraceObject @Override public int getBitLength(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectRegister.KEY_BITLENGTH, + return TraceObjectInterfaceUtils.getValue(object, snap, TraceRegister.KEY_BITLENGTH, Integer.class, 0); } @@ -67,12 +67,12 @@ public class DBTraceObjectRegister implements TraceObjectRegister, DBTraceObject if (length != 0 && value.length != length) { throw new IllegalArgumentException("Length must match the register"); } - object.setValue(lifespan, TraceObjectRegister.KEY_VALUE, value); + object.setValue(lifespan, TraceRegister.KEY_VALUE, value); } @Override public byte[] getValue(long snap) { - TraceObjectValue ov = object.getValue(snap, TraceObjectRegister.KEY_VALUE); + TraceObjectValue ov = object.getValue(snap, TraceRegister.KEY_VALUE); if (ov == null) { return null; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegisterContainer.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegisterContainer.java index e1e3ded1ae..dde3af8e4d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegisterContainer.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegisterContainer.java @@ -17,12 +17,12 @@ package ghidra.trace.database.memory; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; -import ghidra.trace.model.memory.TraceObjectRegisterContainer; +import ghidra.trace.model.memory.TraceRegisterContainer; import ghidra.trace.model.target.TraceObject; import ghidra.trace.util.TraceChangeRecord; public class DBTraceObjectRegisterContainer - implements TraceObjectRegisterContainer, DBTraceObjectInterface { + implements TraceRegisterContainer, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectRegisterContainer(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModule.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModule.java index 7c554a2175..4c0800eedd 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModule.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModule.java @@ -15,216 +15,243 @@ */ package ghidra.trace.database.module; -import java.util.Collection; -import java.util.Objects; +import java.util.*; +import java.util.stream.Collectors; -import db.DBRecord; 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.target.*; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.Trace; import ghidra.trace.model.modules.TraceModule; import ghidra.trace.model.modules.TraceSection; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; +import ghidra.trace.model.target.path.KeyPath; +import ghidra.trace.model.target.path.PathFilter; +import ghidra.trace.model.target.path.PathFilter.Align; +import ghidra.trace.model.target.schema.TraceObjectSchema; +import ghidra.trace.util.*; import ghidra.util.LockHold; -import ghidra.util.database.DBCachedObjectStore; -import ghidra.util.database.DBObjectColumn; -import ghidra.util.database.annot.*; import ghidra.util.exception.DuplicateNameException; -@DBAnnotatedObjectInfo(version = 0) -public class DBTraceModule extends AbstractDBTraceAddressSnapRangePropertyMapData - implements TraceModule { - static final String TABLE_NAME = "Modules"; +public class DBTraceModule implements TraceModule, DBTraceObjectInterface { - static final String PATH_COLUMN_NAME = "Path"; - static final String NAME_COLUMN_NAME = "Name"; + protected class ModuleChangeTranslator extends Translator { + private static final Map> KEYS_BY_SCHEMA = + new WeakHashMap<>(); - @DBAnnotatedColumn(PATH_COLUMN_NAME) - static DBObjectColumn PATH_COLUMN; - @DBAnnotatedColumn(NAME_COLUMN_NAME) - static DBObjectColumn NAME_COLUMN; + private final Set keys; - static String tableName(AddressSpace space) { - return DBTraceUtils.tableName(TABLE_NAME, space, -1, 0); + protected ModuleChangeTranslator(DBTraceObject object, TraceModule iface) { + super(KEY_RANGE, object, iface); + TraceObjectSchema schema = object.getSchema(); + synchronized (KEYS_BY_SCHEMA) { + keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( + s.checkAliasedAttribute(KEY_RANGE), + s.checkAliasedAttribute(KEY_DISPLAY))); + } + } + + @Override + protected TraceEvent getAddedType() { + return TraceEvents.MODULE_ADDED; + } + + @Override + protected TraceEvent getLifespanChangedType() { + return TraceEvents.MODULE_LIFESPAN_CHANGED; + } + + @Override + protected TraceEvent getChangedType() { + return TraceEvents.MODULE_CHANGED; + } + + @Override + protected boolean appliesToKey(String key) { + return keys.contains(key); + } + + @Override + protected TraceEvent getDeletedType() { + return TraceEvents.MODULE_DELETED; + } } - @DBAnnotatedField(column = PATH_COLUMN_NAME, indexed = true) - String path; - @DBAnnotatedField(column = NAME_COLUMN_NAME) - String name; + private final DBTraceObject object; + private final ModuleChangeTranslator translator; - final DBTraceModuleSpace space; + public DBTraceModule(DBTraceObject object) { + this.object = object; - public DBTraceModule(DBTraceModuleSpace space, - DBTraceAddressSnapRangePropertyMapTree tree, - DBCachedObjectStore store, DBRecord record) { - super(tree, store, record); - this.space = space; + translator = new ModuleChangeTranslator(object, this); } @Override - protected void setRecordValue(DBTraceModule value) { - // Nothing. This is the record + public Trace getTrace() { + return object.getTrace(); } @Override - protected DBTraceModule getRecordValue() { - return this; - } - - void set(String path, String name) { - this.path = path; - this.name = name; - update(PATH_COLUMN, NAME_COLUMN); - } - - @Override - public DBTrace getTrace() { - return space.trace; - } - - @Override - public DBTraceSection addSection(long snap, String sectionPath, String sectionName, + public TraceSection addSection(long snap, String sectionPath, String sectionName, AddressRange range) throws DuplicateNameException { - try (LockHold hold = LockHold.lock(space.manager.writeLock())) { - return space.manager.doAddSection(this, sectionPath, sectionName, range); + try (LockHold hold = object.getTrace().lockWrite()) { + DBTraceObjectManager manager = object.getManager(); + KeyPath sectionKeyList = KeyPath.parse(sectionPath); + if (!object.getCanonicalPath().isAncestor(sectionKeyList)) { + throw new IllegalArgumentException( + "Section path must be a successor of this module's path"); + } + return manager.addSection(sectionPath, sectionName, Lifespan.nowOn(snap), range); } } @Override public String getPath() { - try (LockHold hold = LockHold.lock(space.manager.readLock())) { - return path; - } + return object.getCanonicalPath().toString(); + } + + @Override + public void setName(Lifespan lifespan, String name) { + object.setValue(lifespan, KEY_MODULE_NAME, name); } @Override public void setName(long snap, String name) { - try (LockHold hold = LockHold.lock(space.manager.writeLock())) { - if (Objects.equals(this.name, name)) { - return; - } - this.name = name; - update(NAME_COLUMN); + try (LockHold hold = object.getTrace().lockWrite()) { + setName(Lifespan.nowOn(snap), name); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.MODULE_CHANGED, null, this)); } @Override public String getName(long snap) { - try (LockHold hold = LockHold.lock(space.manager.readLock())) { - return name; + String key = object.getCanonicalPath().key(); + String index = KeyPath.parseIfIndex(key); + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_MODULE_NAME, String.class, + index); + } + + @Override + public void setRange(Lifespan lifespan, AddressRange range) { + try (LockHold hold = object.getTrace().lockWrite()) { + object.setValue(lifespan, KEY_RANGE, range); } } @Override public void setRange(long snap, AddressRange range) { - try (LockHold hold = LockHold.lock(space.manager.writeLock())) { - if (this.range.equals(range)) { - return; - } - doSetRange(range); + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(Lifespan.nowOn(snap), range); } - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.MODULE_CHANGED, space, this)); } @Override public AddressRange getRange(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range; + try (LockHold hold = object.getTrace().lockRead()) { + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_RANGE, AddressRange.class, + null); } } @Override public void setBase(long snap, Address base) { - try (LockHold hold = LockHold.lock(space.manager.writeLock())) { - setRange(snap, DBTraceUtils.toRange(base, range.getMaxAddress())); + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(snap, DBTraceUtils.toRange(base, getMaxAddress(snap))); } } @Override public Address getBase(long snap) { - try (LockHold hold = LockHold.lock(space.manager.readLock())) { - return range.getMinAddress(); - } + AddressRange range = getRange(snap); + return range == null ? null : range.getMinAddress(); } @Override public void setMaxAddress(long snap, Address max) { - try (LockHold hold = LockHold.lock(space.manager.writeLock())) { - setRange(snap, DBTraceUtils.toRange(range.getMinAddress(), max)); + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(snap, DBTraceUtils.toRange(getBase(snap), max)); } } @Override public Address getMaxAddress(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range.getMaxAddress(); - } + AddressRange range = getRange(snap); + return range == null ? null : range.getMaxAddress(); } @Override public void setLength(long snap, long length) throws AddressOverflowException { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - Address base = range.getMinAddress(); - setRange(snap, DBTraceUtils.toRange(base, base.addNoWrap(length - 1))); + try (LockHold hold = object.getTrace().lockWrite()) { + setRange(snap, new AddressRangeImpl(getBase(snap), length)); } } @Override public long getLength(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range.getLength(); + AddressRange range = getRange(snap); + return range == null ? 0 : range.getLength(); + } + + @Override + public Collection getSections(long snap) { + try (LockHold hold = object.getTrace().lockRead()) { + return object + .querySuccessorsInterface(Lifespan.at(snap), TraceSection.class, true) + .collect(Collectors.toSet()); } } @Override - public Collection getSections(long snap) { - return getAllSections(); - } - - @Override - public Collection getAllSections() { - return space.manager.doGetSectionsByModuleId(getKey()); + public Collection getAllSections() { + try (LockHold hold = object.getTrace().lockRead()) { + return object + .querySuccessorsInterface(Lifespan.ALL, TraceSection.class, true) + .collect(Collectors.toSet()); + } } @Override public TraceSection getSectionByName(long snap, String sectionName) { - return space.manager.doGetSectionByName(getKey(), sectionName); + PathFilter filter = object.getSchema().searchFor(TraceSection.class, true); + PathFilter applied = filter.applyKeys(Align.LEFT, List.of(sectionName)); + return object.getSuccessors(Lifespan.at(snap), applied) + .map(p -> p.getDestination(object).queryInterface(TraceSection.class)) + .findAny() + .orElse(null); } @Override public void delete() { - space.manager.doDeleteModule(this); + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.ALL); + } } @Override public void remove(long snap) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - if (snap <= lifespan.lmin()) { - space.manager.doDeleteModule(this); - } - else if (snap <= lifespan.lmax()) { - doSetLifespan(lifespan.withMax(snap - 1)); - } + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.nowOn(snap)); } } @Override public boolean isValid(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return lifespan.contains(snap); - } + return object.isAlive(snap); } @Override public boolean isAlive(Lifespan span) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return lifespan.intersects(span); - } + return object.isAlive(span); + } + + @Override + public TraceObject getObject() { + return object; + } + + @Override + public TraceChangeRecord translateEvent(TraceChangeRecord rec) { + return translator.translate(rec); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleManager.java index ca56e2fc1f..51d003eba9 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleManager.java @@ -16,81 +16,45 @@ package ghidra.trace.database.module; import java.io.IOException; -import java.util.*; -import java.util.concurrent.locks.Lock; +import java.util.Collection; +import java.util.Collections; import java.util.concurrent.locks.ReadWriteLock; import db.DBHandle; import ghidra.framework.data.OpenMode; -import ghidra.program.model.address.*; -import ghidra.program.model.lang.Language; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressRange; import ghidra.trace.database.DBTrace; -import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager; -import ghidra.trace.database.space.DBTraceDelegatingManager; +import ghidra.trace.database.DBTraceManager; +import ghidra.trace.database.target.DBTraceObjectManager; import ghidra.trace.model.Lifespan; import ghidra.trace.model.modules.*; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; -public class DBTraceModuleManager extends AbstractDBTraceSpaceBasedManager - implements TraceModuleManager, DBTraceDelegatingManager { - public static final String NAME = "Module"; +public class DBTraceModuleManager implements TraceModuleManager, DBTraceManager { + protected final ReadWriteLock lock; + protected final DBTrace trace; + protected final DBTraceObjectManager objectManager; public DBTraceModuleManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock, - TaskMonitor monitor, Language baseLanguage, DBTrace trace) + TaskMonitor monitor, DBTrace trace, DBTraceObjectManager objectManager) throws VersionException, IOException { - super(NAME, dbh, openMode, lock, monitor, baseLanguage, trace, null); - loadSpaces(); + this.lock = lock; + this.trace = trace; + this.objectManager = objectManager; } @Override - public DBTraceModuleSpace getForSpace(AddressSpace space, boolean createIfAbsent) { - return super.getForSpace(space, createIfAbsent); + public void dbError(IOException e) { + trace.dbError(e); } @Override - protected DBTraceModuleSpace getForRegisterSpace(TraceThread thread, int frameLevel, - boolean createIfAbsent) { - throw new UnsupportedOperationException(); - } - - protected void checkModulePathConflicts(TraceModule ignore, String modulePath, - Lifespan moduleLifespan) throws DuplicateNameException { - for (TraceModule pc : doGetModulesByPath(modulePath)) { - if (pc == ignore) { - continue; - } - if (!pc.isAlive(moduleLifespan)) { - continue; - } - throw new DuplicateNameException( - "Module with path '" + modulePath + "' already exists within an overlapping snap"); - } - } - - protected void checkSectionPathConflicts(DBTraceSection ignore, String sectionPath, - Lifespan moduleLifespan) throws DuplicateNameException { - Collection pathConflicts = doGetSectionsByPath(sectionPath); - for (TraceSection pc : pathConflicts) { - if (pc == ignore) { - continue; - } - /** - * TODO: Certainly, any two sections at the same path will belong to the same module and - * so have the same lifespan, no? I suppose this logic is only true in objects mode..., - * and there, the logic is performed by the value key duplicate check. - */ - if (!pc.getModule().isAlive(moduleLifespan)) { - continue; - } - throw new DuplicateNameException("Section with path '" + sectionPath + - "' already exists within an overlapping snap"); - } + public void invalidateCache(boolean all) { + // NOTE: This is only a wrapper around the object manager } @Override @@ -103,19 +67,11 @@ public class DBTraceModuleManager extends AbstractDBTraceSpaceBasedManager m.doAddModule(modulePath, moduleName, range, lifespan)); + return objectManager.addModule(modulePath, moduleName, lifespan, range); } protected Collection doGetModulesByPath(String modulePath) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getObjectsByPath(modulePath, TraceObjectModule.class); - } - return delegateCollection(memSpaces.values(), m -> m.doGetModulesByPath(modulePath)); + return objectManager.getObjectsByPath(modulePath, TraceModule.class); } @Override @@ -125,136 +81,52 @@ public class DBTraceModuleManager extends AbstractDBTraceSpaceBasedManager m.isValid(snap)) - .findAny() - .orElse(null); - } + return objectManager.getObjectByPath(snap, modulePath, TraceModule.class); } @Override public Collection getAllModules() { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getAllObjects(TraceObjectModule.class); - } - return delegateCollection(memSpaces.values(), m -> m.getAllModules()); + return objectManager.getAllObjects(TraceModule.class); } @Override public Collection getLoadedModules(long snap) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getObjectsAtSnap(snap, TraceObjectModule.class); - } - return delegateCollection(memSpaces.values(), m -> m.getLoadedModules(snap)); + return objectManager.getObjectsAtSnap(snap, TraceModule.class); } @Override public Collection getModulesAt(long snap, Address address) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsContaining(snap, address, TraceObjectModule.KEY_RANGE, - TraceObjectModule.class); - } - return delegateRead(address.getAddressSpace(), m -> m.getModulesAt(snap, address), - Set.of()); + return objectManager.getObjectsContaining(snap, address, TraceModule.KEY_RANGE, + TraceModule.class); } @Override public Collection getModulesIntersecting(Lifespan lifespan, AddressRange range) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsIntersecting(lifespan, range, TraceObjectModule.KEY_RANGE, - TraceObjectModule.class); - } - return delegateRead(range.getAddressSpace(), m -> m.getModulesIntersecting(lifespan, range), - Set.of()); - } - - @Override - public ReadWriteLock getLock() { - return lock; + return objectManager.getObjectsIntersecting(lifespan, range, TraceModule.KEY_RANGE, + TraceModule.class); } @Override public Collection getSectionsAt(long snap, Address address) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsContaining(snap, address, TraceObjectSection.KEY_RANGE, - TraceObjectSection.class); - } - return delegateRead(address.getAddressSpace(), m -> m.getSectionsAt(snap, address), - Set.of()); + return objectManager.getObjectsContaining(snap, address, TraceSection.KEY_RANGE, + TraceSection.class); } @Override public Collection getSectionsIntersecting(Lifespan lifespan, AddressRange range) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager() - .getObjectsIntersecting(lifespan, range, TraceObjectSection.KEY_RANGE, - TraceObjectSection.class); - } - return delegateRead(range.getAddressSpace(), - m -> m.getSectionsIntersecting(lifespan, range), Set.of()); - } - - @Override - public Lock readLock() { - return lock.readLock(); - } - - @Override - public Lock writeLock() { - return lock.writeLock(); - } - - @Override - protected DBTraceModuleSpace createSpace(AddressSpace space, DBTraceSpaceEntry ent) - throws VersionException, IOException { - return new DBTraceModuleSpace(this, space); - } - - @Override - protected DBTraceModuleSpace createRegisterSpace(AddressSpace space, TraceThread thread, - DBTraceSpaceEntry ent) throws VersionException, IOException { - throw new AssertionError(); - } - - protected DBTraceSection doAddSection(DBTraceModule module, String sectionPath, - String sectionName, AddressRange range) throws DuplicateNameException { - checkSectionPathConflicts(null, sectionPath, module.getLifespan()); - DBTraceSection nameConflicts = doGetSectionByName(module.getKey(), sectionName); - if (nameConflicts != null) { - throw new DuplicateNameException( - "Section with name '" + sectionName + "' already exists"); - } - return delegateWrite(range.getAddressSpace(), - m -> m.doAddSection(module, sectionPath, sectionName, range)); + return objectManager.getObjectsIntersecting(lifespan, range, TraceSection.KEY_RANGE, + TraceSection.class); } @Override public Collection getAllSections() { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getAllObjects(TraceObjectSection.class); - } - return delegateCollection(memSpaces.values(), m -> m.getAllSections()); - } - - protected Collection doGetSectionsByModuleId(long key) { - return delegateCollection(memSpaces.values(), m -> m.doGetSectionsByModuleId(key)); + return objectManager.getAllObjects(TraceSection.class); } protected Collection doGetSectionsByPath(String sectionPath) { - if (trace.getObjectManager().hasSchema()) { - return trace.getObjectManager().getObjectsByPath(sectionPath, TraceObjectSection.class); - } - return delegateCollection(memSpaces.values(), m -> m.doGetSectionsByPath(sectionPath)); + return objectManager.getObjectsByPath(sectionPath, TraceSection.class); } @Override @@ -266,34 +138,6 @@ public class DBTraceModuleManager extends AbstractDBTraceSpaceBasedManager s.getModule().isValid(snap)) - .findAny() - .orElse(null); - } - } - - protected DBTraceSection doGetSectionByName(long moduleKey, String sectionName) { - try (LockHold hold = LockHold.lock(lock.readLock())) { - return delegateFirst(memSpaces.values(), - m -> m.doGetSectionByName(moduleKey, sectionName)); - } - } - - protected void doDeleteModule(DBTraceModule module) { - try (LockHold hold = LockHold.lock(lock.writeLock())) { - for (DBTraceSection section : new ArrayList<>( - doGetSectionsByModuleId(module.getKey()))) { - section.space.sectionMapSpace.deleteData(section); - // NOTE: Don't send section events. Module event should suffice. - } - module.space.moduleMapSpace.deleteData(module); - } - trace.setChanged(new TraceChangeRecord<>(TraceEvents.MODULE_DELETED, null, module)); + return objectManager.getObjectByPath(snap, sectionPath, TraceSection.class); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleSpace.java deleted file mode 100644 index c2140ca255..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceModuleSpace.java +++ /dev/null @@ -1,183 +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.module; - -import java.io.IOException; -import java.util.*; -import java.util.concurrent.locks.ReadWriteLock; - -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.DBTraceSpaceBased; -import ghidra.trace.database.thread.DBTraceThread; -import ghidra.trace.model.ImmutableTraceAddressSnapRange; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.modules.TraceModuleSpace; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; -import ghidra.util.database.DBCachedObjectIndex; -import ghidra.util.exception.VersionException; - -public class DBTraceModuleSpace implements TraceModuleSpace, DBTraceSpaceBased { - protected final DBTraceModuleManager manager; - protected final AddressSpace space; - protected final ReadWriteLock lock; - protected final DBTrace trace; - - protected final DBTraceAddressSnapRangePropertyMapSpace moduleMapSpace; - protected final DBCachedObjectIndex modulesByPath; - protected final Collection moduleView; - - protected final DBTraceAddressSnapRangePropertyMapSpace sectionMapSpace; - protected final DBCachedObjectIndex sectionsByModuleKey; - protected final DBCachedObjectIndex sectionsByPath; - protected final Collection sectionView; - - public DBTraceModuleSpace(DBTraceModuleManager manager, AddressSpace space) - throws VersionException, IOException { - this.manager = manager; - this.space = space; - this.lock = manager.getLock(); - this.trace = manager.getTrace(); - - this.moduleMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceModule.tableName(space), trace.getStoreFactory(), lock, space, null, 0, - DBTraceModule.class, (t, s, r) -> new DBTraceModule(this, t, s, r)); - this.modulesByPath = moduleMapSpace.getUserIndex(String.class, DBTraceModule.PATH_COLUMN); - this.moduleView = Collections.unmodifiableCollection(moduleMapSpace.values()); - - this.sectionMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceSection.tableName(space), trace.getStoreFactory(), lock, space, null, 0, - DBTraceSection.class, (t, s, r) -> new DBTraceSection(this, t, s, r)); - this.sectionsByModuleKey = - sectionMapSpace.getUserIndex(long.class, DBTraceSection.MODULE_COLUMN); - this.sectionsByPath = - sectionMapSpace.getUserIndex(String.class, DBTraceSection.PATH_COLUMN); - this.sectionView = Collections.unmodifiableCollection(sectionMapSpace.values()); - } - - @Override - public DBTraceThread getThread() { - return null; - } - - @Override - public int getFrameLevel() { - return 0; - } - - @Override - public void invalidateCache() { - moduleMapSpace.invalidateCache(); - sectionMapSpace.invalidateCache(); - } - - @Override - public AddressSpace getAddressSpace() { - return space; - } - - protected DBTraceModule doAddModule(String modulePath, String moduleName, AddressRange range, - Lifespan lifespan) { - DBTraceModule module = moduleMapSpace - .put(new ImmutableTraceAddressSnapRange(range, lifespan), null); - module.set(modulePath, moduleName); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.MODULE_ADDED, null, module)); - return module; - } - - @Override - public Collection getAllModules() { - return moduleView; - } - - protected Collection doGetModulesByPath(String modulePath) { - return modulesByPath.get(modulePath); - } - - @Override - public Collection getLoadedModules(long snap) { - return Collections.unmodifiableCollection( - moduleMapSpace.reduce(TraceAddressSnapRangeQuery.atSnap(snap, space)).values()); - } - - @Override - public Collection getModulesAt(long snap, Address address) { - return Collections.unmodifiableCollection( - moduleMapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).values()); - } - - @Override - public Collection getModulesIntersecting(Lifespan lifespan, - AddressRange range) { - return Collections.unmodifiableCollection( - moduleMapSpace.reduce(TraceAddressSnapRangeQuery.intersecting(range, lifespan)) - .values()); - } - - public DBTraceSection doAddSection(DBTraceModule module, String sectionPath, String sectionName, - AddressRange range) { - DBTraceSection section = sectionMapSpace - .put(new ImmutableTraceAddressSnapRange(range, module.getLifespan()), null); - section.set(module, sectionPath, sectionName); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.SECTION_ADDED, null, section)); - return section; - } - - @Override - public Collection getAllSections() { - return sectionView; - } - - @Override - public Collection getSectionsAt(long snap, Address address) { - return Collections.unmodifiableCollection( - sectionMapSpace.reduce(TraceAddressSnapRangeQuery.at(address, snap)).values()); - } - - @Override - public Collection getSectionsIntersecting(Lifespan lifespan, - AddressRange range) { - return Collections.unmodifiableCollection( - sectionMapSpace.reduce(TraceAddressSnapRangeQuery.intersecting(range, lifespan)) - .values()); - } - - public Collection doGetSectionsByModuleId(long key) { - return sectionsByModuleKey.get(key); - } - - public DBTraceSection doGetSectionByName(long moduleKey, String sectionName) { - for (DBTraceSection section : sectionsByModuleKey.get(moduleKey)) { - // Legacy manager does not consider snap in name - if (!Objects.equals(section.getName(0), sectionName)) { - continue; - } - return section; - } - return null; - } - - public Collection doGetSectionsByPath(String sectionPath) { - return sectionsByPath.get(sectionPath); - } - - public DBTraceModule doGetModuleById(long moduleKey) { - return moduleMapSpace.getDataByKey(moduleKey); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceObjectModule.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceObjectModule.java deleted file mode 100644 index acade328d6..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceObjectModule.java +++ /dev/null @@ -1,255 +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.module; - -import java.util.*; -import java.util.stream.Collectors; - -import ghidra.program.model.address.*; -import ghidra.trace.database.DBTraceUtils; -import ghidra.trace.database.target.*; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.Trace; -import ghidra.trace.model.modules.*; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; -import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.path.PathFilter; -import ghidra.trace.model.target.path.PathFilter.Align; -import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.util.*; -import ghidra.util.LockHold; -import ghidra.util.exception.DuplicateNameException; - -public class DBTraceObjectModule implements TraceObjectModule, DBTraceObjectInterface { - - protected class ModuleChangeTranslator extends Translator { - private static final Map> KEYS_BY_SCHEMA = - new WeakHashMap<>(); - - private final Set keys; - - protected ModuleChangeTranslator(DBTraceObject object, TraceModule iface) { - super(TraceObjectModule.KEY_RANGE, object, iface); - TraceObjectSchema schema = object.getSchema(); - synchronized (KEYS_BY_SCHEMA) { - keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( - s.checkAliasedAttribute(TraceObjectModule.KEY_RANGE), - s.checkAliasedAttribute(TraceObjectInterface.KEY_DISPLAY))); - } - } - - @Override - protected TraceEvent getAddedType() { - return TraceEvents.MODULE_ADDED; - } - - @Override - protected TraceEvent getLifespanChangedType() { - return TraceEvents.MODULE_LIFESPAN_CHANGED; - } - - @Override - protected TraceEvent getChangedType() { - return TraceEvents.MODULE_CHANGED; - } - - @Override - protected boolean appliesToKey(String key) { - return keys.contains(key); - } - - @Override - protected TraceEvent getDeletedType() { - return TraceEvents.MODULE_DELETED; - } - } - - private final DBTraceObject object; - private final ModuleChangeTranslator translator; - - public DBTraceObjectModule(DBTraceObject object) { - this.object = object; - - translator = new ModuleChangeTranslator(object, this); - } - - @Override - public Trace getTrace() { - return object.getTrace(); - } - - @Override - public TraceSection addSection(long snap, String sectionPath, String sectionName, - AddressRange range) throws DuplicateNameException { - try (LockHold hold = object.getTrace().lockWrite()) { - DBTraceObjectManager manager = object.getManager(); - KeyPath sectionKeyList = KeyPath.parse(sectionPath); - if (!object.getCanonicalPath().isAncestor(sectionKeyList)) { - throw new IllegalArgumentException( - "Section path must be a successor of this module's path"); - } - return manager.addSection(sectionPath, sectionName, Lifespan.nowOn(snap), range); - } - } - - @Override - public String getPath() { - return object.getCanonicalPath().toString(); - } - - @Override - public void setName(Lifespan lifespan, String name) { - object.setValue(lifespan, TraceObjectModule.KEY_MODULE_NAME, name); - } - - @Override - public void setName(long snap, String name) { - try (LockHold hold = object.getTrace().lockWrite()) { - setName(Lifespan.nowOn(snap), name); - } - } - - @Override - public String getName(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectModule.KEY_MODULE_NAME, - String.class, ""); - } - - @Override - public void setRange(Lifespan lifespan, AddressRange range) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(lifespan, TraceObjectModule.KEY_RANGE, range); - } - } - - @Override - public void setRange(long snap, AddressRange range) { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(Lifespan.nowOn(snap), range); - } - } - - @Override - public AddressRange getRange(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectModule.KEY_RANGE, - AddressRange.class, null); - } - } - - @Override - public void setBase(long snap, Address base) { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(snap, DBTraceUtils.toRange(base, getMaxAddress(snap))); - } - } - - @Override - public Address getBase(long snap) { - AddressRange range = getRange(snap); - return range == null ? null : range.getMinAddress(); - } - - @Override - public void setMaxAddress(long snap, Address max) { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(snap, DBTraceUtils.toRange(getBase(snap), max)); - } - } - - @Override - public Address getMaxAddress(long snap) { - AddressRange range = getRange(snap); - return range == null ? null : range.getMaxAddress(); - } - - @Override - public void setLength(long snap, long length) throws AddressOverflowException { - try (LockHold hold = object.getTrace().lockWrite()) { - setRange(snap, new AddressRangeImpl(getBase(snap), length)); - } - } - - @Override - public long getLength(long snap) { - AddressRange range = getRange(snap); - return range == null ? 0 : range.getLength(); - } - - @Override - public Collection getSections(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return object - .querySuccessorsInterface(Lifespan.at(snap), TraceObjectSection.class, true) - .collect(Collectors.toSet()); - } - } - - @Override - public Collection getAllSections() { - try (LockHold hold = object.getTrace().lockRead()) { - return object - .querySuccessorsInterface(Lifespan.ALL, TraceObjectSection.class, true) - .collect(Collectors.toSet()); - } - } - - @Override - public TraceObjectSection getSectionByName(long snap, String sectionName) { - PathFilter filter = object.getSchema().searchFor(TraceObjectSection.class, true); - PathFilter applied = filter.applyKeys(Align.LEFT, List.of(sectionName)); - return object.getSuccessors(Lifespan.at(snap), applied) - .map(p -> p.getDestination(object).queryInterface(TraceObjectSection.class)) - .findAny() - .orElse(null); - } - - @Override - public void delete() { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.ALL); - } - } - - @Override - public void remove(long snap) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.nowOn(snap)); - } - } - - @Override - public boolean isValid(long snap) { - return object.isAlive(snap); - } - - @Override - public boolean isAlive(Lifespan span) { - return object.isAlive(span); - } - - @Override - public TraceObject getObject() { - return object; - } - - @Override - public TraceChangeRecord translateEvent(TraceChangeRecord rec) { - return translator.translate(rec); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceObjectSection.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceObjectSection.java deleted file mode 100644 index 1a16034331..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceObjectSection.java +++ /dev/null @@ -1,170 +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.module; - -import java.util.*; - -import ghidra.program.model.address.AddressRange; -import ghidra.trace.database.target.DBTraceObject; -import ghidra.trace.database.target.DBTraceObjectInterface; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.Trace; -import ghidra.trace.model.modules.TraceObjectModule; -import ghidra.trace.model.modules.TraceSection; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; -import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.util.*; -import ghidra.util.LockHold; - -public class DBTraceObjectSection implements TraceObjectSection, DBTraceObjectInterface { - - protected class SectionTranslator extends Translator { - private static final Map> KEYS_BY_SCHEMA = - new WeakHashMap<>(); - - private final Set keys; - - protected SectionTranslator(DBTraceObject object, TraceSection iface) { - super(TraceObjectSection.KEY_RANGE, object, iface); - TraceObjectSchema schema = object.getSchema(); - synchronized (KEYS_BY_SCHEMA) { - keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( - s.checkAliasedAttribute(TraceObjectSection.KEY_RANGE), - s.checkAliasedAttribute(TraceObjectInterface.KEY_DISPLAY))); - } - } - - @Override - protected TraceEvent getAddedType() { - return TraceEvents.SECTION_ADDED; - } - - @Override - protected TraceEvent getLifespanChangedType() { - return null; // it's the module's lifespan that matters. - } - - @Override - protected TraceEvent getChangedType() { - return TraceEvents.SECTION_CHANGED; - } - - @Override - protected boolean appliesToKey(String key) { - return keys.contains(key); - } - - @Override - protected TraceEvent getDeletedType() { - return TraceEvents.SECTION_DELETED; - } - } - - private final DBTraceObject object; - private final SectionTranslator translator; - - public DBTraceObjectSection(DBTraceObject object) { - this.object = object; - - translator = new SectionTranslator(object, this); - } - - @Override - public Trace getTrace() { - return object.getTrace(); - } - - @Override - public TraceObjectModule getModule() { - try (LockHold hold = object.getTrace().lockRead()) { - return object.queryCanonicalAncestorsInterface(TraceObjectModule.class) - .findAny() - .orElseThrow(); - } - } - - @Override - public String getPath() { - return object.getCanonicalPath().toString(); - } - - @Override - public void setName(Lifespan lifespan, String name) { - object.setValue(lifespan, TraceObjectInterface.KEY_DISPLAY, name); - } - - @Override - public void setName(long snap, String name) { - try (LockHold hold = object.getTrace().lockWrite()) { - setName(Lifespan.nowOn(snap), name); - } - } - - @Override - public String getName(long snap) { - String key = object.getCanonicalPath().key(); - String index = KeyPath.parseIfIndex(key); - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectInterface.KEY_DISPLAY, - String.class, index); - } - - @Override - public void setRange(Lifespan lifespan, AddressRange range) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(lifespan, TraceObjectModule.KEY_RANGE, range); - } - } - - @Override - public AddressRange getRange(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectModule.KEY_RANGE, - AddressRange.class, null); - } - } - - @Override - public void delete() { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.ALL); - } - } - - @Override - public void remove(long snap) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.nowOn(snap)); - } - } - - @Override - public boolean isValid(long snap) { - return object.isAlive(snap); - } - - @Override - public TraceObject getObject() { - return object; - } - - @Override - public TraceChangeRecord translateEvent(TraceChangeRecord rec) { - return translator.translate(rec); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceSection.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceSection.java index 6cab28118a..d5c4223647 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceSection.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceSection.java @@ -15,173 +15,154 @@ */ package ghidra.trace.database.module; -import java.io.IOException; -import java.util.Objects; +import java.util.*; -import db.DBRecord; import ghidra.program.model.address.AddressRange; -import ghidra.program.model.address.AddressSpace; -import ghidra.trace.database.DBTraceUtils; -import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree; -import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData; +import ghidra.trace.database.target.DBTraceObject; +import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; +import ghidra.trace.model.modules.TraceModule; import ghidra.trace.model.modules.TraceSection; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; +import ghidra.trace.model.target.path.KeyPath; +import ghidra.trace.model.target.schema.TraceObjectSchema; +import ghidra.trace.util.*; import ghidra.util.LockHold; -import ghidra.util.database.DBCachedObjectStore; -import ghidra.util.database.DBObjectColumn; -import ghidra.util.database.annot.*; -import ghidra.util.exception.DuplicateNameException; -@DBAnnotatedObjectInfo(version = 0) -public class DBTraceSection extends AbstractDBTraceAddressSnapRangePropertyMapData - implements TraceSection { - private static final String TABLE_NAME = "Sections"; +public class DBTraceSection implements TraceSection, DBTraceObjectInterface { - static final String MODULE_COLUMN_NAME = "Module"; - static final String PATH_COLUMN_NAME = "Path"; - static final String NAME_COLUMN_NAME = "Name"; + protected class SectionTranslator extends Translator { + private static final Map> KEYS_BY_SCHEMA = + new WeakHashMap<>(); - @DBAnnotatedColumn(MODULE_COLUMN_NAME) - static DBObjectColumn MODULE_COLUMN; - @DBAnnotatedColumn(PATH_COLUMN_NAME) - static DBObjectColumn PATH_COLUMN; - @DBAnnotatedColumn(NAME_COLUMN_NAME) - static DBObjectColumn NAME_COLUMN; + private final Set keys; - static String tableName(AddressSpace space) { - return DBTraceUtils.tableName(TABLE_NAME, space, -1, 0); - } - - @DBAnnotatedField(column = MODULE_COLUMN_NAME, indexed = true) - private long moduleKey; - @DBAnnotatedField(column = PATH_COLUMN_NAME, indexed = true) - private String path; - @DBAnnotatedField(column = NAME_COLUMN_NAME) - private String name; - - final DBTraceModuleSpace space; - - private DBTraceModule module; - - public DBTraceSection(DBTraceModuleSpace space, - DBTraceAddressSnapRangePropertyMapTree tree, - DBCachedObjectStore store, DBRecord record) { - super(tree, store, record); - this.space = space; - } - - @Override - protected void setRecordValue(DBTraceSection value) { - // Nothing. This is the record - } - - @Override - protected DBTraceSection getRecordValue() { - return this; - } - - @Override - protected void fresh(boolean created) throws IOException { - super.fresh(created); - if (created) { - return; + protected SectionTranslator(DBTraceObject object, TraceSection iface) { + super(KEY_RANGE, object, iface); + TraceObjectSchema schema = object.getSchema(); + synchronized (KEYS_BY_SCHEMA) { + keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( + s.checkAliasedAttribute(KEY_RANGE), + s.checkAliasedAttribute(KEY_DISPLAY))); + } + } + + @Override + protected TraceEvent getAddedType() { + return TraceEvents.SECTION_ADDED; + } + + @Override + protected TraceEvent getLifespanChangedType() { + return null; // it's the module's lifespan that matters. + } + + @Override + protected TraceEvent getChangedType() { + return TraceEvents.SECTION_CHANGED; + } + + @Override + protected boolean appliesToKey(String key) { + return keys.contains(key); + } + + @Override + protected TraceEvent getDeletedType() { + return TraceEvents.SECTION_DELETED; } - /** - * TODO: This may cause a problem when modules span multiple spaces. Well, the whole "unique - * path" thing may already be a problem in that case, since each module is allowed one - * address range. Maybe unique names within spaces only, and somehow a module comprises all - * its entries among the spaces. - */ - this.module = space.doGetModuleById(moduleKey); } - void set(DBTraceModule module, String path, String name) { - this.moduleKey = module.getKey(); - this.path = path; - this.name = name; - update(MODULE_COLUMN, PATH_COLUMN, NAME_COLUMN); + private final DBTraceObject object; + private final SectionTranslator translator; - this.module = module; + public DBTraceSection(DBTraceObject object) { + this.object = object; + + translator = new SectionTranslator(object, this); } @Override public Trace getTrace() { - return space.trace; + return object.getTrace(); } @Override - public DBTraceModule getModule() { - return module; - } - - @Override // Expose to this package - protected void doSetLifespan(Lifespan lifespan) { - super.doSetLifespan(lifespan); - } - - @Override - public String getPath() { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return path; + public TraceModule getModule() { + try (LockHold hold = object.getTrace().lockRead()) { + return object.queryCanonicalAncestorsInterface(TraceModule.class) + .findAny() + .orElseThrow(); } } @Override - public void setName(long snap, String name) throws DuplicateNameException { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - if (Objects.equals(this.name, name)) { - return; - } - DBTraceSection exists = space.manager.doGetSectionByName(moduleKey, name); - if (exists != null) { - throw new DuplicateNameException(name + " (in " + module + ")"); - } - this.name = name; - update(NAME_COLUMN); - module.space.trace - .setChanged(new TraceChangeRecord<>(TraceEvents.SECTION_CHANGED, null, this)); + public String getPath() { + return object.getCanonicalPath().toString(); + } + + @Override + public void setName(Lifespan lifespan, String name) { + object.setValue(lifespan, KEY_DISPLAY, name); + } + + @Override + public void setName(long snap, String name) { + try (LockHold hold = object.getTrace().lockWrite()) { + setName(Lifespan.nowOn(snap), name); } } @Override public String getName(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return name; + String key = object.getCanonicalPath().key(); + String index = KeyPath.parseIfIndex(key); + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, index); + } + + @Override + public void setRange(Lifespan lifespan, AddressRange range) { + try (LockHold hold = object.getTrace().lockWrite()) { + object.setValue(lifespan, KEY_RANGE, range); } } @Override public AddressRange getRange(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return range; + try (LockHold hold = object.getTrace().lockRead()) { + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_RANGE, + AddressRange.class, null); } } @Override public void delete() { - space.sectionMapSpace.deleteData(this); - space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.SECTION_DELETED, null, this)); + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.ALL); + } } @Override public void remove(long snap) { - try (LockHold hold = LockHold.lock(space.lock.writeLock())) { - if (snap <= lifespan.lmin()) { - delete(); - } - else if (snap <= lifespan.lmax()) { - doSetLifespan(lifespan.withMax(snap - 1)); - } + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.nowOn(snap)); } } @Override public boolean isValid(long snap) { - try (LockHold hold = LockHold.lock(space.lock.readLock())) { - return lifespan.contains(snap); - } + return object.isAlive(snap); + } + + @Override + public TraceObject getObject() { + return object; + } + + @Override + public TraceChangeRecord translateEvent(TraceChangeRecord rec) { + return translator.translate(rec); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceStaticMappingManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceStaticMappingManager.java index b6ccaaee3f..ffa8463e58 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceStaticMappingManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/DBTraceStaticMappingManager.java @@ -4,9 +4,9 @@ * 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. @@ -107,7 +107,8 @@ public class DBTraceStaticMappingManager implements TraceStaticMappingManager, D } DBTraceStaticMapping mapping = mappingStore.create(); mapping.set(range, lifespan, toProgramURL, toAddress); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.MAPPING_ADDED, null, mapping)); + trace.setChanged(new TraceChangeRecord<>(TraceEvents.MAPPING_ADDED, + range.getAddressSpace(), mapping)); return mapping; } } @@ -176,6 +177,7 @@ public class DBTraceStaticMappingManager implements TraceStaticMappingManager, D public void delete(DBTraceStaticMapping mapping) { mappingStore.delete(mapping); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.MAPPING_DELETED, null, mapping)); + trace.setChanged(new TraceChangeRecord<>(TraceEvents.MAPPING_DELETED, + mapping.getTraceAddressRange().getAddressSpace(), mapping)); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/TraceObjectSection.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/TraceObjectSection.java deleted file mode 100644 index b9d77c9b30..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/module/TraceObjectSection.java +++ /dev/null @@ -1,53 +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.module; - -import ghidra.program.model.address.AddressRange; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.modules.TraceSection; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -/** - * An allocated section of a binary module - * - *

- * Note that the model should only present those sections which are allocated in memory. Otherwise - * strange things may happen, such as zero-length ranges (which AddressRange hates), or overlapping - * ranges (which Trace hates). - * - *

- * TODO: Present all sections, but include isAllocated? - */ -@TraceObjectInfo( - schemaName = "Section", - shortName = "section", - attributes = { - TraceObjectSection.KEY_MODULE, - TraceObjectSection.KEY_RANGE, - }, - fixedKeys = { - TraceObjectInterface.KEY_DISPLAY, - TraceObjectSection.KEY_RANGE - }) -public interface TraceObjectSection extends TraceSection, TraceObjectInterface { - String KEY_MODULE = "_module"; - String KEY_RANGE = "_range"; - - void setName(Lifespan lifespan, String name); - - void setRange(Lifespan lifespan, AddressRange range); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/AbstractDBTraceProgramViewListing.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/AbstractDBTraceProgramViewListing.java index 24ca72b1b7..62257d7a01 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/AbstractDBTraceProgramViewListing.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/AbstractDBTraceProgramViewListing.java @@ -38,7 +38,6 @@ import ghidra.trace.database.DBTrace; import ghidra.trace.database.listing.UndefinedDBTraceData; import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.database.program.DBTraceProgramViewMemory.RegionEntry; -import ghidra.trace.database.thread.DBTraceThread; import ghidra.trace.model.*; import ghidra.trace.model.listing.*; import ghidra.trace.model.memory.TraceMemoryRegion; @@ -46,6 +45,7 @@ import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramViewListing; import ghidra.trace.model.property.TracePropertyMapOperations; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.*; import ghidra.util.*; import ghidra.util.AddressIteratorAdapter; @@ -59,13 +59,13 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV protected class DBTraceProgramViewUndefinedData extends UndefinedDBTraceData { public DBTraceProgramViewUndefinedData(DBTrace trace, long snap, Address address, - DBTraceThread thread, int frameLevel) { + TraceThread thread, int frameLevel) { super(trace, snap, address, thread, frameLevel); } @Override public int getBytes(ByteBuffer buffer, int addressOffset) { - DBTraceMemorySpace mem = trace.getMemoryManager().get(this, false); + DBTraceMemorySpace mem = trace.getMemoryManager().get(getAddressSpace(), false); if (mem == null) { buffer.put((byte) 0); return 1; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramView.java index 303a4a2089..4b4fd6a09a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramView.java @@ -60,10 +60,9 @@ import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.symbol.*; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.*; +import ghidra.trace.util.TraceEvents; +import ghidra.trace.util.TypedEventDispatcher; import ghidra.util.*; -import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -175,7 +174,7 @@ public class DBTraceProgramView implements TraceProgramView { type, null, null)); } - private void bookmarkAdded(TraceAddressSpace space, TraceBookmark bm) { + private void bookmarkAdded(AddressSpace space, TraceBookmark bm) { DomainObjectEventQueues queues = isBookmarkVisible(space, bm); if (queues == null) { return; @@ -188,7 +187,7 @@ public class DBTraceProgramView implements TraceProgramView { bm.getAddress(), bm, null, null)); } - private void bookmarkChanged(TraceAddressSpace space, TraceBookmark bm) { + private void bookmarkChanged(AddressSpace space, TraceBookmark bm) { DomainObjectEventQueues queues = isBookmarkVisible(space, bm); if (queues == null) { return; @@ -201,8 +200,8 @@ public class DBTraceProgramView implements TraceProgramView { bm.getAddress(), bm, null, null)); } - private void bookmarkLifespanChanged(TraceAddressSpace space, TraceBookmark bm, - Lifespan oldSpan, Lifespan newSpan) { + private void bookmarkLifespanChanged(AddressSpace space, TraceBookmark bm, Lifespan oldSpan, + Lifespan newSpan) { DomainObjectEventQueues queues = getEventQueues(space); if (queues == null) { return; @@ -217,7 +216,7 @@ public class DBTraceProgramView implements TraceProgramView { } } - private void bookmarkDeleted(TraceAddressSpace space, TraceBookmark bm) { + private void bookmarkDeleted(AddressSpace space, TraceBookmark bm) { DomainObjectEventQueues queues = isBookmarkVisible(space, bm); if (queues == null) { return; @@ -253,7 +252,7 @@ public class DBTraceProgramView implements TraceProgramView { null, null, parent, deleted.getName())); } - private void codeAdded(TraceAddressSpace space, TraceAddressSnapRange range, + private void codeAdded(AddressSpace space, TraceAddressSnapRange range, TraceCodeUnit oldIsNull, TraceCodeUnit added) { // NOTE: Added code may be coalesced range. -added- is just first unit. // TODO: The range may contain many units, so this could be broken down @@ -270,8 +269,8 @@ public class DBTraceProgramView implements TraceProgramView { new ProgramChangeRecord(ProgramEvent.CODE_ADDED, min, max, null, null, null)); } - private void codeLifespanChanged(TraceAddressSpace space, TraceCodeUnit unit, - Lifespan oldSpan, Lifespan newSpan) { + private void codeLifespanChanged(AddressSpace space, TraceCodeUnit unit, Lifespan oldSpan, + Lifespan newSpan) { DomainObjectEventQueues queues = getEventQueues(space); if (queues == null) { return; @@ -286,7 +285,7 @@ public class DBTraceProgramView implements TraceProgramView { } } - private void codeRemoved(TraceAddressSpace space, TraceAddressSnapRange range, + private void codeRemoved(AddressSpace space, TraceAddressSnapRange range, TraceCodeUnit removed, TraceCodeUnit newIsNull) { // NOTE: Removed code may be coalesced range. -removed- is just first unit. DomainObjectEventQueues queues = isCodeVisible(space, removed); @@ -302,7 +301,7 @@ public class DBTraceProgramView implements TraceProgramView { new ProgramChangeRecord(ProgramEvent.CODE_REMOVED, min, max, null, removed, null)); } - private void codeFragmentChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void codeFragmentChanged(AddressSpace space, TraceAddressSnapRange range, ProgramFragment oldFragment, ProgramFragment newFragment) { DomainObjectEventQueues queues = isVisible(space, range); if (queues == null) { @@ -312,7 +311,7 @@ public class DBTraceProgramView implements TraceProgramView { null, range.getX1(), range.getX2())); } - private void codeDataTypeReplaced(TraceAddressSpace space, TraceAddressSnapRange range, + private void codeDataTypeReplaced(AddressSpace space, TraceAddressSnapRange range, Long oldDataTypeID, Long newDataTypeID) { // TODO??: "code" visibility check may not be necessary or advantageous DomainObjectEventQueues queues = isVisible(space, range); @@ -323,7 +322,7 @@ public class DBTraceProgramView implements TraceProgramView { range.getX2(), null, null, null)); } - private void codeDataTypeSettingsChanged(TraceAddressSpace space, + private void codeDataTypeSettingsChanged(AddressSpace space, TraceAddressSnapRange range) { DomainObjectEventQueues queues = isVisible(space, range); if (queues == null) { @@ -334,7 +333,7 @@ public class DBTraceProgramView implements TraceProgramView { range.getX1(), range.getX1(), null, null, null)); } - private void commentChanged(CommentType commentType, TraceAddressSpace space, + private void commentChanged(CommentType commentType, AddressSpace space, TraceAddressSnapRange range, String oldValue, String newValue) { DomainObjectEventQueues queues = isVisible(space, range); if (queues == null) { @@ -344,33 +343,33 @@ public class DBTraceProgramView implements TraceProgramView { new CommentChangeRecord(commentType, range.getX1(), oldValue, newValue)); } - private void commentEolChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void commentEolChanged(AddressSpace space, TraceAddressSnapRange range, String oldValue, String newValue) { commentChanged(CommentType.EOL, space, range, oldValue, newValue); } - private void commentPlateChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void commentPlateChanged(AddressSpace space, TraceAddressSnapRange range, String oldValue, String newValue) { commentChanged(CommentType.PLATE, space, range, oldValue, newValue); } - private void commentPostChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void commentPostChanged(AddressSpace space, TraceAddressSnapRange range, String oldValue, String newValue) { commentChanged(CommentType.POST, space, range, oldValue, newValue); } - private void commentPreChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void commentPreChanged(AddressSpace space, TraceAddressSnapRange range, String oldValue, String newValue) { commentChanged(CommentType.PRE, space, range, oldValue, newValue); } - private void commentRepeatableChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void commentRepeatableChanged(AddressSpace space, TraceAddressSnapRange range, String oldValue, String newValue) { // TODO: The "repeatable" semantics are not implemented, yet. commentChanged(CommentType.REPEATABLE, space, range, oldValue, newValue); } - private void compositeDataAdded(TraceAddressSpace space, TraceAddressSnapRange range, + private void compositeDataAdded(AddressSpace space, TraceAddressSnapRange range, TraceData oldIsNull, TraceData added) { DomainObjectEventQueues queues = isCodeVisible(space, added); if (queues == null) { @@ -380,8 +379,8 @@ public class DBTraceProgramView implements TraceProgramView { added.getMinAddress(), added.getMaxAddress(), null, null, added)); } - private void compositeLifespanChanged(TraceAddressSpace space, TraceData data, - Lifespan oldSpan, Lifespan newSpan) { + private void compositeLifespanChanged(AddressSpace space, TraceData data, Lifespan oldSpan, + Lifespan newSpan) { DomainObjectEventQueues queues = getEventQueues(space); if (queues == null) { return; @@ -398,7 +397,7 @@ public class DBTraceProgramView implements TraceProgramView { } } - private void compositeDataRemoved(TraceAddressSpace space, TraceAddressSnapRange range, + private void compositeDataRemoved(AddressSpace space, TraceAddressSnapRange range, TraceData removed, TraceData newIsNull) { DomainObjectEventQueues queues = isCodeVisible(space, removed); if (queues == null) { @@ -443,7 +442,7 @@ public class DBTraceProgramView implements TraceProgramView { null, oldPath, newIsNull)); } - private void instructionFlowOverrideChanged(TraceAddressSpace space, + private void instructionFlowOverrideChanged(AddressSpace space, TraceInstruction instruction, FlowOverride oldOverride, FlowOverride newOverride) { DomainObjectEventQueues queues = isCodeVisible(space, instruction); if (queues == null) { @@ -453,7 +452,7 @@ public class DBTraceProgramView implements TraceProgramView { instruction.getMinAddress(), instruction.getMinAddress(), null, null, null)); } - private void instructionFallThroughChanged(TraceAddressSpace space, + private void instructionFallThroughChanged(AddressSpace space, TraceInstruction instruction, boolean oldFallThrough, boolean newFallThrough) { DomainObjectEventQueues queues = isCodeVisible(space, instruction); if (queues == null) { @@ -463,7 +462,7 @@ public class DBTraceProgramView implements TraceProgramView { instruction.getMinAddress(), instruction.getMinAddress(), null, null, null)); } - private void instructionLengthOverrideChanged(TraceAddressSpace space, + private void instructionLengthOverrideChanged(AddressSpace space, TraceInstruction instruction, int oldLengthOverride, int newLengthOverride) { DomainObjectEventQueues queues = isCodeVisible(space, instruction); if (queues == null) { @@ -473,7 +472,7 @@ public class DBTraceProgramView implements TraceProgramView { instruction.getMinAddress(), instruction.getMinAddress(), null, null, null)); } - private void memoryBytesChanged(TraceAddressSpace space, TraceAddressSnapRange range, + private void memoryBytesChanged(AddressSpace space, TraceAddressSnapRange range, byte[] oldIsNull, byte[] bytes) { DomainObjectEventQueues queues = isBytesVisible(space, range); if (queues == null) { @@ -488,22 +487,22 @@ public class DBTraceProgramView implements TraceProgramView { range.getX1(), range.getX2(), null, null, null)); } - private void memoryRegionAdded(TraceAddressSpace space, TraceMemoryRegion region) { + private void memoryRegionAdded(AddressSpace space, TraceMemoryRegion region) { // This is handled via another path } - private void memoryRegionChanged(TraceAddressSpace space, TraceMemoryRegion region) { + private void memoryRegionChanged(AddressSpace space, TraceMemoryRegion region) { // Could be a name change, which must get communicated to program. // RESTORED may be duplicative, but should get de-duped by event manager. eventQueues.fireEvent(new DomainObjectChangeRecord(DomainObjectEvent.RESTORED)); } - private void memoryRegionLifespanChanged(TraceAddressSpace space, TraceMemoryRegion region, + private void memoryRegionLifespanChanged(AddressSpace space, TraceMemoryRegion region, Lifespan oldSpan, Lifespan newSpan) { // This is handled via another path } - private void memoryRegionDeleted(TraceAddressSpace space, TraceMemoryRegion region) { + private void memoryRegionDeleted(AddressSpace space, TraceMemoryRegion region) { // HACK listing.fragmentsByRegion.remove(region); // END HACK @@ -521,7 +520,7 @@ public class DBTraceProgramView implements TraceProgramView { null, id, null, null)); } - private void symbolAdded(TraceAddressSpace space, TraceSymbol symbol) { + private void symbolAdded(AddressSpace space, TraceSymbol symbol) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { return; @@ -534,7 +533,7 @@ public class DBTraceProgramView implements TraceProgramView { symbol.getAddress(), null, null, symbol)); } - private void symbolSourceChanged(TraceAddressSpace space, TraceSymbol symbol) { + private void symbolSourceChanged(AddressSpace space, TraceSymbol symbol) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { return; @@ -543,7 +542,7 @@ public class DBTraceProgramView implements TraceProgramView { symbol.getAddress(), symbol.getAddress(), symbol, null, null)); } - private void symbolSetAsPrimary(TraceAddressSpace space, TraceSymbol symbol, + private void symbolSetAsPrimary(AddressSpace space, TraceSymbol symbol, TraceSymbol oldPrimary, TraceSymbol newPrimary) { // NOTE symbol == newPrimary DomainObjectEventQueues newQueues = isSymbolVisible(space, symbol); @@ -559,7 +558,7 @@ public class DBTraceProgramView implements TraceProgramView { symbol.getAddress(), symbol.getAddress(), null, oldPrimary, newPrimary)); } - private void symbolRenamed(TraceAddressSpace space, TraceSymbol symbol, String oldName, + private void symbolRenamed(AddressSpace space, TraceSymbol symbol, String oldName, String newName) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { @@ -569,7 +568,7 @@ public class DBTraceProgramView implements TraceProgramView { symbol.getAddress(), symbol.getAddress(), symbol, oldName, newName)); } - private void symbolParentChanged(TraceAddressSpace space, TraceSymbol symbol, + private void symbolParentChanged(AddressSpace space, TraceSymbol symbol, TraceNamespaceSymbol oldParent, TraceNamespaceSymbol newParent) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { @@ -579,7 +578,7 @@ public class DBTraceProgramView implements TraceProgramView { symbol.getAddress(), symbol.getAddress(), symbol, oldParent, newParent)); } - private void symbolAssociationAdded(TraceAddressSpace space, TraceSymbol symbol, + private void symbolAssociationAdded(AddressSpace space, TraceSymbol symbol, TraceReference oldRefIsNull, TraceReference newRef) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { @@ -590,7 +589,7 @@ public class DBTraceProgramView implements TraceProgramView { newRef.getFromAddress(), newRef.getFromAddress(), newRef, null, symbol)); } - private void symbolAssociationRemoved(TraceAddressSpace space, TraceSymbol symbol, + private void symbolAssociationRemoved(AddressSpace space, TraceSymbol symbol, TraceReference oldRef, TraceReference newRefIsNull) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { @@ -601,7 +600,7 @@ public class DBTraceProgramView implements TraceProgramView { oldRef.getFromAddress(), oldRef.getFromAddress(), oldRef, symbol, null)); } - private void symbolAddressChanged(TraceAddressSpace space, TraceSymbol symbol, + private void symbolAddressChanged(AddressSpace space, TraceSymbol symbol, Address oldAddress, Address newAddress) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { @@ -611,7 +610,7 @@ public class DBTraceProgramView implements TraceProgramView { oldAddress, oldAddress, symbol, oldAddress, newAddress)); } - private void symbolLifespanChanged(TraceAddressSpace space, TraceSymbolWithLifespan symbol, + private void symbolLifespanChanged(AddressSpace space, TraceSymbolWithLifespan symbol, Lifespan oldSpan, Lifespan newSpan) { DomainObjectEventQueues queues = getEventQueues(space); if (queues == null) { @@ -627,7 +626,7 @@ public class DBTraceProgramView implements TraceProgramView { } } - private void symbolDeleted(TraceAddressSpace space, TraceSymbol symbol) { + private void symbolDeleted(AddressSpace space, TraceSymbol symbol) { DomainObjectEventQueues queues = isSymbolVisible(space, symbol); if (queues == null) { return; @@ -695,8 +694,6 @@ public class DBTraceProgramView implements TraceProgramView { // TODO: How does this work? protected final DBTraceProgramViewChangeSet changes; - protected final Map regViewsByThread; - protected long snap; protected InternalTracePlatform platform; protected final DBTraceTimeViewport viewport; @@ -722,8 +719,6 @@ public class DBTraceProgramView implements TraceProgramView { this.eventQueues = new DomainObjectEventQueues(this, TIME_INTERVAL, trace.getLock()); - this.regViewsByThread = new WeakValueHashMap<>(); - this.bookmarkManager = new DBTraceProgramViewBookmarkManager(this); this.equateTable = new DBTraceProgramViewEquateTable(this); this.functionManager = new DBTraceProgramViewFunctionManager(this); @@ -762,11 +757,7 @@ public class DBTraceProgramView implements TraceProgramView { } protected void fireEventAllViews(DomainObjectChangeRecord ev) { - // TODO: Do I need to make copies? eventQueues.fireEvent(ev); - for (DBTraceProgramViewRegisters regView : regViewsByThread.values()) { - regView.eventQueues.fireEvent(ev); - } } /** @@ -806,31 +797,6 @@ public class DBTraceProgramView implements TraceProgramView { return listing; } - @Override - public DBTraceProgramViewRegisters getViewRegisters(TraceThread thread, - boolean createIfAbsent) { - synchronized (regViewsByThread) { - DBTraceProgramViewRegisters regView = regViewsByThread.get(thread); - if (regView != null) { - return regView; - } - assert trace.getThreadManager().getAllThreads().contains(thread); - DBTraceCodeSpace codeSpace = - trace.getCodeManager().getCodeRegisterSpace(thread, createIfAbsent); - if (codeSpace == null) { - return null; - } - DBTraceMemorySpace memorySpace = - trace.getMemoryManager().getMemoryRegisterSpace(thread, createIfAbsent); - if (memorySpace == null) { - return null; - } - regView = new DBTraceProgramViewRegisters(this, codeSpace, memorySpace); - regViewsByThread.put(thread, regView); - return regView; - } - } - @Override public AddressMap getAddressMap() { return null; @@ -1486,21 +1452,15 @@ public class DBTraceProgramView implements TraceProgramView { memory.updateBytesChanged(range); } - protected DomainObjectEventQueues getEventQueues(TraceAddressSpace space) { - // TODO: Should there be views on other frames? - // IIRC, this was an abandoned experiment for "register listings" - TraceThread thread = space == null ? null : space.getThread(); - if (thread == null) { - return eventQueues; - } - DBTraceProgramViewRegisters viewRegisters; - synchronized (regViewsByThread) { - viewRegisters = regViewsByThread.get(thread); - } - return viewRegisters == null ? null : viewRegisters.eventQueues; + protected DomainObjectEventQueues getEventQueues(AddressSpace space) { + /** + * NOTE: Thought about views on other frames. IIRC, this was an abandoned experiment for + * "register listings" + */ + return eventQueues; } - protected DomainObjectEventQueues isVisible(TraceAddressSpace space, + protected DomainObjectEventQueues isVisible(AddressSpace space, TraceAddressSnapRange range) { return viewport.containsAnyUpper(range.getLifespan()) ? getEventQueues(space) : null; } @@ -1509,7 +1469,7 @@ public class DBTraceProgramView implements TraceProgramView { return viewport.containsAnyUpper(lifespan); } - protected DomainObjectEventQueues isBookmarkVisible(TraceAddressSpace space, TraceBookmark bm) { + protected DomainObjectEventQueues isBookmarkVisible(AddressSpace space, TraceBookmark bm) { return isBookmarkVisible(bm, bm.getLifespan()) ? getEventQueues(space) : null; } @@ -1525,7 +1485,7 @@ public class DBTraceProgramView implements TraceProgramView { return false; } - protected Occlusion getCodeOcclusion(TraceAddressSpace space) { + protected Occlusion getCodeOcclusion(AddressSpace space) { return new RangeQueryOcclusion<>() { final DBTraceCodeSpace codeSpace = trace.getCodeManager().get(space, false); final DBTraceMemorySpace memSpace = trace.getMemoryManager().get(space, false); @@ -1600,15 +1560,15 @@ public class DBTraceProgramView implements TraceProgramView { throw new AssertionError(e); } return viewport.isCompletelyVisible(cu.getRange(), lifespan, cu, - getCodeOcclusion(cu.getTraceSpace())); + getCodeOcclusion(cu.getAddress().getAddressSpace())); } - protected boolean isCodeVisible(TraceAddressSpace space, TraceAddressSnapRange range) { + protected boolean isCodeVisible(AddressSpace space, TraceAddressSnapRange range) { return viewport.isCompletelyVisible(range.getRange(), range.getLifespan(), null, getCodeOcclusion(space)); } - protected DomainObjectEventQueues isCodeVisible(TraceAddressSpace space, TraceCodeUnit cu) { + protected DomainObjectEventQueues isCodeVisible(AddressSpace space, TraceCodeUnit cu) { if (!isCodeVisible(cu, cu.getLifespan())) { return null; } @@ -1623,7 +1583,7 @@ public class DBTraceProgramView implements TraceProgramView { return true; } - protected DomainObjectEventQueues isSymbolVisible(TraceAddressSpace space, TraceSymbol symbol) { + protected DomainObjectEventQueues isSymbolVisible(AddressSpace space, TraceSymbol symbol) { // NB. Most symbols do not occlude each other DomainObjectEventQueues queues = getEventQueues(space); if (queues == null) { @@ -1636,7 +1596,7 @@ public class DBTraceProgramView implements TraceProgramView { return isSymbolWithLifespanVisible(symWl, symWl.getLifespan()) ? queues : null; } - protected DomainObjectEventQueues isBytesVisible(TraceAddressSpace space, + protected DomainObjectEventQueues isBytesVisible(AddressSpace space, TraceAddressSnapRange range) { // NB. This need not be precise.... DomainObjectEventQueues queues = getEventQueues(space); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewBookmarkManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewBookmarkManager.java index 4adf6d5c6a..f68e5a0855 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewBookmarkManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewBookmarkManager.java @@ -4,9 +4,9 @@ * 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. @@ -310,7 +310,7 @@ public class DBTraceProgramViewBookmarkManager implements TraceProgramViewBookma @Override public Iterator getBookmarksIterator() { // TODO: This seems terribly inefficient. We'll have to see how/when it's used. - return NestedIterator.start(bookmarkManager.getActiveMemorySpaces().iterator(), + return NestedIterator.start(bookmarkManager.getActiveSpaces().iterator(), space -> filteredIterator(space.getAllBookmarks().iterator(), bm -> program.viewport.containsAnyUpper(bm.getLifespan()))); } @@ -368,7 +368,7 @@ public class DBTraceProgramViewBookmarkManager implements TraceProgramViewBookma // Not doing so here causes a slight display error in the bookmark table. // It will say "Row i of n", but n will be greater than the actual number of rows. int sum = 0; - for (DBTraceBookmarkSpace space : bookmarkManager.getActiveMemorySpaces()) { + for (DBTraceBookmarkSpace space : bookmarkManager.getActiveSpaces()) { sum += space.getAllBookmarks().size(); } return sum; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterListing.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterListing.java deleted file mode 100644 index a66bc070e0..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterListing.java +++ /dev/null @@ -1,80 +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.program; - -import ghidra.program.model.address.*; -import ghidra.trace.database.listing.DBTraceCodeSpace; -import ghidra.trace.database.listing.UndefinedDBTraceData; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.program.TraceProgramViewRegisterListing; -import ghidra.trace.model.thread.TraceThread; -import ghidra.util.exception.CancelledException; -import ghidra.util.task.TaskMonitor; - -public class DBTraceProgramViewRegisterListing extends AbstractDBTraceProgramViewListing - implements TraceProgramViewRegisterListing { - private final TraceThread thread; - private Address minAddr; - private Address maxAddr; - - public DBTraceProgramViewRegisterListing(DBTraceProgramView program, - DBTraceCodeSpace regSpace) { - super(program, regSpace); - this.thread = regSpace.getThread(); - - AddressSpace space = program.getAddressFactory().getRegisterSpace(); - this.minAddr = space.getMinAddress(); - this.maxAddr = space.getMaxAddress(); - } - - @Override - public TraceThread getThread() { - return thread; - } - - @Override - public UndefinedDBTraceData doCreateUndefinedUnit(Address address) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isUndefined(Address start, Address end) { - return codeOperations.undefinedData() - .coversRange(Lifespan.at(program.snap), new AddressRangeImpl(start, end)); - } - - @Override - public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext, - TaskMonitor monitor) throws CancelledException { - codeOperations.definedUnits() - .clear(Lifespan.at(program.snap), new AddressRangeImpl(startAddr, endAddr), - clearContext, monitor); - } - - @Override - // TODO: Delete this when the interface removes it - public void clearAll(boolean clearContext, TaskMonitor monitor) { - try { - codeOperations.definedUnits() - .clear(Lifespan.at(program.snap), new AddressRangeImpl(minAddr, maxAddr), - clearContext, monitor); - } - catch (CancelledException e) { - // This whole method is supposed to go away, anyway - throw new AssertionError(e); - } - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemory.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemory.java deleted file mode 100644 index ff93235287..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemory.java +++ /dev/null @@ -1,71 +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.program; - -import ghidra.program.model.address.*; -import ghidra.program.model.mem.MemoryBlock; -import ghidra.trace.database.memory.DBTraceMemorySpace; - -public class DBTraceProgramViewRegisterMemory extends AbstractDBTraceProgramViewMemory { - protected final DBTraceMemorySpace space; - protected final DBTraceProgramViewRegisterMemoryBlock block; - - public DBTraceProgramViewRegisterMemory(DBTraceProgramView program, - DBTraceMemorySpace space) { - super(program); - this.space = space; - this.block = new DBTraceProgramViewRegisterMemoryBlock(program, space); - } - - @Override - public void setForceFullView(boolean forceFullView) { - throw new UnsupportedOperationException(); - } - - @Override - protected AddressSetView computeAddressSet() { - // AddressSet is always full space - return new AddressSet(new AddressRangeImpl(space.getAddressSpace().getMinAddress(), - space.getAddressSpace().getMaxAddress())); - } - - @Override - public MemoryBlock getBlock(Address addr) { - if (addr.getAddressSpace().isRegisterSpace()) { - return block; - } - return null; - } - - @Override - public MemoryBlock getBlock(String blockName) { - if (DBTraceProgramViewRegisterMemoryBlock.REGS_BLOCK_NAME.equals(blockName)) { - return block; - } - return null; - } - - @Override - public MemoryBlock[] getBlocks() { - // NOTE: Don't cache, to avoid external mutation. - return new MemoryBlock[] { block }; - } - - @Override - public AddressSetView getExecuteSet() { - return new AddressSet(); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java deleted file mode 100644 index 58fd5c318e..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java +++ /dev/null @@ -1,320 +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.program; - -import java.io.InputStream; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.util.*; - -import javax.help.UnsupportedOperationException; - -import ghidra.framework.store.LockException; -import ghidra.program.database.mem.ByteMappingScheme; -import ghidra.program.database.mem.FileBytes; -import ghidra.program.model.address.*; -import ghidra.program.model.mem.*; -import ghidra.trace.database.memory.DBTraceMemorySpace; -import ghidra.trace.model.memory.TraceMemorySpaceInputStream; - -public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock { - public static final String REGS_BLOCK_NAME = "regs"; - - private class DBTraceProgramViewRegisterMemoryBlockSourceInfo implements MemoryBlockSourceInfo { - @Override - public long getLength() { - return range.getLength(); - } - - @Override - public Address getMinAddress() { - return range.getMinAddress(); - } - - @Override - public Address getMaxAddress() { - return range.getMaxAddress(); - } - - @Override - public String getDescription() { - return "Trace registers: " + space.getThread().getName(program.getSnap()); - } - - @Override - public Optional getFileBytes() { - return Optional.empty(); - } - - @Override - public long getFileBytesOffset() { - return -1; - } - - @Override - public long getFileBytesOffset(Address address) { - return -1; - } - - @Override - public Optional getMappedRange() { - return Optional.empty(); - } - - @Override - public Optional getByteMappingScheme() { - return Optional.empty(); - } - - @Override - public MemoryBlock getMemoryBlock() { - return DBTraceProgramViewRegisterMemoryBlock.this; - } - - @Override - public boolean contains(Address address) { - return range.contains(address); - } - - @Override - public String toString() { - return getDescription(); - } - } - - private final DBTraceProgramView program; - private final DBTraceMemorySpace space; - private final AddressRange range; - - private final List info = - Collections.singletonList(new DBTraceProgramViewRegisterMemoryBlockSourceInfo()); - - public DBTraceProgramViewRegisterMemoryBlock(DBTraceProgramView program, - DBTraceMemorySpace space) { - this.program = program; - this.space = space; - this.range = new AddressRangeImpl(space.getAddressSpace().getMinAddress(), - space.getAddressSpace().getMaxAddress()); - } - - @Override - public int compareTo(MemoryBlock that) { - return this.getStart().compareTo(that.getStart()); - } - - @Override - public int getFlags() { - return MemoryBlock.READ | MemoryBlock.WRITE; - } - - @Override - public InputStream getData() { - return new TraceMemorySpaceInputStream(program, space, range); - } - - @Override - public boolean contains(Address addr) { - return range.contains(addr); - } - - @Override - public AddressRange getAddressRange() { - return range; - } - - @Override - public Address getStart() { - return range.getMinAddress(); - } - - @Override - public Address getEnd() { - return range.getMaxAddress(); - } - - @Override - public long getSize() { - return range.getLength(); - } - - @Override - public BigInteger getSizeAsBigInteger() { - return range.getBigLength(); - } - - @Override - public String getName() { - return REGS_BLOCK_NAME; - } - - @Override - public void setName(String name) throws IllegalArgumentException, LockException { - throw new UnsupportedOperationException(); - } - - @Override - public String getComment() { - return null; - } - - @Override - public void setComment(String comment) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isRead() { - return true; - } - - @Override - public void setRead(boolean r) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isWrite() { - return true; - } - - @Override - public void setWrite(boolean w) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isExecute() { - return false; - } - - @Override - public void setExecute(boolean e) { - throw new UnsupportedOperationException(); - } - - @Override - public void setPermissions(boolean read, boolean write, boolean execute) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isVolatile() { - return false; - } - - @Override - public void setVolatile(boolean v) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isArtificial() { - return false; - } - - @Override - public void setArtificial(boolean a) { - throw new UnsupportedOperationException(); - } - - @Override - public String getSourceName() { - return "Trace"; // TODO: What does this method actually do? - } - - @Override - public void setSourceName(String sourceName) { - throw new UnsupportedOperationException(); - } - - @Override - public byte getByte(Address addr) throws MemoryAccessException { - if (!range.contains(addr)) { - throw new MemoryAccessException(); - } - ByteBuffer buf = ByteBuffer.allocate(1); - if (space.getViewBytes(program.snap, addr, buf) != 1) { - throw new MemoryAccessException(); - } - return buf.get(0); - } - - @Override - public int getBytes(Address addr, byte[] b) throws MemoryAccessException { - return getBytes(addr, b, 0, b.length); - } - - @Override - public int getBytes(Address addr, byte[] b, int off, int len) throws MemoryAccessException { - if (!range.contains(addr)) { - throw new MemoryAccessException(); - } - len = (int) Math.min(len, range.getMaxAddress().subtract(addr) + 1); - return space.getViewBytes(program.snap, addr, ByteBuffer.wrap(b, off, len)); - } - - @Override - public void putByte(Address addr, byte b) throws MemoryAccessException { - if (putBytes(addr, new byte[] { b }) != 1) { - throw new MemoryAccessException(); - } - } - - @Override - public int putBytes(Address addr, byte[] b) throws MemoryAccessException { - return putBytes(addr, b, 0, b.length); - } - - @Override - public int putBytes(Address addr, byte[] b, int off, int len) throws MemoryAccessException { - if (!range.contains(addr)) { - throw new MemoryAccessException(); - } - len = (int) Math.min(len, range.getMaxAddress().subtract(addr) + 1); - return space.putBytes(program.snap, addr, ByteBuffer.wrap(b, off, len)); - } - - @Override - public MemoryBlockType getType() { - return MemoryBlockType.DEFAULT; - } - - @Override - public boolean isInitialized() { - return true; - } - - @Override - public boolean isMapped() { - return false; - } - - @Override - public boolean isOverlay() { - return false; - } - - @Override - public boolean isLoaded() { - return true; - } - - @Override - public List getSourceInfos() { - return info; - } - -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisters.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisters.java deleted file mode 100644 index 36cb3c0f6b..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisters.java +++ /dev/null @@ -1,686 +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.program; - -import java.io.File; -import java.io.IOException; -import java.util.*; - -import db.Transaction; -import ghidra.framework.data.DomainObjectEventQueues; -import ghidra.framework.data.DomainObjectFileListener; -import ghidra.framework.model.*; -import ghidra.framework.options.Options; -import ghidra.framework.store.LockException; -import ghidra.program.database.IntRangeMap; -import ghidra.program.database.ProgramOverlayAddressSpace; -import ghidra.program.database.map.AddressMap; -import ghidra.program.model.address.*; -import ghidra.program.model.data.CategoryPath; -import ghidra.program.model.lang.*; -import ghidra.program.model.listing.*; -import ghidra.program.model.pcode.Varnode; -import ghidra.program.model.reloc.RelocationTable; -import ghidra.program.model.symbol.*; -import ghidra.program.model.util.AddressSetPropertyMap; -import ghidra.program.model.util.PropertyMapManager; -import ghidra.trace.database.listing.DBTraceCodeSpace; -import ghidra.trace.database.memory.DBTraceMemorySpace; -import ghidra.trace.model.Trace; -import ghidra.trace.model.TraceTimeViewport; -import ghidra.trace.model.data.TraceBasedDataTypeManager; -import ghidra.trace.model.program.TraceProgramView; -import ghidra.trace.model.program.TraceProgramViewMemory; -import ghidra.trace.model.thread.TraceThread; -import ghidra.util.InvalidNameException; -import ghidra.util.exception.*; -import ghidra.util.task.TaskMonitor; - -public class DBTraceProgramViewRegisters implements TraceProgramView { - protected final DomainObjectEventQueues eventQueues; - - private final DBTraceProgramView view; - private final TraceThread thread; - - private final DBTraceProgramViewRegisterListing listing; - private final DBTraceProgramViewRegisterMemory memory; - private final DBTraceProgramViewRegistersReferenceManager referenceManager; - - public DBTraceProgramViewRegisters(DBTraceProgramView view, DBTraceCodeSpace codeSpace, - DBTraceMemorySpace memorySpace) { - this.view = view; - this.thread = codeSpace.getThread(); // TODO: Bleh, should be parameter - - this.eventQueues = new DomainObjectEventQueues(this, DBTraceProgramView.TIME_INTERVAL, - view.trace.getLock()); - - // TODO: Make these create code/memory spaces lazily, to allow null at construction - // NOTE: Use reference manager as example - this.listing = new DBTraceProgramViewRegisterListing(view, codeSpace); - this.memory = new DBTraceProgramViewRegisterMemory(view, memorySpace); - this.referenceManager = new DBTraceProgramViewRegistersReferenceManager(view, thread); - } - - @Override - public Listing getListing() { - return listing; - } - - @Override - public AddressMap getAddressMap() { - return null; - } - - @Override - public TraceBasedDataTypeManager getDataTypeManager() { - return view.getDataTypeManager(); - } - - @Override - public FunctionManager getFunctionManager() { - return view.getFunctionManager(); - } - - @Override - public ProgramUserData getProgramUserData() { - // TODO Auto-generated method stub - return null; - } - - @Override - public SymbolTable getSymbolTable() { - return view.getSymbolTable(); - } - - @Override - public ExternalManager getExternalManager() { - return view.getExternalManager(); - } - - @Override - public EquateTable getEquateTable() { - return view.getEquateTable(); - } - - @Override - public TraceProgramViewMemory getMemory() { - return memory; - } - - @Override - public ReferenceManager getReferenceManager() { - return referenceManager; - } - - @Override - public BookmarkManager getBookmarkManager() { - return view.getBookmarkManager(); - } - - @Override - public int getDefaultPointerSize() { - return view.getDefaultPointerSize(); - } - - @Override - public String getCompiler() { - return view.getCompiler(); - } - - @Override - public void setCompiler(String compiler) { - view.setCompiler(compiler); - } - - @Override - public CategoryPath getPreferredRootNamespaceCategoryPath() { - return view.getPreferredRootNamespaceCategoryPath(); - } - - @Override - public void setPreferredRootNamespaceCategoryPath(String categoryPath) { - view.setPreferredRootNamespaceCategoryPath(categoryPath); - } - - @Override - public String getExecutablePath() { - return view.getExecutablePath(); - } - - @Override - public void setExecutablePath(String path) { - view.setExecutablePath(path); - } - - @Override - public String getExecutableFormat() { - return view.getExecutableFormat(); - } - - @Override - public void setExecutableFormat(String format) { - view.setExecutableFormat(format); - } - - @Override - public String getExecutableMD5() { - return view.getExecutableMD5(); - } - - @Override - public void setExecutableMD5(String md5) { - view.setExecutableMD5(md5); - } - - @Override - public void setExecutableSHA256(String sha256) { - view.setExecutableSHA256(sha256); - } - - @Override - public String getExecutableSHA256() { - return view.getExecutableSHA256(); - } - - @Override - public Date getCreationDate() { - return view.getCreationDate(); - } - - @Override - public RelocationTable getRelocationTable() { - return view.getRelocationTable(); - } - - @Override - public Language getLanguage() { - return view.getLanguage(); - } - - @Override - public CompilerSpec getCompilerSpec() { - return view.getCompilerSpec(); - } - - @Override - public LanguageID getLanguageID() { - return view.getLanguageID(); - } - - @Override - public PropertyMapManager getUsrPropertyManager() { - return view.getUsrPropertyManager(); - } - - @Override - public ProgramContext getProgramContext() { - return view.getProgramContext(); - } - - @Override - public Address getMinAddress() { - return view.getLanguage().getAddressFactory().getRegisterSpace().getMinAddress(); - } - - @Override - public Address getMaxAddress() { - return view.getLanguage().getAddressFactory().getRegisterSpace().getMaxAddress(); - } - - @Override - public ProgramChangeSet getChanges() { - return view.getChanges(); - } - - @Override - public AddressFactory getAddressFactory() { - return view.getAddressFactory(); - } - - @Override - public Address[] parseAddress(String addrStr) { - return view.parseAddress(addrStr); - } - - @Override - public Address[] parseAddress(String addrStr, boolean caseSensitive) { - return view.parseAddress(addrStr, caseSensitive); - } - - @Override - public Register getRegister(String name) { - return view.getRegister(name); - } - - @Override - public Register getRegister(Address addr) { - return view.getRegister(addr); - } - - @Override - public Register[] getRegisters(Address addr) { - return view.getRegisters(addr); - } - - @Override - public Register getRegister(Address addr, int size) { - return view.getRegister(addr, size); - } - - @Override - public Register getRegister(Varnode varnode) { - return view.getRegister(varnode); - } - - @Override - public Address getImageBase() { - return view.getImageBase(); - } - - @Override - public ProgramOverlayAddressSpace createOverlaySpace(String overlaySpaceName, - AddressSpace baseSpace) throws IllegalStateException, DuplicateNameException, - InvalidNameException, LockException { - return view.createOverlaySpace(overlaySpaceName, baseSpace); - } - - @Override - public void renameOverlaySpace(String overlaySpaceName, String newName) - throws NotFoundException, InvalidNameException, DuplicateNameException, LockException { - view.renameOverlaySpace(overlaySpaceName, newName); - } - - @Override - public boolean removeOverlaySpace(String overlaySpaceName) - throws LockException, NotFoundException { - return view.removeOverlaySpace(overlaySpaceName); - } - - @Override - public void setImageBase(Address base, boolean commit) - throws AddressOverflowException, LockException, IllegalStateException { - view.setImageBase(base, commit); - } - - @Override - public void restoreImageBase() { - view.restoreImageBase(); - } - - @Override - public void setLanguage(Language language, CompilerSpecID compilerSpecID, - boolean forceRedisassembly, TaskMonitor monitor) - throws IllegalStateException, IncompatibleLanguageException, LockException { - view.setLanguage(language, compilerSpecID, forceRedisassembly, monitor); - } - - @Override - public Namespace getGlobalNamespace() { - return view.getGlobalNamespace(); - } - - @Override - public AddressSetPropertyMap createAddressSetPropertyMap(String name) - throws DuplicateNameException { - return view.getAddressSetPropertyMap(name); - } - - @Override - public IntRangeMap createIntRangeMap(String name) throws DuplicateNameException { - return view.createIntRangeMap(name); - } - - @Override - public AddressSetPropertyMap getAddressSetPropertyMap(String name) { - return view.getAddressSetPropertyMap(name); - } - - @Override - public IntRangeMap getIntRangeMap(String name) { - return view.getIntRangeMap(name); - } - - @Override - public void deleteAddressSetPropertyMap(String name) { - view.deleteAddressSetPropertyMap(name); - } - - @Override - public void deleteIntRangeMap(String name) { - view.deleteIntRangeMap(name); - } - - @Override - public long getUniqueProgramID() { - return view.getUniqueProgramID(); - } - - @Override - public Transaction openTransaction(String description) throws IllegalStateException { - return view.openTransaction(description); - } - - @Override - public int startTransaction(String description) { - return view.startTransaction(description); - } - - @Override - public int startTransaction(String description, AbortedTransactionListener listener) { - return view.startTransaction(description, listener); - } - - @Override - public boolean endTransaction(int transactionID, boolean commit) { - return view.endTransaction(transactionID, commit); - } - - @Override - public TransactionInfo getCurrentTransactionInfo() { - return view.getCurrentTransactionInfo(); - } - - @Override - public boolean hasTerminatedTransaction() { - return view.hasTerminatedTransaction(); - } - - @Override - public DomainObject[] getSynchronizedDomainObjects() { - return view.getSynchronizedDomainObjects(); - } - - @Override - public void addSynchronizedDomainObject(DomainObject domainObj) throws LockException { - view.addSynchronizedDomainObject(domainObj); - } - - @Override - public void releaseSynchronizedDomainObject() throws LockException { - view.releaseSynchronizedDomainObject(); - } - - @Override - public boolean isChanged() { - return view.isChanged(); - } - - @Override - public void setTemporary(boolean state) { - view.setTemporary(state); - } - - @Override - public boolean isTemporary() { - return view.isTemporary(); - } - - @Override - public boolean isChangeable() { - return view.isChangeable(); - } - - @Override - public boolean canSave() { - return view.canSave(); - } - - @Override - public void save(String comment, TaskMonitor monitor) throws IOException, CancelledException { - view.save(comment, monitor); - } - - @Override - public void saveToPackedFile(File outputFile, TaskMonitor monitor) - throws IOException, CancelledException { - view.saveToPackedFile(outputFile, monitor); - } - - @Override - public void release(Object consumer) { - view.release(consumer); - } - - @Override - public void addListener(DomainObjectListener dol) { - eventQueues.addListener(dol); - } - - @Override - public void removeListener(DomainObjectListener dol) { - eventQueues.removeListener(dol); - } - - @Override - public void addCloseListener(DomainObjectClosedListener listener) { - view.addCloseListener(listener); - } - - @Override - public void removeCloseListener(DomainObjectClosedListener listener) { - view.removeCloseListener(listener); - } - - @Override - public void addDomainFileListener(DomainObjectFileListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeDomainFileListener(DomainObjectFileListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public EventQueueID createPrivateEventQueue(DomainObjectListener listener, int maxDelay) { - return eventQueues.createPrivateEventQueue(listener, maxDelay); - } - - @Override - public boolean removePrivateEventQueue(EventQueueID id) { - return removePrivateEventQueue(id); - } - - @Override - public String getDescription() { - return view.getDescription(); - } - - @Override - public String getName() { - return view.getName(); // TODO: Append thread name? - } - - @Override - public void setName(String name) { - view.setName(name); // TODO: Allow this? - } - - @Override - public DomainFile getDomainFile() { - return view.getDomainFile(); - } - - @Override - public boolean addConsumer(Object consumer) { - return view.addConsumer(consumer); - } - - @Override - public ArrayList getConsumerList() { - return view.getConsumerList(); - } - - @Override - public boolean isUsedBy(Object consumer) { - return view.isUsedBy(consumer); - } - - @Override - public void setEventsEnabled(boolean enabled) { - view.setEventsEnabled(enabled); - } - - @Override - public boolean isSendingEvents() { - return view.isSendingEvents(); - } - - @Override - public void flushEvents() { - view.flushEvents(); - } - - @Override - public void flushPrivateEventQueue(EventQueueID id) { - view.flushPrivateEventQueue(id); - } - - @Override - public boolean canLock() { - return view.canLock(); - } - - @Override - public boolean isLocked() { - return view.isLocked(); - } - - @Override - public boolean lock(String reason) { - return view.lock(reason); - } - - @Override - public void forceLock(boolean rollback, String reason) { - view.forceLock(rollback, reason); - } - - @Override - public void unlock() { - view.unlock(); - } - - @Override - public List getOptionsNames() { - return view.getOptionsNames(); - } - - @Override - public Options getOptions(String propertyListName) { - return view.getOptions(propertyListName); - } - - @Override - public boolean isClosed() { - return view.isClosed(); - } - - @Override - public boolean hasExclusiveAccess() { - return view.hasExclusiveAccess(); - } - - @Override - public Map getMetadata() { - return view.getMetadata(); - } - - @Override - public long getModificationNumber() { - return view.getModificationNumber(); - } - - @Override - public boolean canUndo() { - return view.canUndo(); - } - - @Override - public boolean canRedo() { - return view.canRedo(); - } - - @Override - public void clearUndo() { - view.clearUndo(); - } - - @Override - public void undo() throws IOException { - view.undo(); - } - - @Override - public void redo() throws IOException { - view.redo(); - } - - @Override - public String getUndoName() { - return view.getUndoName(); - } - - @Override - public String getRedoName() { - return view.getRedoName(); - } - - @Override - public List getAllUndoNames() { - return view.getAllUndoNames(); - } - - @Override - public List getAllRedoNames() { - return view.getAllRedoNames(); - } - - @Override - public void addTransactionListener(TransactionListener listener) { - view.addTransactionListener(listener); - } - - @Override - public void removeTransactionListener(TransactionListener listener) { - view.removeTransactionListener(listener); - } - - @Override - public Trace getTrace() { - return view.getTrace(); - } - - @Override - public long getSnap() { - return view.getSnap(); - } - - @Override - public TraceTimeViewport getViewport() { - return view.getViewport(); - } - - @Override - public Long getMaxSnap() { - return view.getMaxSnap(); - } - - @Override - public TraceProgramView getViewRegisters(TraceThread t, boolean createIfAbsent) { - return view.getViewRegisters(t, createIfAbsent); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegistersReferenceManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegistersReferenceManager.java deleted file mode 100644 index 6b7e7e88c6..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegistersReferenceManager.java +++ /dev/null @@ -1,43 +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.program; - -import ghidra.trace.model.listing.TraceCodeOperations; -import ghidra.trace.model.symbol.TraceReferenceOperations; -import ghidra.trace.model.thread.TraceThread; - -public class DBTraceProgramViewRegistersReferenceManager - extends AbstractDBTraceProgramViewReferenceManager { - - private final TraceThread thread; - - public DBTraceProgramViewRegistersReferenceManager(DBTraceProgramView program, - TraceThread thread) { - super(program); - this.thread = thread; - } - - @Override - protected TraceReferenceOperations getReferenceOperations(boolean createIfAbsent) { - return program.trace.getReferenceManager() - .getReferenceRegisterSpace(thread, createIfAbsent); - } - - @Override - protected TraceCodeOperations getCodeOperations(boolean createIfAbsent) { - return program.trace.getCodeManager().getCodeRegisterSpace(thread, createIfAbsent); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java index 364cc20d26..057b472b02 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java @@ -4,9 +4,9 @@ * 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. @@ -86,15 +86,14 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { @Override public Symbol createLabel(Address addr, String name, SourceType source) throws InvalidInputException { - return symbolManager.labels().create(program.snap, null, addr, name, global, source); + return symbolManager.labels().create(program.snap, addr, name, global, source); } @Override public Symbol createLabel(Address addr, String name, Namespace namespace, SourceType source) throws InvalidInputException { return symbolManager.labels() - .create(program.snap, null, addr, name, - assertTraceNamespace(namespace), source); + .create(program.snap, addr, name, assertTraceNamespace(namespace), source); } @Override @@ -110,7 +109,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { } Address address = dbSym.getAddress(); Collection at = - symbolManager.labels().getAt(program.snap, null, address, false); + symbolManager.labels().getAt(program.snap, address, false); String name; TraceNamespaceSymbol parent; SourceType source; @@ -272,7 +271,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { public Symbol getPrimarySymbol(Address addr) { try (LockHold hold = program.trace.lockRead()) { Collection at = - symbolManager.labels().getAt(program.snap, null, addr, true); + symbolManager.labels().getAt(program.snap, addr, true); if (at.isEmpty()) { return null; } @@ -284,7 +283,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { public Symbol[] getSymbols(Address addr) { try (LockHold hold = program.trace.lockRead()) { Collection at = - symbolManager.labels().getAt(program.snap, null, addr, true); + symbolManager.labels().getAt(program.snap, addr, true); return at.toArray(new Symbol[at.size()]); } } @@ -300,7 +299,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { public Symbol[] getUserSymbols(Address addr) { try (LockHold hold = program.trace.lockRead()) { Collection at = - symbolManager.labels().getAt(program.snap, null, addr, false); + symbolManager.labels().getAt(program.snap, addr, false); return at.toArray(new Symbol[at.size()]); } } @@ -324,7 +323,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { @Override public boolean hasSymbol(Address addr) { if (addr.isMemoryAddress()) { - return symbolManager.labels().hasAt(program.snap, null, addr, true); + return symbolManager.labels().hasAt(program.snap, addr, true); } return false; } @@ -347,7 +346,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { if (range.getAddressSpace().isMemorySpace()) { if (type == SymbolType.LABEL) { return symbolManager.labels() - .getIntersecting(Lifespan.at(program.snap), null, range, true, forward) + .getIntersecting(Lifespan.at(program.snap), range, true, forward) .iterator(); } } @@ -371,8 +370,8 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { Spliterator spliterator = Spliterators.spliteratorUnknownSize(asv.iterator(forward), 0); return StreamSupport.stream(spliterator, false).flatMap(range -> { - return view.getIntersecting(Lifespan.at(program.snap), null, range, - includeDynamicSymbols, forward).stream(); + return view.getIntersecting(Lifespan.at(program.snap), range, includeDynamicSymbols, + forward).stream(); }).iterator(); } @@ -429,7 +428,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { public SymbolIterator getPrimarySymbolIterator(AddressSetView asv, boolean forward) { return new PrimarySymbolIterator(NestedIterator.start(asv.iterator(forward), range -> symbolManager.labels() - .getIntersecting(Lifespan.at(program.snap), null, range, true, forward) + .getIntersecting(Lifespan.at(program.snap), range, true, forward) .iterator())); } @@ -473,7 +472,7 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { // NOTE: Currently, traces do not allow namespaces to have arbitrary bodies. // Instead, their bodies are the union of addresses of their descendants. if (addr.isMemoryAddress()) { - for (TraceSymbol sym : symbolManager.labels().getAt(program.snap, null, addr, true)) { + for (TraceSymbol sym : symbolManager.labels().getAt(program.snap, addr, true)) { if (sym instanceof TraceNamespaceSymbol /* Function */) { return (TraceNamespaceSymbol) sym; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/space/AbstractDBTraceSpaceBasedManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/space/AbstractDBTraceSpaceBasedManager.java index 88e23ce5f9..f7c4d9ffa8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/space/AbstractDBTraceSpaceBasedManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/space/AbstractDBTraceSpaceBasedManager.java @@ -22,19 +22,15 @@ import java.util.concurrent.locks.ReadWriteLock; import db.DBHandle; import db.DBRecord; -import generic.CatenatedCollection; import ghidra.framework.data.OpenMode; import ghidra.program.model.address.*; import ghidra.program.model.lang.Language; import ghidra.trace.database.*; import ghidra.trace.database.thread.DBTraceThreadManager; -import ghidra.trace.model.memory.TraceObjectRegisterContainer; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.memory.TraceRegisterContainer; import ghidra.trace.model.stack.TraceStackFrame; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.LockHold; import ghidra.util.Msg; import ghidra.util.database.*; @@ -46,25 +42,15 @@ public abstract class AbstractDBTraceSpaceBasedManager spaceStore; // Note: use tree map so traversal is ordered by address space - protected final Map memSpaces = new TreeMap<>(); - // Note: can use hash map here. I see no need to order these spaces - protected final Map regSpaces = new HashMap<>(); - protected final Map regSpacesByContainer = new HashMap<>(); + protected final Map spaces = new TreeMap<>(); + protected final Map regSpacesByContainer = new HashMap<>(); - protected final Collection memSpacesView = - Collections.unmodifiableCollection(memSpaces.values()); - protected final Collection regSpacesView = - Collections.unmodifiableCollection(regSpaces.values()); - protected final Collection allSpacesView = - new CatenatedCollection<>(memSpacesView, regSpacesView); + protected final Collection spacesView = Collections.unmodifiableCollection(spaces.values()); public AbstractDBTraceSpaceBasedManager(String name, DBHandle dbh, OpenMode openMode, ReadWriteLock lock, TaskMonitor monitor, Language baseLanguage, DBTrace trace, @@ -141,31 +96,19 @@ public abstract class AbstractDBTraceSpaceBasedManager newRegSpaces = new HashMap<>(); - Map newMemSpaces = new HashMap<>(); + Map newSpaces = new HashMap<>(); for (TabledSpace ts : getTabledSpaces()) { - if (ts.isRegisterSpace() && !ts.isOverlaySpace()) { - newRegSpaces.put(ts.frame(), ts); - } - else { - newMemSpaces.put(ts.space(), ts); - } + newSpaces.put(ts.space(), ts); } - regSpaces.keySet().retainAll(newRegSpaces.keySet()); - memSpaces.keySet().retainAll(newMemSpaces.keySet()); - for (Entry ent : newRegSpaces.entrySet()) { - if (!regSpaces.containsKey(ent.getKey())) { - regSpaces.put(ent.getKey(), createRegisterSpace(ent.getValue())); - } - } - for (Entry ent : newMemSpaces.entrySet()) { - if (!memSpaces.containsKey(ent.getKey())) { - memSpaces.put(ent.getKey(), createSpace(ent.getValue())); + spaces.keySet().retainAll(newSpaces.keySet()); + for (Entry ent : newSpaces.entrySet()) { + if (!spaces.containsKey(ent.getKey())) { + spaces.put(ent.getKey(), createSpace(ent.getValue())); } } } @@ -187,17 +130,7 @@ public abstract class AbstractDBTraceSpaceBasedManager { + return spaces.computeIfAbsent(space, s -> { // NOTE: Require caller to start transaction try { DBTraceSpaceEntry ent = spaceStore.create(); @@ -235,51 +168,23 @@ public abstract class AbstractDBTraceSpaceBasedManager { - AddressSpace regSpace = baseLanguage.getAddressFactory().getRegisterSpace(); - try { - DBTraceSpaceEntry ent = spaceStore.create(); - ent.set(regSpace.getName(), thread.getKey(), frameLevel); - return createRegisterSpace(regSpace, thread, ent); - } - catch (VersionException e) { - throw new AssertionError(e); - } - catch (IOException e) { - dbError(e); - return null; - } - }); - } + TraceRegisterContainer container = + TraceRegisterUtils.getRegisterContainer(thread.getObject(), frameLevel); + return getForRegisterSpace(container, createIfAbsent); } protected M getForRegisterSpace(TraceStackFrame frame, boolean createIfAbsent) { - if (frame instanceof TraceObjectStackFrame objFrame) { - // Use frameLevel = 0, because we're already in the frame - // so, no wild cards between here and registers - return getForRegisterSpace(objFrame.getObject(), 0, createIfAbsent); - } - return getForRegisterSpace(frame.getStack().getThread(), frame.getLevel(), createIfAbsent); + TraceRegisterContainer container = TraceRegisterUtils.getRegisterContainer(frame); + return getForRegisterSpace(container, createIfAbsent); } - private M doGetForRegisterSpaceFoundContainer(TraceObject regsObject, boolean createIfAbsent) { - String name = regsObject.getCanonicalPath().toString(); + private M doGetForRegisterSpaceFoundContainer(TraceRegisterContainer container, + boolean createIfAbsent) { + AddressSpace as = TraceRegisterUtils.getRegisterAddressSpace(container, createIfAbsent); if (!createIfAbsent) { try (LockHold hold = LockHold.lock(lock.readLock())) { - AddressSpace as = trace.getBaseAddressFactory().getAddressSpace(name); if (as == null) { - // TODO: Would like to cache this, but answer is likely to change + // NOTE: Would like to cache this, but answer is likely to change return null; } M space = getForSpace(as, createIfAbsent); @@ -287,51 +192,32 @@ public abstract class AbstractDBTraceSpaceBasedManager getActiveSpaces() { - return allSpacesView; - } - - public Collection getActiveMemorySpaces() { - return memSpacesView; - } - - public Collection getActiveRegisterSpaces() { - return regSpacesView; + return spacesView; } protected abstract M createSpace(AddressSpace space, DBTraceSpaceEntry ent) throws VersionException, IOException; - protected abstract M createRegisterSpace(AddressSpace space, TraceThread thread, - DBTraceSpaceEntry ent) throws VersionException, IOException; - @SuppressWarnings("unchecked") private M createSpace(TabledSpace ts) throws VersionException, IOException { if (ts.entry.space != null) { @@ -383,16 +254,6 @@ public abstract class AbstractDBTraceSpaceBasedManager { - protected StackChangeTranslator(DBTraceObject object, TraceStack iface) { - super(null, object, iface); - } - - @Override - protected TraceEvent getAddedType() { - return TraceEvents.STACK_ADDED; - } - - @Override - protected TraceEvent getLifespanChangedType() { - return null; - } - - @Override - protected TraceEvent getChangedType() { - return TraceEvents.STACK_CHANGED; - } - - @Override - protected boolean appliesToKey(String key) { - return false; - } - - @Override - protected TraceEvent getDeletedType() { - return TraceEvents.STACK_DELETED; - } - } - - private final DBTraceObject object; - private final StackChangeTranslator translator; - - public DBTraceObjectStack(DBTraceObject object) { - this.object = object; - - translator = new StackChangeTranslator(object, this); - } - - @Override - public TraceThread getThread() { - try (LockHold hold = object.getTrace().lockRead()) { - return object.queryCanonicalAncestorsInterface(TraceObjectThread.class) - .findAny() - .orElseThrow(); - } - } - - @Override - public int getDepth(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return object - .querySuccessorsInterface(Lifespan.at(snap), TraceObjectStackFrame.class, true) - .map(f -> f.getLevel()) - .reduce(Integer::max) - .map(m -> m + 1) - .orElse(0); - } - } - - protected TraceObjectStackFrame doAddStackFrame(long snap, int level) { - try (LockHold hold = object.getTrace().lockWrite()) { - PathFilter filter = - object.getSchema().searchFor(TraceObjectStackFrame.class, true); - KeyPath relPath = filter.applyKeys(KeyPath.makeIndex(level)).getSingletonPath(); - if (relPath == null) { - throw new IllegalStateException("Could not determine where to create new frame"); - } - KeyPath path = object.getCanonicalPath().extend(relPath); - return object.getManager().addStackFrame(path, snap); - } - } - - protected void copyFrameAttributes(long snap, TraceObjectStackFrame from, - TraceObjectStackFrame to) { - // Program Counter is the only attribute? - to.setProgramCounter(Lifespan.nowOn(snap), from.getProgramCounter(snap)); - } - - protected void shiftFrameAttributes(long snap, int from, int to, int count, - List frames) { - if (from == to) { - return; - } - if (from < to) { - for (int i = count - 1; i >= 0; i--) { - copyFrameAttributes(snap, frames.get(from + i), frames.get(to + i)); - } - } - else { - for (int i = 0; i < count; i++) { - copyFrameAttributes(snap, frames.get(from + i), frames.get(to + i)); - } - } - } - - protected void clearFrameAttributes(long snap, int start, int end, - List frames) { - for (int i = start; i < end; i++) { - TraceObjectStackFrame frame = frames.get(i); - frame.setProgramCounter(Lifespan.nowOn(snap), null); - } - } - - @Override - public void setDepth(long snap, int depth, boolean atInner) { - try (LockHold hold = object.getTrace().lockWrite()) { - List frames = doGetFrames(snap) - // Want mutable list - .collect(Collectors.toCollection(ArrayList::new)); - int curDepth = frames.size(); - if (curDepth == depth) { - return; - } - if (depth < curDepth) { - if (atInner) { - int diff = curDepth - depth; - shiftFrameAttributes(snap, diff, 0, depth, frames); - } - for (int i = depth; i < curDepth; i++) { - frames.get(i).getObject().removeTree(Lifespan.nowOn(snap)); - } - } - else { - for (int i = curDepth; i < depth; i++) { - frames.add(doAddStackFrame(snap, i)); - } - if (atInner) { - int diff = depth - curDepth; - shiftFrameAttributes(snap, 0, diff, curDepth, frames); - clearFrameAttributes(snap, 0, diff, frames); - } - } - } - } - - protected TraceStackFrame doGetFrame(long snap, int level) { - TraceObjectSchema schema = object.getSchema(); - PathFilter filter = schema.searchFor(TraceObjectStackFrame.class, true); - PathFilter decFilter = filter.applyKeys(KeyPath.makeIndex(level)); - PathFilter hexFilter = filter.applyKeys("0x" + Integer.toHexString(level)); - Lifespan lifespan = Lifespan.at(snap); - return object.getSuccessors(lifespan, decFilter) - .findAny() - .map(p -> p.getDestination(object).queryInterface(TraceObjectStackFrame.class)) - .or(() -> object.getSuccessors(lifespan, hexFilter) - .findAny() - .map(p -> p.getDestination(object) - .queryInterface(TraceObjectStackFrame.class))) - .orElse(null); - } - - @Override - // This assumes the frame indices are contiguous and include 0 - public TraceStackFrame getFrame(long snap, int level, boolean ensureDepth) { - if (ensureDepth) { - try (LockHold hold = object.getTrace().lockWrite()) { - if (level >= getDepth(snap)) { - setDepth(snap, level + 1, false); - } - return doGetFrame(snap, level); - } - } - try (LockHold hold = object.getTrace().lockRead()) { - return doGetFrame(snap, level); - } - } - - protected Stream doGetFrames(long snap) { - return object.querySuccessorsInterface(Lifespan.at(snap), TraceObjectStackFrame.class, true) - .sorted(Comparator.comparing(f -> f.getLevel())); - } - - @Override - public List getFrames(long snap) { - try (LockHold hold = object.getTrace().lockRead()) { - return doGetFrames(snap).collect(Collectors.toList()); - } - } - - @Override - public void delete() { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.ALL); - } - } - - @Override - public void remove(long snap) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.nowOn(snap)); - } - } - - @Override - public boolean isValid(long snap) { - return object.isAlive(snap); - } - - @Override - public TraceObject getObject() { - return object; - } - - @Override - public TraceChangeRecord translateEvent(TraceChangeRecord rec) { - return translator.translate(rec); - } - - @Override - public boolean hasFixedFrames() { - return false; - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceObjectStackFrame.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceObjectStackFrame.java deleted file mode 100644 index d24e508407..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceObjectStackFrame.java +++ /dev/null @@ -1,180 +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.stack; - -import java.util.*; - -import ghidra.framework.model.EventType; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.CommentType; -import ghidra.trace.database.target.DBTraceObject; -import ghidra.trace.database.target.DBTraceObjectInterface; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.Lifespan.DefaultLifeSet; -import ghidra.trace.model.Lifespan.LifeSet; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.TraceObjectValue; -import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; -import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; -import ghidra.util.LockHold; - -public class DBTraceObjectStackFrame implements TraceObjectStackFrame, DBTraceObjectInterface { - private static final Map> KEYS_BY_SCHEMA = new WeakHashMap<>(); - - private final DBTraceObject object; - private final Set keys; - - // TODO: Memorizing life is not optimal. - // GP-1887 means to expose multiple lifespans in, e.g., TraceThread - private LifeSet life = new DefaultLifeSet(); - - public DBTraceObjectStackFrame(DBTraceObject object) { - this.object = object; - - TraceObjectSchema schema = object.getSchema(); - synchronized (KEYS_BY_SCHEMA) { - keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, - s -> Set.of(schema.checkAliasedAttribute(TraceObjectStackFrame.KEY_PC))); - } - } - - @Override - public TraceObjectStack getStack() { - try (LockHold hold = object.getTrace().lockRead()) { - return object.queryCanonicalAncestorsInterface(TraceObjectStack.class) - .findAny() - .orElseThrow(); - } - } - - @Override - public int getLevel() { - KeyPath path = object.getCanonicalPath(); - for (int i = path.size() - 1; i >= 0; i--) { - String k = path.key(i); - if (!KeyPath.isIndex(k)) { - continue; - } - String index = KeyPath.parseIndex(k); - try { - return Integer.decode(index); - // TODO: Perhaps just have an attribute that is its level? - } - catch (NumberFormatException e) { - // fall to preceding key - } - } - throw new IllegalStateException("Frame has no index!?"); - } - - @Override - public Address getProgramCounter(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, TraceObjectStackFrame.KEY_PC, - Address.class, null); - } - - @Override - public void setProgramCounter(Lifespan span, Address pc) { - try (LockHold hold = object.getTrace().lockWrite()) { - if (pc == Address.NO_ADDRESS) { - pc = null; - } - object.setValue(span, TraceObjectStackFrame.KEY_PC, pc); - } - } - - @Override - public String getComment(long snap) { - // TODO: One day, we'll have dynamic columns in the debugger - /* - * I don't use an attribute for this, because there's not a nice way track the "identity" of - * a stack frame. If the frame is re-used (the recommendation for connector development), - * the same comment may not necessarily apply. It'd be nice if the connector re-assigned - * levels so that identical objects implied identical frames, but that's quite a burden. The - * closest identity heuristic is the program counter. Instead of commenting the frame, I'll - * comment the memory at the program counter (often, really the return address). Not - * perfect, since it may collide with other comments, but a decent approximation that will - * follow the "same frame" as its level changes. - */ - try (LockHold hold = object.getTrace().lockRead()) { - Address pc = getProgramCounter(snap); - return pc == null ? null - : object.getTrace().getCommentAdapter().getComment(snap, pc, CommentType.EOL); - } - } - - @Override - public void setComment(long snap, String comment) { - /* See rant in getComment */ - try (LockHold hold = object.getTrace().lockWrite()) { - TraceObjectValue pcAttr = object.getValue(snap, TraceObjectStackFrame.KEY_PC); - object.getTrace() - .getCommentAdapter() - .setComment(pcAttr.getLifespan(), (Address) pcAttr.getValue(), CommentType.EOL, - comment); - } - } - - @Override - public TraceObject getObject() { - return object; - } - - protected boolean changeApplies(TraceChangeRecord rec) { - TraceChangeRecord cast = TraceEvents.VALUE_CREATED.cast(rec); - TraceObjectValue affected = cast.getAffectedObject(); - assert affected.getParent() == object; - if (!keys.contains(affected.getEntryKey())) { - return false; - } - if (object.getCanonicalParent(affected.getMaxSnap()) == null) { - return false; - } - return true; - } - - protected TraceChangeRecord createChangeRecord() { - return new TraceChangeRecord<>(TraceEvents.STACK_CHANGED, null, getStack(), 0L, - life.bound().lmin()); - } - - @Override - public TraceChangeRecord translateEvent(TraceChangeRecord rec) { - EventType type = rec.getEventType(); - if (type == TraceEvents.OBJECT_LIFE_CHANGED) { - LifeSet newLife = object.getLife(); - if (!newLife.isEmpty()) { - life = newLife; - } - return createChangeRecord(); - } - else if (type == TraceEvents.VALUE_CREATED && changeApplies(rec)) { - return createChangeRecord(); - } - else if (type == TraceEvents.OBJECT_DELETED) { - if (life.isEmpty()) { - return null; - } - return createChangeRecord(); - } - return null; - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java index 358de95b7e..a6afc0481c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java @@ -15,256 +15,235 @@ */ package ghidra.trace.database.stack; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.ByteBuffer; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import db.BinaryField; -import db.DBRecord; +import ghidra.trace.database.target.DBTraceObject; +import ghidra.trace.database.target.DBTraceObjectInterface; +import ghidra.trace.model.Lifespan; import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStackFrame; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.path.KeyPath; +import ghidra.trace.model.target.path.PathFilter; +import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; +import ghidra.trace.util.*; import ghidra.util.LockHold; -import ghidra.util.database.*; -import ghidra.util.database.DBCachedObjectStoreFactory.AbstractDBFieldCodec; -import ghidra.util.database.annot.*; -@DBAnnotatedObjectInfo(version = 0) -public class DBTraceStack extends DBAnnotatedObject implements TraceStack { - public static final String TABLE_NAME = "Stacks"; +public class DBTraceStack implements TraceStack, DBTraceObjectInterface { - static final String THREAD_SNAP_COLUMN_NAME = "ThreadSnap"; - static final String FRAMES_COLUMN_NAME = "Frames"; - - @DBAnnotatedColumn(THREAD_SNAP_COLUMN_NAME) - static DBObjectColumn THREAD_SNAP_COLUMN; - @DBAnnotatedColumn(FRAMES_COLUMN_NAME) - static DBObjectColumn FRAMES_COLUMN; - - public static class ThreadSnap { - long threadKey; - long snap; - - public ThreadSnap() { - } - - public ThreadSnap(long threadKey, long snap) { - this.threadKey = threadKey; - this.snap = snap; - } - } - - public static class ThreadSnapDBFieldCodec - extends AbstractDBFieldCodec { - - public ThreadSnapDBFieldCodec(Class objectType, Field field, - int column) { - super(ThreadSnap.class, objectType, BinaryField.class, field, column); - } - - protected byte[] encode(ThreadSnap value) { - ByteBuffer buf = ByteBuffer.allocate(Long.BYTES * 2); - buf.putLong(value.threadKey); - buf.putLong(value.snap); - return buf.array(); - } - - protected ThreadSnap decode(byte[] data) { - ByteBuffer buf = ByteBuffer.wrap(data); - ThreadSnap value = new ThreadSnap(); - value.threadKey = buf.getLong(); - value.snap = buf.getLong(); - return value; + protected class StackChangeTranslator extends Translator { + protected StackChangeTranslator(DBTraceObject object, TraceStack iface) { + super(null, object, iface); } @Override - public void store(ThreadSnap value, BinaryField f) { - f.setBinaryData(encode(value)); + protected TraceEvent getAddedType() { + return TraceEvents.STACK_ADDED; } @Override - protected void doStore(DBAnnotatedObject obj, DBRecord record) - throws IllegalArgumentException, IllegalAccessException { - record.setBinaryData(column, encode(getValue(obj))); + protected TraceEvent getLifespanChangedType() { + return null; } @Override - protected void doLoad(DBAnnotatedObject obj, DBRecord record) - throws IllegalArgumentException, IllegalAccessException { - setValue(obj, decode(record.getBinaryData(column))); + protected TraceEvent getChangedType() { + return TraceEvents.STACK_CHANGED; + } + + @Override + protected boolean appliesToKey(String key) { + return false; + } + + @Override + protected TraceEvent getDeletedType() { + return TraceEvents.STACK_DELETED; } } - @DBAnnotatedField( - column = THREAD_SNAP_COLUMN_NAME, - indexed = true, - codec = ThreadSnapDBFieldCodec.class) - private ThreadSnap threadSnap; - @DBAnnotatedField(column = FRAMES_COLUMN_NAME) - private long[] frameKeys; + private final DBTraceObject object; + private final StackChangeTranslator translator; - private final DBTraceStackManager manager; + public DBTraceStack(DBTraceObject object) { + this.object = object; - private TraceThread thread; - private final List frames = new ArrayList<>(); - - public DBTraceStack(DBTraceStackManager manager, DBCachedObjectStore store, - DBRecord record) { - super(store, record); - this.manager = manager; - } - - @Override - protected void fresh(boolean created) throws IOException { - if (created) { - threadSnap = new ThreadSnap(); - } - else { - thread = manager.threadManager.getThread(threadSnap.threadKey); - frames.clear(); - if (frameKeys == null) { - return; - } - for (long k : frameKeys) { - frames.add(manager.getFrameByKey(k)); - } - } - } - - void set(TraceThread thread, long snap) { - this.thread = thread; - threadSnap.threadKey = thread.getKey(); - threadSnap.snap = snap; - update(THREAD_SNAP_COLUMN); + translator = new StackChangeTranslator(object, this); } @Override public TraceThread getThread() { - return thread; - } - - long getSnap() { - return threadSnap.snap; + try (LockHold hold = object.getTrace().lockRead()) { + return object.queryCanonicalAncestorsInterface(TraceThread.class) + .findAny() + .orElseThrow(); + } } @Override public int getDepth(long snap) { - if (frameKeys == null) { - return 0; + try (LockHold hold = object.getTrace().lockRead()) { + return object + .querySuccessorsInterface(Lifespan.at(snap), TraceStackFrame.class, true) + .map(f -> f.getLevel()) + .reduce(Integer::max) + .map(m -> m + 1) + .orElse(0); } - return frameKeys.length; } - protected void doUpdateFrameKeys() { - int depth = frames.size(); - frameKeys = new long[depth]; - for (int i = 0; i < depth; i++) { - frameKeys[i] = frames.get(i).getKey(); + protected TraceStackFrame doAddStackFrame(long snap, int level) { + try (LockHold hold = object.getTrace().lockWrite()) { + PathFilter filter = + object.getSchema().searchFor(TraceStackFrame.class, true); + KeyPath relPath = filter.applyKeys(KeyPath.makeIndex(level)).getSingletonPath(); + if (relPath == null) { + throw new IllegalStateException("Could not determine where to create new frame"); + } + KeyPath path = object.getCanonicalPath().extend(relPath); + return object.getManager().addStackFrame(path, snap); } - update(FRAMES_COLUMN); } - protected void doUpdateFrameLevels(int start, int end) { + protected void copyFrameAttributes(long snap, TraceStackFrame from, TraceStackFrame to) { + // Program Counter is the only attribute? + to.setProgramCounter(Lifespan.nowOn(snap), from.getProgramCounter(snap)); + } + + protected void shiftFrameAttributes(long snap, int from, int to, int count, + List frames) { + if (from == to) { + return; + } + if (from < to) { + for (int i = count - 1; i >= 0; i--) { + copyFrameAttributes(snap, frames.get(from + i), frames.get(to + i)); + } + } + else { + for (int i = 0; i < count; i++) { + copyFrameAttributes(snap, frames.get(from + i), frames.get(to + i)); + } + } + } + + protected void clearFrameAttributes(long snap, int start, int end, + List frames) { for (int i = start; i < end; i++) { - frames.get(i).setLevel(i); + TraceStackFrame frame = frames.get(i); + frame.setProgramCounter(Lifespan.nowOn(snap), null); } } @Override public void setDepth(long snap, int depth, boolean atInner) { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - //System.err.println("setDepth(threadKey=" + thread.getKey() + "snap=" + getSnap() + - // ",depth=" + depth + ",inner=" + atInner + ");"); - int curDepth = frameKeys == null ? 0 : frameKeys.length; - if (depth == curDepth) { + try (LockHold hold = object.getTrace().lockWrite()) { + List frames = doGetFrames(snap) + // Want mutable list + .collect(Collectors.toCollection(ArrayList::new)); + int curDepth = frames.size(); + if (curDepth == depth) { return; } if (depth < curDepth) { - List toRemove = - atInner ? frames.subList(0, curDepth - depth) - : frames.subList(depth, curDepth); - for (DBTraceStackFrame frame : toRemove) { - manager.deleteFrame(frame); - } - toRemove.clear(); if (atInner) { - doUpdateFrameLevels(0, frames.size()); + int diff = curDepth - depth; + shiftFrameAttributes(snap, diff, 0, depth, frames); + } + for (int i = depth; i < curDepth; i++) { + frames.get(i).getObject().removeTree(Lifespan.nowOn(snap)); } } else { - List toAdd = - Arrays.asList(new DBTraceStackFrame[depth - curDepth]); - for (int i = 0; i < toAdd.size(); i++) { - toAdd.set(i, manager.createFrame(this)); + for (int i = curDepth; i < depth; i++) { + frames.add(doAddStackFrame(snap, i)); } if (atInner) { - frames.addAll(0, toAdd); - doUpdateFrameLevels(0, frames.size()); - } - else { - frames.addAll(toAdd); - doUpdateFrameLevels(frames.size() - toAdd.size(), frames.size()); + int diff = depth - curDepth; + shiftFrameAttributes(snap, 0, diff, curDepth, frames); + clearFrameAttributes(snap, 0, diff, frames); } } - doUpdateFrameKeys(); } - manager.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.STACK_CHANGED, null, this, 0L, snap)); + } + + protected TraceStackFrame doGetFrame(long snap, int level) { + TraceObjectSchema schema = object.getSchema(); + PathFilter filter = schema.searchFor(TraceStackFrame.class, true); + PathFilter decFilter = filter.applyKeys(KeyPath.makeIndex(level)); + PathFilter hexFilter = filter.applyKeys("0x" + Integer.toHexString(level)); + Lifespan lifespan = Lifespan.at(snap); + return object.getSuccessors(lifespan, decFilter) + .findAny() + .map(p -> p.getDestination(object).queryInterface(TraceStackFrame.class)) + .or(() -> object.getSuccessors(lifespan, hexFilter) + .findAny() + .map(p -> p.getDestination(object).queryInterface(TraceStackFrame.class))) + .orElse(null); } @Override - public DBTraceStackFrame getFrame(long snap, int level, boolean ensureDepth) { + // This assumes the frame indices are contiguous and include 0 + public TraceStackFrame getFrame(long snap, int level, boolean ensureDepth) { if (ensureDepth) { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - if (level >= frames.size()) { + try (LockHold hold = object.getTrace().lockWrite()) { + if (level >= getDepth(snap)) { setDepth(snap, level + 1, false); } - return frames.get(level); + return doGetFrame(snap, level); } } - else { - try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - if (level >= frames.size()) { - return null; - } - return frames.get(level); - } + try (LockHold hold = object.getTrace().lockRead()) { + return doGetFrame(snap, level); } } + protected Stream doGetFrames(long snap) { + return object.querySuccessorsInterface(Lifespan.at(snap), TraceStackFrame.class, true) + .sorted(Comparator.comparing(f -> f.getLevel())); + } + @Override public List getFrames(long snap) { - try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - return List.copyOf(frames); + try (LockHold hold = object.getTrace().lockRead()) { + return doGetFrames(snap).collect(Collectors.toList()); } } @Override public void delete() { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - for (DBTraceStackFrame frame : frames) { - manager.deleteFrame(frame); - } - manager.deleteStack(this); + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.ALL); } - manager.trace.setChanged(new TraceChangeRecord<>(TraceEvents.STACK_DELETED, null, this)); } @Override public void remove(long snap) { - throw new UnsupportedOperationException(); + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.nowOn(snap)); + } } @Override public boolean isValid(long snap) { - return this == manager.getLatestStack(thread, snap); + return object.isAlive(snap); + } + + @Override + public TraceObject getObject() { + return object; + } + + @Override + public TraceChangeRecord translateEvent(TraceChangeRecord rec) { + return translator.translate(rec); } @Override public boolean hasFixedFrames() { - return true; + return false; } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackFrame.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackFrame.java index 3fc45074df..98a5c80c60 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackFrame.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackFrame.java @@ -15,142 +15,171 @@ */ package ghidra.trace.database.stack; -import java.io.IOException; -import java.util.Objects; +import java.util.*; -import db.DBRecord; -import ghidra.lifecycle.Internal; +import ghidra.framework.model.EventType; import ghidra.program.model.address.Address; -import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter; -import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec; -import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses; +import ghidra.program.model.listing.CommentType; +import ghidra.trace.database.target.DBTraceObject; +import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.Lifespan.DefaultLifeSet; +import ghidra.trace.model.Lifespan.LifeSet; +import ghidra.trace.model.Trace; +import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStackFrame; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.TraceObjectValue; +import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; +import ghidra.trace.model.target.path.KeyPath; +import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; -import ghidra.util.database.*; -import ghidra.util.database.annot.*; -/** - * The implementation of a stack frame, directly via a database object - * - *

- * Version history: - *

    - *
  • 1: Change {@link #pc} to 10-byte fixed encoding, make it sparse, so optional
  • - *
  • 0: Initial version and previous unversioned implementations
  • - *
- */ -@DBAnnotatedObjectInfo(version = 1) -public class DBTraceStackFrame extends DBAnnotatedObject - implements TraceStackFrame, DecodesAddresses { - public static final String TABLE_NAME = "StackFrames"; +public class DBTraceStackFrame implements TraceStackFrame, DBTraceObjectInterface { + private static final Map> KEYS_BY_SCHEMA = new WeakHashMap<>(); - static final String STACK_COLUMN_NAME = "Stack"; - static final String LEVEL_COLUMN_NAME = "Level"; - static final String PC_COLUMN_NAME = "PC"; - static final String COMMENT_COLUMN_NAME = "Comment"; + private final DBTraceObject object; + private final Set keys; - @DBAnnotatedColumn(STACK_COLUMN_NAME) - static DBObjectColumn STACK_COLUMN; - @DBAnnotatedColumn(LEVEL_COLUMN_NAME) - static DBObjectColumn LEVEL_COLUMN; - @DBAnnotatedColumn(PC_COLUMN_NAME) - static DBObjectColumn PC_COLUMN; - @DBAnnotatedColumn(COMMENT_COLUMN_NAME) - static DBObjectColumn COMMENT_COLUMN; + // TODO: Memorizing life is not optimal. + // GP-1887 means to expose multiple lifespans in, e.g., TraceThread + private LifeSet life = new DefaultLifeSet(); - @DBAnnotatedField(column = STACK_COLUMN_NAME) - private long stackKey; - @DBAnnotatedField(column = LEVEL_COLUMN_NAME) - private int level; - @DBAnnotatedField( - column = PC_COLUMN_NAME, - indexed = true, - codec = AddressDBFieldCodec.class, - sparse = true) - private Address pc; - @DBAnnotatedField(column = COMMENT_COLUMN_NAME) - private String comment; + public DBTraceStackFrame(DBTraceObject object) { + this.object = object; - private final DBTraceStackManager manager; - - private DBTraceStack stack; - - public DBTraceStackFrame(DBTraceStackManager manager, DBCachedObjectStore store, - DBRecord record) { - super(store, record); - this.manager = manager; - } - - @Override - public DBTraceOverlaySpaceAdapter getOverlaySpaceAdapter() { - return manager.overlayAdapter; - } - - @Override - protected void fresh(boolean created) throws IOException { - if (!created) { - stack = manager.getStackByKey(stackKey); + TraceObjectSchema schema = object.getSchema(); + synchronized (KEYS_BY_SCHEMA) { + keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, + s -> Set.of(schema.checkAliasedAttribute(KEY_PC))); } } - public void set(DBTraceStack stack) { - this.stack = stack; - this.stackKey = stack.getKey(); - update(STACK_COLUMN); + @Override + public Trace getTrace() { + return object.getTrace(); } @Override - public DBTraceStack getStack() { - return stack; + public TraceStack getStack() { + try (LockHold hold = object.getTrace().lockRead()) { + return object.queryCanonicalAncestorsInterface(TraceStack.class) + .findAny() + .orElseThrow(); + } } @Override public int getLevel() { - return level; + KeyPath path = object.getCanonicalPath(); + for (int i = path.size() - 1; i >= 0; i--) { + String k = path.key(i); + if (!KeyPath.isIndex(k)) { + continue; + } + String index = KeyPath.parseIndex(k); + try { + return Integer.decode(index); + // TODO: Perhaps just have an attribute that is its level? + } + catch (NumberFormatException e) { + // fall to preceding key + } + } + throw new IllegalStateException("Frame has no index!?"); } @Override public Address getProgramCounter(long snap) { - return pc; + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_PC, Address.class, null); } @Override public void setProgramCounter(Lifespan span, Address pc) { - //System.err.println("setPC(threadKey=" + stack.getThread().getKey() + ",snap=" + - // stack.getSnap() + ",level=" + level + ",pc=" + pc + ");"); - manager.trace.assertValidAddress(pc); - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - if (Objects.equals(this.pc, pc)) { - return; + try (LockHold hold = object.getTrace().lockWrite()) { + if (pc == Address.NO_ADDRESS) { + pc = null; } - this.pc = pc; - update(PC_COLUMN); + object.setValue(span, KEY_PC, pc); } - manager.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.STACK_CHANGED, null, stack, 0L, span.lmin())); } @Override public String getComment(long snap) { - return comment; + // TODO: One day, we'll have dynamic columns in the debugger + /* + * I don't use an attribute for this, because there's not a nice way track the "identity" of + * a stack frame. If the frame is re-used (the recommendation for connector development), + * the same comment may not necessarily apply. It'd be nice if the connector re-assigned + * levels so that identical objects implied identical frames, but that's quite a burden. The + * closest identity heuristic is the program counter. Instead of commenting the frame, I'll + * comment the memory at the program counter (often, really the return address). Not + * perfect, since it may collide with other comments, but a decent approximation that will + * follow the "same frame" as its level changes. + */ + try (LockHold hold = object.getTrace().lockRead()) { + Address pc = getProgramCounter(snap); + return pc == null ? null + : object.getTrace().getCommentAdapter().getComment(snap, pc, CommentType.EOL); + } } @Override public void setComment(long snap, String comment) { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - this.comment = comment; - update(COMMENT_COLUMN); + /* See rant in getComment */ + try (LockHold hold = object.getTrace().lockWrite()) { + TraceObjectValue pcAttr = object.getValue(snap, KEY_PC); + object.getTrace() + .getCommentAdapter() + .setComment(pcAttr.getLifespan(), (Address) pcAttr.getValue(), CommentType.EOL, + comment); } - manager.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.STACK_CHANGED, null, stack, 0L, snap)); } - @Internal - protected void setLevel(int level) { - this.level = level; - update(LEVEL_COLUMN); + @Override + public TraceObject getObject() { + return object; + } + + protected boolean changeApplies(TraceChangeRecord rec) { + TraceChangeRecord cast = TraceEvents.VALUE_CREATED.cast(rec); + TraceObjectValue affected = cast.getAffectedObject(); + assert affected.getParent() == object; + if (!keys.contains(affected.getEntryKey())) { + return false; + } + if (object.getCanonicalParent(affected.getMaxSnap()) == null) { + return false; + } + return true; + } + + protected TraceChangeRecord createChangeRecord() { + return new TraceChangeRecord<>(TraceEvents.STACK_CHANGED, null, getStack(), 0L, + life.bound().lmin()); + } + + @Override + public TraceChangeRecord translateEvent(TraceChangeRecord rec) { + EventType type = rec.getEventType(); + if (type == TraceEvents.OBJECT_LIFE_CHANGED) { + LifeSet newLife = object.getLife(); + if (!newLife.isEmpty()) { + life = newLife; + } + return createChangeRecord(); + } + else if (type == TraceEvents.VALUE_CREATED && changeApplies(rec)) { + return createChangeRecord(); + } + else if (type == TraceEvents.OBJECT_DELETED) { + if (life.isEmpty()) { + return null; + } + return createChangeRecord(); + } + return null; } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackManager.java index 40736a2780..a17d775b2b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStackManager.java @@ -21,12 +21,10 @@ import java.util.concurrent.locks.ReadWriteLock; import db.DBHandle; import generic.NestedIterator; import ghidra.framework.data.OpenMode; -import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTraceManager; import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter; -import ghidra.trace.database.stack.DBTraceStack.ThreadSnap; import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.model.Lifespan; import ghidra.trace.model.stack.*; @@ -34,12 +32,8 @@ import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; -import ghidra.util.database.*; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; @@ -52,11 +46,6 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager { protected final DBTraceThreadManager threadManager; protected final DBTraceOverlaySpaceAdapter overlayAdapter; - protected final DBCachedObjectStore stackStore; - protected final DBCachedObjectIndex stacksByThreadSnap; - protected final DBCachedObjectStore frameStore; - protected final DBCachedObjectIndex framesByPC; - public DBTraceStackManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock, TaskMonitor monitor, DBTrace trace, DBTraceThreadManager threadManager, DBTraceOverlaySpaceAdapter overlayAdapter) throws VersionException, IOException { @@ -65,22 +54,6 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager { this.trace = trace; this.threadManager = threadManager; this.overlayAdapter = overlayAdapter; - - DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - - stackStore = factory.getOrCreateCachedStore(DBTraceStack.TABLE_NAME, DBTraceStack.class, - (s, r) -> new DBTraceStack(this, s, r), true); - stacksByThreadSnap = stackStore.getIndex(ThreadSnap.class, DBTraceStack.THREAD_SNAP_COLUMN); - - frameStore = factory.getOrCreateCachedStore(DBTraceStackFrame.TABLE_NAME, - DBTraceStackFrame.class, (s, r) -> new DBTraceStackFrame(this, s, r), true); - framesByPC = frameStore.getIndex(Address.class, DBTraceStackFrame.PC_COLUMN); - } - - @Override - public void invalidateCache(boolean all) { - stackStore.invalidateCache(); - frameStore.invalidateCache(); } @Override @@ -88,12 +61,9 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager { trace.dbError(e); } - protected DBTraceStack getStackByKey(long stackKey) { - return stackStore.getObjectAt(stackKey); - } - - protected DBTraceStackFrame getFrameByKey(long frameKey) { - return frameStore.getObjectAt(frameKey); + @Override + public void invalidateCache(boolean all) { + // NOTE: This is only a wrapper around the object manager } public static PathFilter single(TraceObject seed, @@ -106,15 +76,14 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager { return stackFilter.getSingletonPattern(); } - protected TraceObjectStack doGetOrAddObjectStack(TraceThread thread, long snap, + protected TraceStack doGetOrAddObjectStack(TraceThread thread, long snap, boolean createIfAbsent) { - TraceObjectThread objThread = (TraceObjectThread) thread; - TraceObject obj = objThread.getObject(); - PathFilter filter = single(obj, TraceObjectStack.class); + TraceObject obj = thread.getObject(); + PathFilter filter = single(obj, TraceStack.class); if (createIfAbsent) { try (LockHold hold = trace.lockWrite()) { - TraceObjectStack stack = trace.getObjectManager() - .getSuccessor(obj, filter, snap, TraceObjectStack.class); + TraceStack stack = + trace.getObjectManager().getSuccessor(obj, filter, snap, TraceStack.class); if (stack != null) { return stack; } @@ -123,90 +92,37 @@ public class DBTraceStackManager implements TraceStackManager, DBTraceManager { } } try (LockHold hold = trace.lockRead()) { - return trace.getObjectManager() - .getSuccessor(obj, filter, snap, TraceObjectStack.class); + return trace.getObjectManager().getSuccessor(obj, filter, snap, TraceStack.class); } } - protected TraceObjectStack doGetLatestObjectStack(TraceThread thread, long snap) { - TraceObjectThread objThread = (TraceObjectThread) thread; - TraceObject obj = objThread.getObject(); - KeyPath path = single(obj, TraceObjectStack.class).getSingletonPath(); - return trace.getObjectManager().getLatestSuccessor(obj, path, snap, TraceObjectStack.class); + protected TraceStack doGetLatestObjectStack(TraceThread thread, long snap) { + TraceObject obj = thread.getObject(); + KeyPath path = single(obj, TraceStack.class).getSingletonPath(); + return trace.getObjectManager().getLatestSuccessor(obj, path, snap, TraceStack.class); } @Override public TraceStack getStack(TraceThread thread, long snap, boolean createIfAbsent) { threadManager.assertIsMine(thread); - if (trace.getObjectManager().hasSchema()) { - return doGetOrAddObjectStack(thread, snap, createIfAbsent); - } - DBTraceStack stack; - ThreadSnap key = new ThreadSnap(thread.getKey(), snap); - if (createIfAbsent) { - try (LockHold hold = LockHold.lock(lock.writeLock())) { - stack = stacksByThreadSnap.getOne(key); - if (stack != null) { - return stack; - } - stack = stackStore.create(); - stack.set(thread, snap); - } - trace.setChanged(new TraceChangeRecord<>(TraceEvents.STACK_ADDED, null, stack)); - return stack; - } - return stacksByThreadSnap.getOne(key); + return doGetOrAddObjectStack(thread, snap, createIfAbsent); } @Override public TraceStack getLatestStack(TraceThread thread, long snap) { threadManager.assertIsMine(thread); try (LockHold hold = LockHold.lock(lock.readLock())) { - if (trace.getObjectManager().hasSchema()) { - return doGetLatestObjectStack(thread, snap); - } - DBTraceStack found = - stacksByThreadSnap.floorValue(new ThreadSnap(thread.getKey(), snap)); - if (found == null) { - return null; - } - if (found.getThread() != thread || found.getSnap() > snap) { - // Encoded field results in unsigned index - // NB. Conventionally, a search should never traverse 0 (real to scratch space) - return null; - } - return found; + return doGetLatestObjectStack(thread, snap); } } @Override // TODO: Should probably include a lifespan parameter? public Iterable getFramesIn(AddressSetView set) { - if (trace.getObjectManager().hasSchema()) { - return () -> NestedIterator.start(set.iterator(), - rng -> trace.getObjectManager() - .getObjectsIntersecting(Lifespan.ALL, rng, - TraceObjectStackFrame.KEY_PC, TraceObjectStackFrame.class) - .iterator()); - } return () -> NestedIterator.start(set.iterator(), - rng -> framesByPC.sub(rng.getMinAddress(), true, rng.getMaxAddress(), true) - .values() + rng -> trace.getObjectManager() + .getObjectsIntersecting(Lifespan.ALL, rng, TraceStackFrame.KEY_PC, + TraceStackFrame.class) .iterator()); } - - protected void deleteStack(DBTraceStack stack) { - // Caller must delete frames - stackStore.delete(stack); - } - - protected DBTraceStackFrame createFrame(DBTraceStack stack) { - DBTraceStackFrame frame = frameStore.create(); - frame.set(stack); - return frame; - } - - protected void deleteFrame(DBTraceStackFrame frame) { - frameStore.delete(frame); - } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbol.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbol.java index 11344cffa1..4bbca1dffb 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbol.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbol.java @@ -39,7 +39,8 @@ import ghidra.trace.model.Lifespan; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.symbol.TraceSymbol; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.*; +import ghidra.trace.util.TraceChangeRecord; +import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; import ghidra.util.database.*; import ghidra.util.database.annot.DBAnnotatedColumn; @@ -172,8 +173,8 @@ public abstract class AbstractDBTraceSymbol extends DBAnnotatedObject return null; } - protected TraceAddressSpace getSpace() { - return null; + protected AddressSpace getAddressSpace() { + return getAddress().getAddressSpace(); } @Override @@ -340,7 +341,7 @@ public abstract class AbstractDBTraceSymbol extends DBAnnotatedObject return null; } this.name = newName; - return new TraceChangeRecord<>(TraceEvents.SYMBOL_RENAMED, getSpace(), this, oldName, + return new TraceChangeRecord<>(TraceEvents.SYMBOL_RENAMED, getAddressSpace(), this, oldName, newName); } @@ -365,7 +366,7 @@ public abstract class AbstractDBTraceSymbol extends DBAnnotatedObject DBTraceNamespaceSymbol checkedParent = checkCircular(newParent); this.parent = checkedParent; this.parentID = parent.getID(); - return new TraceChangeRecord<>(TraceEvents.SYMBOL_PARENT_CHANGED, getSpace(), this, + return new TraceChangeRecord<>(TraceEvents.SYMBOL_PARENT_CHANGED, getAddressSpace(), this, oldParent, checkedParent); } @@ -389,7 +390,7 @@ public abstract class AbstractDBTraceSymbol extends DBAnnotatedObject return null; } doSetSource(newSource); - return new TraceChangeRecord<>(TraceEvents.SYMBOL_SOURCE_CHANGED, getSpace(), this, + return new TraceChangeRecord<>(TraceEvents.SYMBOL_SOURCE_CHANGED, getAddressSpace(), this, oldSource, newSource); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeWithLocationView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeWithLocationView.java index 304130e35a..1eb049fcba 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeWithLocationView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeWithLocationView.java @@ -4,9 +4,9 @@ * 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. @@ -26,7 +26,6 @@ import ghidra.trace.database.DBTraceCacheForContainingQueries; import ghidra.trace.database.DBTraceCacheForContainingQueries.GetKey; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; -import ghidra.trace.database.space.DBTraceSpaceKey; import ghidra.trace.database.symbol.DBTraceSymbolManager.DBTraceSymbolIDEntry; import ghidra.trace.model.Lifespan; import ghidra.trace.model.TraceAddressSnapRange; @@ -120,7 +119,7 @@ public abstract class AbstractDBTraceSymbolSingleTypeWithLocationView doGetContaining(GetSymbolsKey key) { if (key.thread != null) { List result = - new ArrayList<>(getIntersecting(Lifespan.at(key.snap), key.thread, + new ArrayList<>(getIntersecting(Lifespan.at(key.snap), new AddressRangeImpl(key.addr, key.addr), key.includeDynamic, true)); result.sort(TraceSymbolManager.PRIMALITY_COMPARATOR); return result; @@ -138,12 +137,12 @@ public abstract class AbstractDBTraceSymbolSingleTypeWithLocationView getAt(long snap, TraceThread thread, Address address, + public Collection getAt(long snap, Address address, boolean includeDynamicSymbols) { try (LockHold hold = getManager().getTrace().lockRead()) { // TODO: Does "at" here work like "containing"? I suspect not.... return cacheForAt - .getContaining(new GetSymbolsKey(thread, snap, address, includeDynamicSymbols)); + .getContaining(new GetSymbolsKey(null, snap, address, includeDynamicSymbols)); } } /** - * TODO: Document me - * * Get intersecting things in no particular order * - * @param span - * @param thread - * @param range - * @param includeDynamicSymbols - * @return + * @param span the span of snapshots + * @param range the range of addresses + * @param includeDynamicSymbols true to include dynamic symbols + * @return the collection */ - public Collection getIntersecting(Lifespan span, TraceThread thread, - AddressRange range, boolean includeDynamicSymbols) { + public Collection getIntersecting(Lifespan span, AddressRange range, + boolean includeDynamicSymbols) { try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - manager.trace.getThreadManager().assertIsMine(thread); - manager.assertValidThreadAddress(thread, range.getMinAddress()); // Only examines space DBTraceAddressSnapRangePropertyMapSpace space = - manager.idMap.get(DBTraceSpaceKey.create(range.getAddressSpace(), thread, 0), - false); + manager.idMap.get(range.getAddressSpace(), false); if (space == null) { return Collections.emptyList(); } @@ -209,14 +199,11 @@ public abstract class AbstractDBTraceSymbolSingleTypeWithLocationView getIntersecting(Lifespan span, TraceThread thread, - AddressRange range, boolean includeDynamicSymbols, boolean forward) { + public Collection getIntersecting(Lifespan span, AddressRange range, + boolean includeDynamicSymbols, boolean forward) { try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - manager.trace.getThreadManager().assertIsMine(thread); - manager.assertValidThreadAddress(thread, range.getMinAddress()); // Only examines space DBTraceAddressSnapRangePropertyMapSpace space = - manager.idMap.get(DBTraceSpaceKey.create(range.getAddressSpace(), thread, 0), - false); + manager.idMap.get(range.getAddressSpace(), false); if (space == null) { return Collections.emptyList(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateManager.java index 6ba0aaaa1a..eeba3a9f63 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateManager.java @@ -4,9 +4,9 @@ * 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. @@ -106,13 +106,7 @@ public class DBTraceEquateManager extends AbstractDBTraceSpaceBasedManager m.getReferringAddresses(span)).toList()); + spacesView.stream().map(m -> m.getReferringAddresses(span)).toList()); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateSpace.java index 3686b875ad..8d7304b4a8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceEquateSpace.java @@ -4,9 +4,9 @@ * 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. @@ -32,7 +32,6 @@ import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpace import ghidra.trace.database.space.DBTraceSpaceBased; import ghidra.trace.model.Lifespan; import ghidra.trace.model.symbol.TraceEquateSpace; -import ghidra.trace.model.thread.TraceThread; import ghidra.util.LockHold; import ghidra.util.database.*; import ghidra.util.database.annot.*; @@ -61,8 +60,8 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace { @DBAnnotatedColumn(TYPE_COLUMN_NAME) static DBObjectColumn TYPE_COLUMN; - public static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + public static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField(column = EQUATE_COLUMN_NAME, indexed = true) @@ -99,8 +98,6 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace { protected final DBTraceEquateManager manager; protected final DBHandle dbh; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final ReadWriteLock lock; protected final Language baseLanguage; protected final DBTrace trace; @@ -110,12 +107,10 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace { protected final DBTraceAddressSnapRangePropertyMapSpace equateMapSpace; public DBTraceEquateSpace(DBTraceEquateManager manager, DBHandle dbh, AddressSpace space, - DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException { + DBTraceSpaceEntry ent) throws VersionException, IOException { this.manager = manager; this.dbh = dbh; this.space = space; - this.thread = thread; - this.frameLevel = ent.getFrameLevel(); this.lock = manager.getLock(); this.baseLanguage = manager.getBaseLanguage(); this.trace = manager.getTrace(); @@ -124,12 +119,14 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace { DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - long threadKey = ent.getThreadKey(); - int frameLevel = ent.getFrameLevel(); this.equateMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceEquateReference.tableName(space, threadKey, frameLevel), factory, lock, space, - thread, ent.getFrameLevel(), DBTraceEquateReference.class, - (t, s, r) -> new DBTraceEquateReference(this, t, s, r)); + DBTraceEquateReference.tableName(space), trace, factory, lock, space, + DBTraceEquateReference.class, (t, s, r) -> new DBTraceEquateReference(this, t, s, r)); + } + + @Override + public DBTrace getTrace() { + return trace; } @Override @@ -137,16 +134,6 @@ public class DBTraceEquateSpace implements DBTraceSpaceBased, TraceEquateSpace { return space; } - @Override - public TraceThread getThread() { - return thread; - } - - @Override - public int getFrameLevel() { - return frameLevel; - } - @Override public AddressSetView getReferringAddresses(Lifespan span) { return new DBTraceAddressSnapRangePropertyMapAddressSetView<>(space, lock, diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbol.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbol.java index 1c4a220fd3..9c19e9b52b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbol.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbol.java @@ -4,9 +4,9 @@ * 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. @@ -24,7 +24,6 @@ import ghidra.program.model.symbol.SymbolType; import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec; import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses; import ghidra.trace.database.listing.*; -import ghidra.trace.database.space.DBTraceSpaceKey; import ghidra.trace.model.Lifespan; import ghidra.trace.model.symbol.TraceLabelSymbol; import ghidra.trace.model.thread.TraceThread; @@ -47,21 +46,18 @@ import ghidra.util.exception.DuplicateNameException; */ @DBAnnotatedObjectInfo(version = 1) public class DBTraceLabelSymbol extends AbstractDBTraceSymbol - implements TraceLabelSymbol, DBTraceSpaceKey, DecodesAddresses { + implements TraceLabelSymbol, TraceSpaceMixin, DecodesAddresses { static final String TABLE_NAME = "Labels"; private static final byte PRIMARY_MASK = 0x10; private static final int PRIMARY_CLEAR = ~PRIMARY_MASK; static final String ADDRESS_COLUMN_NAME = "Address"; - static final String THREAD_COLUMN_NAME = "Thread"; static final String START_SNAP_COLUMN_NAME = "Start"; static final String END_SNAP_COLUMN_NAME = "End"; @DBAnnotatedColumn(ADDRESS_COLUMN_NAME) static DBObjectColumn ADDRESS_COLUMN; - @DBAnnotatedColumn(THREAD_COLUMN_NAME) - static DBObjectColumn THREAD_COLUMN; @DBAnnotatedColumn(START_SNAP_COLUMN_NAME) static DBObjectColumn START_SNAP_COLUMN; @DBAnnotatedColumn(END_SNAP_COLUMN_NAME) @@ -70,14 +66,11 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol // NOTE: Indexed in manager's range map @DBAnnotatedField(column = ADDRESS_COLUMN_NAME, codec = AddressDBFieldCodec.class) protected Address address = Address.NO_ADDRESS; - @DBAnnotatedField(column = THREAD_COLUMN_NAME) - protected long threadKey; @DBAnnotatedField(column = START_SNAP_COLUMN_NAME) protected long startSnap; @DBAnnotatedField(column = END_SNAP_COLUMN_NAME) protected long endSnap; - protected TraceThread thread; protected Lifespan lifespan; public DBTraceLabelSymbol(DBTraceSymbolManager manager, DBCachedObjectStore store, @@ -92,25 +85,22 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol return; } - thread = manager.threadManager.getThread(threadKey); lifespan = Lifespan.span(startSnap, endSnap); } - protected void set(Lifespan lifespan, TraceThread thread, Address address, String name, + protected void set(Lifespan lifespan, Address address, String name, DBTraceNamespaceSymbol parent, SourceType source) { this.name = name; this.parentID = parent.getID(); doSetSource(source); this.address = address; - this.threadKey = thread == null ? -1 : thread.getKey(); this.startSnap = lifespan.lmin(); this.endSnap = lifespan.lmax(); update(NAME_COLUMN, PARENT_COLUMN, START_SNAP_COLUMN, END_SNAP_COLUMN, FLAGS_COLUMN, - ADDRESS_COLUMN, THREAD_COLUMN); + ADDRESS_COLUMN); this.parent = parent; - this.thread = thread; this.lifespan = lifespan; } @@ -138,7 +128,7 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol this.lifespan = newLifespan; manager.trace.setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_LIFESPAN_CHANGED, - getSpace(), this, oldLifespan, newLifespan)); + getAddressSpace(), this, oldLifespan, newLifespan)); } } @@ -154,17 +144,7 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol @Override public TraceThread getThread() { - return thread; - } - - @Override - public int getFrameLevel() { - return 0; - } - - @Override - protected TraceAddressSpace getSpace() { - return this; + return TraceSpaceMixin.super.getThread(); } @Override @@ -175,7 +155,7 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol @Override protected void validateNameAndParent(String newName, DBTraceNamespaceSymbol newParent) throws DuplicateNameException { - manager.assertNotDuplicate(this, lifespan, thread, address, newName, newParent); + manager.assertNotDuplicate(this, lifespan, address, newName, newParent); } @Override @@ -186,10 +166,10 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol @Override public DBTraceCodeUnitAdapter getCodeUnit() { try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - DBTraceCodeSpace code = manager.trace.getCodeManager().get(this, false); + DBTraceCodeSpace code = manager.trace.getCodeManager().get(getAddressSpace(), false); if (code == null) { return manager.trace.getCodeManager() - .doCreateUndefinedUnit(startSnap, address, thread, getFrameLevel()); + .doCreateUndefinedUnit(startSnap, address, null, getFrameLevel()); } DBTraceCodeUnitAdapter cu = code.codeUnits().getContaining(startSnap, address); if (cu == null) { @@ -246,18 +226,18 @@ public class DBTraceLabelSymbol extends AbstractDBTraceSymbol // TODO: May be able to resolve "multiple overlapping primary" with priority instead boolean firedEvent = false; update(FLAGS_COLUMN); - for (DBTraceLabelSymbol other : manager.labels.getIntersecting(lifespan, thread, range, - false, true)) { + for (DBTraceLabelSymbol other : manager.labels.getIntersecting(lifespan, range, false, + true)) { if (other.doSetPrimary(false)) { other.update(AbstractDBTraceSymbol.FLAGS_COLUMN); manager.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.SYMBOL_PRIMARY_CHANGED, getSpace(), this, other, this)); + TraceEvents.SYMBOL_PRIMARY_CHANGED, getAddressSpace(), this, other, this)); firedEvent = true; } } if (!firedEvent) { manager.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.SYMBOL_PRIMARY_CHANGED, getSpace(), this)); + TraceEvents.SYMBOL_PRIMARY_CHANGED, getAddressSpace(), this)); } return true; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbolView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbolView.java index 654143d61f..06fe8e9bb2 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbolView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceLabelSymbolView.java @@ -4,9 +4,9 @@ * 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. @@ -20,7 +20,6 @@ import ghidra.program.model.symbol.*; import ghidra.trace.model.Lifespan; import ghidra.trace.model.symbol.TraceLabelSymbolView; import ghidra.trace.model.symbol.TraceNamespaceSymbol; -import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; @@ -35,26 +34,23 @@ public class DBTraceLabelSymbolView } @Override - public DBTraceLabelSymbol add(Lifespan lifespan, TraceThread thread, Address address, - String name, TraceNamespaceSymbol parent, SourceType source) + public DBTraceLabelSymbol add(Lifespan lifespan, Address address, String name, + TraceNamespaceSymbol parent, SourceType source) throws InvalidInputException, IllegalArgumentException { - // TODO: Allow frames other than 0? Don't allow threads at all? if (source == SourceType.DEFAULT) { throw new IllegalArgumentException(); } DBTraceSymbolManager.assertValidName(name); try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - manager.trace.getThreadManager().assertIsMine(thread); DBTraceNamespaceSymbol dbnsParent = manager.assertIsMine((Namespace) parent); - manager.assertValidThreadAddress(thread, address); DBTraceLabelSymbol label = store.create(); - label.set(lifespan, thread, address, name, dbnsParent, source); - manager.putID(lifespan, thread, address, label.getID()); + label.set(lifespan, address, name, dbnsParent, source); + manager.putID(lifespan, address, label.getID()); cacheForAt.notifyNewEntry(lifespan, address, label); - manager.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.SYMBOL_ADDED, label.getSpace(), label)); + manager.trace.setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_ADDED, + label.getAddressSpace(), label)); return label; } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceNamespaceSymbolView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceNamespaceSymbolView.java index 3d094f9ff7..aeac9f8aaa 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceNamespaceSymbolView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceNamespaceSymbolView.java @@ -4,9 +4,9 @@ * 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. @@ -47,8 +47,8 @@ public class DBTraceNamespaceSymbolView manager.assertUniqueName(name, dbnsParent); DBTraceNamespaceSymbol namespace = store.create(); namespace.set(name, dbnsParent, source); - manager.trace - .setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_ADDED, null, namespace)); + manager.trace.setChanged( + new TraceChangeRecord<>(TraceEvents.SYMBOL_ADDED, null, namespace)); return namespace; } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReference.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReference.java index eb9c41fc6a..e1dbedcfe6 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReference.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReference.java @@ -4,9 +4,9 @@ * 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. @@ -24,7 +24,6 @@ import ghidra.trace.database.DBTrace; import ghidra.trace.database.symbol.DBTraceReferenceSpace.DBTraceReferenceEntry; import ghidra.trace.model.Lifespan; import ghidra.trace.model.symbol.*; -import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; import ghidra.util.LockHold; @@ -41,16 +40,12 @@ public class DBTraceReference implements TraceReference { return ent.space.trace; } - public TraceThread getThread() { - return ent.space.getThread(); - } - @Override public void delete() { try (LockHold hold = LockHold.lock(ent.space.lock.writeLock())) { ent.doDelete(); - ent.space.trace.setChanged( - new TraceChangeRecord<>(TraceEvents.REFERENCE_DELETED, ent.space, ent, this)); + ent.space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.REFERENCE_DELETED, + ent.space.space, ent, this)); if (isPrimary()) { Collection remaining = ent.space.getReferencesFrom( getStartSnap(), getFromAddress(), getOperandIndex()); @@ -60,7 +55,7 @@ public class DBTraceReference implements TraceReference { DBTraceReference newPrimary = remaining.iterator().next(); newPrimary.ent.setPrimary(true); ent.space.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.REFERENCE_PRIMARY_CHANGED, ent.space, this, false, true)); + TraceEvents.REFERENCE_PRIMARY_CHANGED, ent.space.space, this, false, true)); } } } @@ -98,11 +93,12 @@ public class DBTraceReference implements TraceReference { if (oldPrimary != null) { oldPrimary.ent.setPrimary(false); ent.space.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.REFERENCE_PRIMARY_CHANGED, ent.space, oldPrimary, true, false)); + TraceEvents.REFERENCE_PRIMARY_CHANGED, ent.space.space, oldPrimary, true, + false)); } ent.setPrimary(true); ent.space.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.REFERENCE_PRIMARY_CHANGED, ent.space, this, false, true)); + TraceEvents.REFERENCE_PRIMARY_CHANGED, ent.space.space, this, false, true)); } } @@ -163,7 +159,7 @@ public class DBTraceReference implements TraceReference { } ent.setSymbolId(symbol.getID()); getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_ASSOCIATION_ADDED, - ent.space, dbSym, null, this)); + ent.space.space, dbSym, null, this)); } } @@ -176,7 +172,7 @@ public class DBTraceReference implements TraceReference { TraceSymbol oldSymbol = getTrace().getSymbolManager().getSymbolByID(ent.symbolId); ent.setSymbolId(-1); getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_ASSOCIATION_REMOVED, - ent.space, oldSymbol, this, null)); + ent.space.space, oldSymbol, this, null)); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceManager.java index de78ef2266..b8e3ba34fc 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceManager.java @@ -61,13 +61,7 @@ public class DBTraceReferenceManager extends AbstractDBTraceSpaceBasedManager s.getReferenceSources(span)).toList()); + spacesView.stream().map(s -> s.getReferenceSources(span)).toList()); } @Override public AddressSetView getReferenceDestinations(Lifespan span) { return new UnionAddressSetView( - memSpacesView.stream().map(s -> s.getReferenceDestinations(span)).toList()); + spacesView.stream().map(s -> s.getReferenceDestinations(span)).toList()); } @Override @@ -296,6 +290,6 @@ public class DBTraceReferenceManager extends AbstractDBTraceSpaceBasedManager getReferencesBySymbolId(long id) { // NOTE: Must include register spaces, since this API is not public // Only accessed via Symbol, for which it makes sense to include ALL refs. - return delegateCollection(allSpacesView, m -> m.getReferencesBySymbolId(id)); + return delegateCollection(spacesView, m -> m.getReferencesBySymbolId(id)); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java index 1d30e144eb..c15b7f94b4 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java @@ -42,7 +42,6 @@ import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.symbol.TraceReference; import ghidra.trace.model.symbol.TraceReferenceSpace; -import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; import ghidra.util.*; @@ -136,8 +135,8 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS @DBAnnotatedColumn(FLAGS_COLUMN_NAME) static DBObjectColumn FLAGS_COLUMN; - public static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + public static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField( @@ -228,11 +227,11 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS if (oldSymbol != null) { space.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.SYMBOL_ASSOCIATION_REMOVED, space, oldSymbol, ref)); + TraceEvents.SYMBOL_ASSOCIATION_REMOVED, space.space, oldSymbol, ref)); } if (newSymbol != null) { space.trace.setChanged(new TraceChangeRecord<>( - TraceEvents.SYMBOL_ASSOCIATION_ADDED, space, newSymbol, ref)); + TraceEvents.SYMBOL_ASSOCIATION_ADDED, space.space, newSymbol, ref)); } } @@ -288,8 +287,8 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS @DBAnnotatedColumn(REF_SPACE_COLUMN_NAME) static DBObjectColumn REF_SPACE_COLUMN; - public static String tableName(AddressSpace space, long threadKey, int frameLevel) { - return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, frameLevel); + public static String tableName(AddressSpace space) { + return DBTraceUtils.tableName(TABLE_NAME, space); } @DBAnnotatedField(column = REF_SPACE_COLUMN_NAME) @@ -331,8 +330,6 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS protected final DBTraceReferenceManager manager; protected final DBHandle dbh; protected final AddressSpace space; - protected final TraceThread thread; - protected final int frameLevel; protected final ReadWriteLock lock; protected final Language baseLanguage; protected final DBTrace trace; @@ -346,12 +343,10 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS protected final DBCachedObjectIndex xrefsByRefKey; public DBTraceReferenceSpace(DBTraceReferenceManager manager, DBHandle dbh, AddressSpace space, - DBTraceSpaceEntry ent, TraceThread thread) throws VersionException, IOException { + DBTraceSpaceEntry ent) throws VersionException, IOException { this.manager = manager; this.dbh = dbh; this.space = space; - this.thread = thread; - this.frameLevel = ent.getFrameLevel(); this.lock = manager.getLock(); this.baseLanguage = manager.getBaseLanguage(); this.trace = manager.getTrace(); @@ -360,18 +355,15 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - long threadKey = ent.getThreadKey(); - int frameLevel = ent.getFrameLevel(); this.referenceMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceReferenceEntry.tableName(space, threadKey, frameLevel), factory, lock, space, - thread, frameLevel, DBTraceReferenceEntry.class, - (t, s, r) -> new DBTraceReferenceEntry(this, t, s, r)); + DBTraceReferenceEntry.tableName(space), trace, factory, lock, space, + DBTraceReferenceEntry.class, (t, s, r) -> new DBTraceReferenceEntry(this, t, s, r)); this.refsBySymbolId = referenceMapSpace.getUserIndex(long.class, DBTraceReferenceEntry.SYMBOL_ID_COLUMN); this.xrefMapSpace = new DBTraceAddressSnapRangePropertyMapSpace<>( - DBTraceXRefEntry.tableName(space, threadKey, frameLevel), factory, lock, space, thread, - frameLevel, DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r)); + DBTraceXRefEntry.tableName(space), trace, factory, lock, space, + DBTraceXRefEntry.class, (t, s, r) -> new DBTraceXRefEntry(this, t, s, r)); this.xrefsByRefKey = xrefMapSpace.getUserIndex(long.class, DBTraceXRefEntry.REF_KEY_COLUMN); } @@ -404,21 +396,16 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS throw new AssertionError(); // The entry must exist (unless database is corrupt) } + @Override + public DBTrace getTrace() { + return trace; + } + @Override public AddressSpace getAddressSpace() { return space; } - @Override - public TraceThread getThread() { - return thread; - } - - @Override - public int getFrameLevel() { - return frameLevel; - } - @Override public DBTraceReference addReference(TraceReference reference) { return addReference(reference.getLifespan(), reference); @@ -692,8 +679,9 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS if (ref.getLifespan().lmin() < otherStartSnap) { Lifespan oldSpan = ref.getLifespan(); ref.setEndSnap(otherStartSnap - 1); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.REFERENCE_LIFESPAN_CHANGED, this, - ref.ref, oldSpan, ref.getLifespan())); + trace.setChanged(new TraceChangeRecord<>( + TraceEvents.REFERENCE_LIFESPAN_CHANGED, space, ref.ref, oldSpan, + ref.getLifespan())); } else { ref.ref.delete(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolManager.java index 40471ff567..8a9e3c15b6 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolManager.java @@ -4,9 +4,9 @@ * 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. @@ -36,7 +36,6 @@ import ghidra.trace.database.data.DBTraceDataTypeManager; import ghidra.trace.database.map.*; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.AbstractDBTraceAddressSnapRangePropertyMapData; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; -import ghidra.trace.database.space.DBTraceSpaceKey; import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; @@ -139,7 +138,10 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager @DBAnnotatedColumn(STORAGE_COLUMN_NAME) static DBObjectColumn STORAGE_COLUMN; - @DBAnnotatedField(column = STORAGE_COLUMN_NAME, indexed = true, codec = VariableStorageDBFieldCodec.class) + @DBAnnotatedField( + column = STORAGE_COLUMN_NAME, + indexed = true, + codec = VariableStorageDBFieldCodec.class) private VariableStorage storage; protected final DBTraceSymbolManager manager; @@ -516,29 +518,22 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager if (symbol.getAddress().isMemoryAddress()) { delID(thread, symbol.getAddress().getAddressSpace(), symbol.getID()); } - // TODO: Remove from other space maps, once implemented. - trace.setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_DELETED, symbol.getSpace(), - symbol, null, null)); + trace.setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_DELETED, + symbol.getAddressSpace(), symbol, null, null)); return true; } - protected void putID(Lifespan lifespan, TraceThread thread, Address address, long id) { - idMap.get(DBTraceSpaceKey.create(address.getAddressSpace(), thread, 0), true) - .put(address, lifespan, id); - // TODO: Add to ancestors' too? - // NOTE: Might be hard to remove because of overlaps + protected void putID(Lifespan lifespan, Address address, long id) { + idMap.get(address.getAddressSpace(), true).put(address, lifespan, id); } protected void putID(Lifespan lifespan, TraceThread thread, AddressRange rng, long id) { - idMap.get(DBTraceSpaceKey.create(rng.getAddressSpace(), thread, 0), true) - .put(rng, lifespan, id); - // TODO: Add to ancestors' too? - // NOTE: Might be hard to remove because of overlaps + idMap.get(rng.getAddressSpace(), true).put(rng, lifespan, id); } protected void delID(TraceThread thread, AddressSpace addressSpace, long id) { DBTraceAddressSnapRangePropertyMapSpace space = - idMap.get(DBTraceSpaceKey.create(addressSpace, thread, 0), false); + idMap.get(addressSpace, false); if (space == null) { return; } @@ -550,10 +545,10 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager } protected void assertNotDuplicate(AbstractDBTraceSymbol exclude, Lifespan lifespan, - TraceThread thread, Address address, String name, DBTraceNamespaceSymbol parent) + Address address, String name, DBTraceNamespaceSymbol parent) throws DuplicateNameException { if (address.isMemoryAddress()) { - for (AbstractDBTraceSymbol duplicate : labels.getIntersecting(lifespan, thread, + for (AbstractDBTraceSymbol duplicate : labels.getIntersecting(lifespan, new AddressRangeImpl(address, address), false, true)) { if (duplicate == exclude) { continue; @@ -587,7 +582,7 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager } Collection result = new ArrayList<>(); for (DBTraceAddressSnapRangePropertyMapSpace space : idMap - .getActiveMemorySpaces()) { + .getActiveSpaces()) { result.addAll( space.reduce(TraceAddressSnapRangeQuery.added(from, to, space.getAddressSpace())) .values()); @@ -602,7 +597,7 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager } Collection result = new ArrayList<>(); for (DBTraceAddressSnapRangePropertyMapSpace space : idMap - .getActiveMemorySpaces()) { + .getActiveSpaces()) { result.addAll( space.reduce(TraceAddressSnapRangeQuery.removed(from, to, space.getAddressSpace())) .values()); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesWithLocationView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesWithLocationView.java index 52235da920..320003ded1 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesWithLocationView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesWithLocationView.java @@ -4,9 +4,9 @@ * 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. @@ -22,12 +22,10 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapSpace; import ghidra.trace.database.map.DBTraceAddressSnapRangePropertyMapTree.TraceAddressSnapRangeQuery; -import ghidra.trace.database.space.DBTraceSpaceKey; import ghidra.trace.database.symbol.DBTraceSymbolManager.DBTraceSymbolIDEntry; import ghidra.trace.model.Lifespan; import ghidra.trace.model.symbol.TraceNamespaceSymbol; import ghidra.trace.model.symbol.TraceSymbolWithLocationView; -import ghidra.trace.model.thread.TraceThread; import ghidra.util.LazyCollection; import ghidra.util.LockHold; import ghidra.util.database.spatial.rect.Rectangle2DDirection; @@ -52,11 +50,11 @@ public class DBTraceSymbolMultipleTypesWithLocationView p : getParts()) { - T symbol = p.getChildWithNameAt(name, snap, thread, address, parent); + T symbol = p.getChildWithNameAt(name, snap, address, parent); if (symbol != null) { return symbol; } @@ -66,23 +64,20 @@ public class DBTraceSymbolMultipleTypesWithLocationView getAt(long snap, TraceThread thread, Address address, + public Collection getAt(long snap, Address address, boolean includeDynamicSymbols) { return getParts().stream() - .flatMap(p -> p.getAt(snap, thread, address, includeDynamicSymbols).stream()) + .flatMap(p -> p.getAt(snap, address, includeDynamicSymbols).stream()) .toList(); } @Override - public Collection getIntersecting(Lifespan span, TraceThread thread, - AddressRange range, boolean includeDynamicSymbols, boolean forward) { + public Collection getIntersecting(Lifespan span, AddressRange range, + boolean includeDynamicSymbols, boolean forward) { // NOTE: Do not use Catenated collection, so that the order is by address. try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - manager.trace.getThreadManager().assertIsMine(thread); - manager.assertValidThreadAddress(thread, range.getMinAddress()); // Only examines space DBTraceAddressSnapRangePropertyMapSpace space = - manager.idMap.get(DBTraceSpaceKey.create(range.getAddressSpace(), thread, 0), - false); + manager.idMap.get(range.getAddressSpace(), false); if (space == null) { return Collections.emptyList(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObject.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObject.java index ee33e5c267..9e04d21155 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObject.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObject.java @@ -23,6 +23,7 @@ import java.util.stream.Stream; import db.DBRecord; import db.StringField; +import ghidra.program.model.address.*; import ghidra.trace.database.DBTrace; import ghidra.trace.database.target.CachePerDBTraceObject.Cached; import ghidra.trace.database.target.DBTraceObjectValue.ValueLifespanSetter; @@ -669,6 +670,14 @@ public class DBTraceObject extends DBAnnotatedObject implements TraceObject { } } + static AddressSpace spaceForValue(Object value) { + return switch (value) { + case Address address -> address.getAddressSpace(); + case AddressRange range -> range.getAddressSpace(); + default -> null; + }; + } + @Override public TraceObjectValue setValue(Lifespan lifespan, String key, Object value) { return setValue(lifespan, key, value, ConflictResolution.TRUNCATE); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectInterface.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectInterface.java index 302d29e042..90c9107c1c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectInterface.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectInterface.java @@ -15,9 +15,7 @@ */ package ghidra.trace.database.target; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRange; -import ghidra.trace.database.space.DBTraceSpaceKey.DefaultDBTraceSpaceKey; +import ghidra.program.model.address.AddressSpace; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan.DefaultLifeSet; import ghidra.trace.model.Lifespan.LifeSet; @@ -78,7 +76,7 @@ public interface DBTraceObjectInterface extends TraceObjectInterface, TraceUniqu // Extension point } - protected TraceAddressSpace getSpace(LifeSet life) { + protected AddressSpace getSpace(LifeSet life) { if (life.isEmpty()) { return null; } @@ -183,21 +181,12 @@ public interface DBTraceObjectInterface extends TraceObjectInterface, TraceUniqu */ TraceChangeRecord translateEvent(TraceChangeRecord rec); - static TraceAddressSpace spaceForValue(TraceObject object, long snap, String key) { + static AddressSpace spaceForValue(TraceObject object, long snap, String key) { TraceObjectValue val = object.getAttribute(snap, key); - if (val == null) { - return null; - } - if (val.getValue() instanceof Address address) { - return new DefaultDBTraceSpaceKey(null, address.getAddressSpace(), 0); - } - if (val.getValue() instanceof AddressRange range) { - return new DefaultDBTraceSpaceKey(null, range.getAddressSpace(), 0); - } - return null; + return val == null ? null : DBTraceObject.spaceForValue(val.getValue()); } - default TraceAddressSpace spaceForValue(long snap, String key) { + default AddressSpace spaceForValue(long snap, String key) { return spaceForValue(getObject(), snap, key); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectManager.java index 8a04ad533d..36ef72db53 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectManager.java @@ -31,19 +31,19 @@ import ghidra.program.model.address.*; import ghidra.program.model.lang.Language; import ghidra.trace.database.DBTrace; import ghidra.trace.database.DBTraceManager; -import ghidra.trace.database.breakpoint.DBTraceObjectBreakpointLocation; -import ghidra.trace.database.module.TraceObjectSection; +import ghidra.trace.database.breakpoint.DBTraceBreakpointLocation; import ghidra.trace.database.target.DBTraceObjectValueRStarTree.DBTraceObjectValueMap; import ghidra.trace.database.target.ValueSpace.EntryKeyDimension; import ghidra.trace.database.target.visitors.SuccessorsRelativeVisitor; -import ghidra.trace.database.thread.DBTraceObjectThread; +import ghidra.trace.database.thread.DBTraceThread; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.memory.*; -import ghidra.trace.model.modules.TraceObjectModule; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.modules.TraceModule; +import ghidra.trace.model.modules.TraceSection; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.*; import ghidra.trace.model.target.DuplicateKeyException; import ghidra.trace.model.target.TraceObject.ConflictResolution; @@ -51,7 +51,6 @@ import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.path.*; import ghidra.trace.model.target.schema.*; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; @@ -274,6 +273,7 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager DBTraceObjectSchemaEntry schemaEntry = schemaStore.create(0); schemaEntry.set(schema); rootSchema = schema; + schemasByInterface.clear(); } protected void emitValueCreated(DBTraceObject parent, DBTraceObjectValue entry) { @@ -467,7 +467,7 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager public Stream queryAllInterface(Lifespan span, Class iface) { if (rootSchema == null) { - throw new IllegalStateException("There is no schema. Create a root object."); + return Stream.of(); } PathFilter filter = rootSchema.searchFor(iface, true); return getValuePaths(span, filter).filter(p -> { @@ -527,12 +527,16 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager invalidateObjectsContainingCache(); } - public boolean hasSchema() { - return rootSchema != null; + @Override + public TraceObjectSchema requireRootSchema() { + if (rootSchema == null) { + throw new IllegalStateException("The root object has not been created"); + } + return rootSchema; } protected I doAddWithInterface(KeyPath path, Class iface) { - TraceObjectSchema schema = rootSchema.getSuccessorSchema(path); + TraceObjectSchema schema = requireRootSchema().getSuccessorSchema(path); if (!schema.getInterfaces().contains(iface)) { throw new BadSchemaException("Schema " + schema + " at '" + path + "' does not provide interface " + iface.getSimpleName()); @@ -693,27 +697,25 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager } } - public TraceObjectBreakpointLocation addBreakpoint(String path, Lifespan lifespan, - AddressRange range, Collection threads, - Collection kinds, boolean enabled, String comment) - throws DuplicateNameException { + public TraceBreakpointLocation addBreakpoint(String path, Lifespan lifespan, AddressRange range, + Collection threads, Collection kinds, boolean enabled, + String comment) throws DuplicateNameException { // First verify that the schema accommodates - KeyPath specPath = getRootSchema().searchForAncestor(TraceObjectBreakpointSpec.class, - KeyPath.parse(path)); + KeyPath specPath = + requireRootSchema().searchForAncestor(TraceBreakpointSpec.class, KeyPath.parse(path)); if (specPath == null) { throw new IllegalStateException("The schema does not provide an implicit " + "breakpoint specification on the given path."); } try (LockHold hold = trace.lockWrite()) { - DBTraceObjectBreakpointLocation loc = - (DBTraceObjectBreakpointLocation) doAddWithInterface(path, - TraceObjectBreakpointLocation.class); + DBTraceBreakpointLocation loc = + (DBTraceBreakpointLocation) doAddWithInterface(path, TraceBreakpointLocation.class); loc.setName(lifespan, path); loc.setRange(lifespan, range); loc.setEnabled(lifespan, enabled); loc.setComment(lifespan, comment); - TraceObjectBreakpointSpec spec = loc.getOrCreateSpecification(); + TraceBreakpointSpec spec = loc.getOrCreateSpecification(); // NB. Ignore threads. I'd like to deprecate that field, anyway. spec.setKinds(lifespan, kinds); loc.getObject().insert(lifespan, ConflictResolution.DENY); @@ -724,13 +726,10 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager } } - public TraceObjectMemoryRegion addMemoryRegion(String path, Lifespan lifespan, - AddressRange range, Collection flags) - throws TraceOverlappedRegionException { + public TraceMemoryRegion addMemoryRegion(String path, Lifespan lifespan, AddressRange range, + Collection flags) throws TraceOverlappedRegionException { try (LockHold hold = trace.lockWrite()) { - TraceObjectMemoryRegion region = - doAddWithInterface(path, TraceObjectMemoryRegion.class); - region.setName(lifespan, path); + TraceMemoryRegion region = doAddWithInterface(path, TraceMemoryRegion.class); region.setRange(lifespan, range); region.setFlags(lifespan, flags); region.getObject().insert(lifespan, ConflictResolution.TRUNCATE); @@ -738,11 +737,13 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager } } - public TraceObjectModule addModule(String path, String name, Lifespan lifespan, + public TraceModule addModule(String path, String name, Lifespan lifespan, AddressRange range) throws DuplicateNameException { try (LockHold hold = trace.lockWrite()) { - TraceObjectModule module = doAddWithInterface(path, TraceObjectModule.class); - module.setName(lifespan, name); + TraceModule module = doAddWithInterface(path, TraceModule.class); + if (name != null) { + module.setName(lifespan, name); + } module.setRange(lifespan, range); module.getObject().insert(lifespan, ConflictResolution.DENY); return module; @@ -752,11 +753,13 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager } } - public TraceObjectSection addSection(String path, String name, Lifespan lifespan, + public TraceSection addSection(String path, String name, Lifespan lifespan, AddressRange range) throws DuplicateNameException { try (LockHold hold = trace.lockWrite()) { - TraceObjectSection section = doAddWithInterface(path, TraceObjectSection.class); - section.setName(lifespan, name); + TraceSection section = doAddWithInterface(path, TraceSection.class); + if (name != null) { + section.setName(lifespan, name); + } section.setRange(lifespan, range); section.getObject().insert(lifespan, ConflictResolution.DENY); return section; @@ -766,17 +769,17 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager } } - public TraceObjectStack addStack(KeyPath path, long snap) { + public TraceStack addStack(KeyPath path, long snap) { try (LockHold hold = trace.lockWrite()) { - TraceObjectStack stack = doAddWithInterface(path, TraceObjectStack.class); + TraceStack stack = doAddWithInterface(path, TraceStack.class); stack.getObject().insert(Lifespan.at(snap), ConflictResolution.DENY); return stack; } } - public TraceObjectStackFrame addStackFrame(KeyPath path, long snap) { + public TraceStackFrame addStackFrame(KeyPath path, long snap) { try (LockHold hold = trace.lockWrite()) { - TraceObjectStackFrame frame = doAddWithInterface(path, TraceObjectStackFrame.class); + TraceStackFrame frame = doAddWithInterface(path, TraceStackFrame.class); frame.getObject().insert(Lifespan.at(snap), ConflictResolution.DENY); return frame; } @@ -796,11 +799,11 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager "A thread having path '" + path + "' already exists within an overlapping snap"); } - public TraceObjectThread addThread(String path, String display, Lifespan lifespan) + public TraceThread addThread(String path, String display, Lifespan lifespan) throws DuplicateNameException { try (LockHold hold = trace.lockWrite()) { checkDuplicateThread(path, lifespan); - TraceObjectThread thread = doAddWithInterface(path, TraceObjectThread.class); + TraceThread thread = doAddWithInterface(path, TraceThread.class); thread.setName(lifespan.withMax(Lifespan.DOMAIN.lmax()), display); thread.getObject().insert(lifespan, ConflictResolution.DENY); return thread; @@ -811,7 +814,10 @@ public class DBTraceObjectManager implements TraceObjectManager, DBTraceManager } public TraceThread assertMyThread(TraceThread thread) { - if (!(thread instanceof DBTraceObjectThread dbThread)) { + if (thread == null) { + return null; + } + if (!(thread instanceof DBTraceThread dbThread)) { throw new AssertionError("Thread " + thread + " is not an object in this trace"); } if (!checkMyObject(dbThread.getObject())) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValue.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValue.java index 3bf5a517e0..0a1e2e1c2b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValue.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValue.java @@ -23,8 +23,9 @@ import ghidra.trace.database.target.visitors.TreeTraversal; import ghidra.trace.database.target.visitors.TreeTraversal.Visitor; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; -import ghidra.trace.model.target.*; import ghidra.trace.model.target.TraceObject.ConflictResolution; +import ghidra.trace.model.target.TraceObjectValPath; +import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.util.TraceChangeRecord; import ghidra.trace.util.TraceEvents; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectActivatable.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectActivatable.java index 4034c82952..b2f6137542 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectActivatable.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectActivatable.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectActivatable; +import ghidra.trace.model.target.iface.TraceActivatable; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectActivatable implements TraceObjectActivatable, DBTraceObjectInterface { +public class DBTraceObjectActivatable implements TraceActivatable, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectActivatable(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectAggregate.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectAggregate.java index 2aa5e9368d..110a319a6d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectAggregate.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectAggregate.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectAggregate; +import ghidra.trace.model.target.iface.TraceAggregate; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectAggregate implements TraceObjectAggregate, DBTraceObjectInterface { +public class DBTraceObjectAggregate implements TraceAggregate, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectAggregate(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEnvironment.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEnvironment.java index 2dcf403740..9a0c7aed3a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEnvironment.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEnvironment.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectEnvironment; +import ghidra.trace.model.target.iface.TraceEnvironment; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectEnvironment implements TraceObjectEnvironment, DBTraceObjectInterface { +public class DBTraceObjectEnvironment implements TraceEnvironment, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectEnvironment(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEventScope.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEventScope.java index 83024bfc3d..665f1f8d1a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEventScope.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectEventScope.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectEventScope; +import ghidra.trace.model.target.iface.TraceEventScope; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectEventScope implements TraceObjectEventScope, DBTraceObjectInterface { +public class DBTraceObjectEventScope implements TraceEventScope, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectEventScope(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectExecutionStateful.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectExecutionStateful.java index 806b22c818..cda8bad5ba 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectExecutionStateful.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectExecutionStateful.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectExecutionStateful; +import ghidra.trace.model.target.iface.TraceExecutionStateful; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectExecutionStateful implements TraceObjectExecutionStateful, DBTraceObjectInterface { +public class DBTraceObjectExecutionStateful implements TraceExecutionStateful, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectExecutionStateful(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectFocusScope.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectFocusScope.java index ab50ba3232..7dc8556672 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectFocusScope.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectFocusScope.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectFocusScope; +import ghidra.trace.model.target.iface.TraceFocusScope; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectFocusScope implements TraceObjectFocusScope, DBTraceObjectInterface { +public class DBTraceObjectFocusScope implements TraceFocusScope, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectFocusScope(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectMethod.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectMethod.java index aaec7e38c3..520ee4e6a2 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectMethod.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectMethod.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectMethod; +import ghidra.trace.model.target.iface.TraceMethod; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectMethod implements TraceObjectMethod, DBTraceObjectInterface { +public class DBTraceObjectMethod implements TraceMethod, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectMethod(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectTogglable.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectTogglable.java index 783d2a4e13..d19ffad009 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectTogglable.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/iface/DBTraceObjectTogglable.java @@ -18,10 +18,10 @@ package ghidra.trace.database.target.iface; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectTogglable; +import ghidra.trace.model.target.iface.TraceTogglable; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectTogglable implements TraceObjectTogglable, DBTraceObjectInterface { +public class DBTraceObjectTogglable implements TraceTogglable, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectTogglable(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectProcess.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectProcess.java index adcc423a04..28cea05924 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectProcess.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectProcess.java @@ -18,10 +18,10 @@ package ghidra.trace.database.thread; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.TraceObjectProcess; +import ghidra.trace.model.thread.TraceProcess; import ghidra.trace.util.TraceChangeRecord; -public class DBTraceObjectProcess implements TraceObjectProcess, DBTraceObjectInterface { +public class DBTraceObjectProcess implements TraceProcess, DBTraceObjectInterface { private final DBTraceObject object; public DBTraceObjectProcess(DBTraceObject object) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectThread.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectThread.java deleted file mode 100644 index 7bde0a0c08..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceObjectThread.java +++ /dev/null @@ -1,161 +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.thread; - -import java.util.*; - -import ghidra.trace.database.target.DBTraceObject; -import ghidra.trace.database.target.DBTraceObjectInterface; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.Trace; -import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; -import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.model.thread.TraceObjectThread; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.*; -import ghidra.util.LockHold; - -public class DBTraceObjectThread implements TraceObjectThread, DBTraceObjectInterface { - - protected class ThreadChangeTranslator extends Translator { - private static final Map> KEYS_BY_SCHEMA = - new WeakHashMap<>(); - - private final Set keys; - - protected ThreadChangeTranslator(DBTraceObject object, TraceThread iface) { - super(null, object, iface); - TraceObjectSchema schema = object.getSchema(); - synchronized (KEYS_BY_SCHEMA) { - keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( - s.checkAliasedAttribute(KEY_COMMENT), - s.checkAliasedAttribute(KEY_DISPLAY))); - } - } - - @Override - protected TraceEvent getAddedType() { - return TraceEvents.THREAD_ADDED; - } - - @Override - protected TraceEvent getLifespanChangedType() { - return TraceEvents.THREAD_LIFESPAN_CHANGED; - } - - @Override - protected TraceEvent getChangedType() { - return TraceEvents.THREAD_CHANGED; - } - - @Override - protected boolean appliesToKey(String key) { - return keys.contains(key); - } - - @Override - protected TraceEvent getDeletedType() { - return TraceEvents.THREAD_DELETED; - } - } - - private final DBTraceObject object; - private final ThreadChangeTranslator translator; - - public DBTraceObjectThread(DBTraceObject object) { - this.object = object; - - translator = new ThreadChangeTranslator(object, this); - } - - @Override - public DBTraceObject getObject() { - return object; - } - - @Override - public Trace getTrace() { - return object.getTrace(); - } - - @Override - public long getKey() { - return object.getKey(); - } - - @Override - public String getPath() { - return object.getCanonicalPath().toString(); - } - - @Override - public String getName(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, ""); - } - - @Override - public void setName(Lifespan lifespan, String name) { - object.setValue(lifespan, KEY_DISPLAY, name); - } - - @Override - public void setName(long snap, String name) { - try (LockHold hold = object.getTrace().lockWrite()) { - setName(Lifespan.nowOn(snap), name); - } - } - - @Override - public void setComment(long snap, String comment) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.setValue(Lifespan.nowOn(snap), KEY_COMMENT, comment); - } - } - - @Override - public String getComment(long snap) { - return TraceObjectInterfaceUtils.getValue(object, snap, KEY_COMMENT, String.class, ""); - } - - @Override - public void delete() { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.ALL); - } - } - - @Override - public void remove(long snap) { - try (LockHold hold = object.getTrace().lockWrite()) { - object.removeTree(Lifespan.nowOn(snap)); - } - } - - @Override - public boolean isValid(long snap) { - return object.isAlive(snap); - } - - @Override - public boolean isAlive(Lifespan span) { - return object.isAlive(span); - } - - @Override - public TraceChangeRecord translateEvent(TraceChangeRecord rec) { - return translator.translate(rec); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThread.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThread.java index 2e715beded..473c119fc8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThread.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThread.java @@ -15,163 +15,146 @@ */ package ghidra.trace.database.thread; -import java.io.IOException; +import java.util.*; -import db.DBRecord; +import ghidra.trace.database.target.DBTraceObject; +import ghidra.trace.database.target.DBTraceObjectInterface; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; +import ghidra.trace.model.target.info.TraceObjectInterfaceUtils; +import ghidra.trace.model.target.schema.TraceObjectSchema; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; +import ghidra.trace.util.*; import ghidra.util.LockHold; -import ghidra.util.database.*; -import ghidra.util.database.annot.*; -@DBAnnotatedObjectInfo(version = 0) -public class DBTraceThread extends DBAnnotatedObject implements TraceThread { - protected static final String TABLE_NAME = "Threads"; +public class DBTraceThread implements TraceThread, DBTraceObjectInterface { - static final String PATH_COLUMN_NAME = "Path"; - static final String NAME_COLUMN_NAME = "Name"; - static final String CREATION_SNAP_COLUMN_NAME = "CreatedAt"; - static final String DESTRUCTION_SNAP_COLUMN_NAME = "DestroyedAt"; - static final String COMMENT_COLUMN_NAME = "Comment"; + protected class ThreadChangeTranslator extends Translator { + private static final Map> KEYS_BY_SCHEMA = + new WeakHashMap<>(); - @DBAnnotatedColumn(PATH_COLUMN_NAME) - static DBObjectColumn PATH_COLUMN; - @DBAnnotatedColumn(NAME_COLUMN_NAME) - static DBObjectColumn NAME_COLUMN; - @DBAnnotatedColumn(CREATION_SNAP_COLUMN_NAME) - static DBObjectColumn CREATION_SNAP_COLUMN; - @DBAnnotatedColumn(DESTRUCTION_SNAP_COLUMN_NAME) - static DBObjectColumn DESTRUCTION_SNAP_COLUMN; - @DBAnnotatedColumn(COMMENT_COLUMN_NAME) - static DBObjectColumn COMMENT_COLUMN; + private final Set keys; - @DBAnnotatedField(column = PATH_COLUMN_NAME, indexed = true) - private String path; - @DBAnnotatedField(column = NAME_COLUMN_NAME) - private String name; - @DBAnnotatedField(column = CREATION_SNAP_COLUMN_NAME) - private long creationSnap; - @DBAnnotatedField(column = DESTRUCTION_SNAP_COLUMN_NAME) - private long destructionSnap; - @DBAnnotatedField(column = COMMENT_COLUMN_NAME) - private String comment; - - public final DBTraceThreadManager manager; - - private Lifespan lifespan; - - protected DBTraceThread(DBTraceThreadManager manager, DBCachedObjectStore store, - DBRecord record) { - super(store, record); - this.manager = manager; - } - - public void set(String path, String name, Lifespan lifespan) { - this.path = path; - this.name = name; - this.creationSnap = lifespan.lmin(); - this.destructionSnap = lifespan.lmax(); - update(PATH_COLUMN, NAME_COLUMN, CREATION_SNAP_COLUMN, DESTRUCTION_SNAP_COLUMN); - - this.lifespan = lifespan; - } - - @Override - protected void fresh(boolean created) throws IOException { - if (created) { - return; + protected ThreadChangeTranslator(DBTraceObject object, TraceThread iface) { + super(null, object, iface); + TraceObjectSchema schema = object.getSchema(); + synchronized (KEYS_BY_SCHEMA) { + keys = KEYS_BY_SCHEMA.computeIfAbsent(schema, s -> Set.of( + s.checkAliasedAttribute(KEY_COMMENT), + s.checkAliasedAttribute(KEY_DISPLAY))); + } } - lifespan = Lifespan.span(creationSnap, destructionSnap); + + @Override + protected TraceEvent getAddedType() { + return TraceEvents.THREAD_ADDED; + } + + @Override + protected TraceEvent getLifespanChangedType() { + return TraceEvents.THREAD_LIFESPAN_CHANGED; + } + + @Override + protected TraceEvent getChangedType() { + return TraceEvents.THREAD_CHANGED; + } + + @Override + protected boolean appliesToKey(String key) { + return keys.contains(key); + } + + @Override + protected TraceEvent getDeletedType() { + return TraceEvents.THREAD_DELETED; + } + } + + private final DBTraceObject object; + private final ThreadChangeTranslator translator; + + public DBTraceThread(DBTraceObject object) { + this.object = object; + + translator = new ThreadChangeTranslator(object, this); } @Override - public String toString() { - return "TraceThread: " + getName(0); - } - - protected void doSetLifespan(Lifespan lifespan) { - this.creationSnap = lifespan.lmin(); - this.destructionSnap = lifespan.lmax(); - update(CREATION_SNAP_COLUMN, DESTRUCTION_SNAP_COLUMN); - - this.lifespan = lifespan; + public DBTraceObject getObject() { + return object; } @Override public Trace getTrace() { - return manager.trace; + return object.getTrace(); + } + + @Override + public long getKey() { + return object.getKey(); } @Override public String getPath() { - try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - return path; - } + return object.getCanonicalPath().toString(); } @Override public String getName(long snap) { - try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - return name; - } + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_DISPLAY, String.class, ""); + } + + @Override + public void setName(Lifespan lifespan, String name) { + object.setValue(lifespan, KEY_DISPLAY, name); } @Override public void setName(long snap, String name) { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - this.name = name; - update(NAME_COLUMN); - manager.trace - .setChanged(new TraceChangeRecord<>(TraceEvents.THREAD_CHANGED, null, this)); + try (LockHold hold = object.getTrace().lockWrite()) { + setName(Lifespan.nowOn(snap), name); } } @Override public void setComment(long snap, String comment) { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - this.comment = comment; - update(COMMENT_COLUMN); - manager.trace - .setChanged(new TraceChangeRecord<>(TraceEvents.THREAD_CHANGED, null, this)); + try (LockHold hold = object.getTrace().lockWrite()) { + object.setValue(Lifespan.nowOn(snap), KEY_COMMENT, comment); } } @Override public String getComment(long snap) { - return comment; + return TraceObjectInterfaceUtils.getValue(object, snap, KEY_COMMENT, String.class, ""); } @Override public void delete() { - manager.deleteThread(this); + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.ALL); + } } @Override public void remove(long snap) { - try (LockHold hold = LockHold.lock(manager.lock.writeLock())) { - if (snap <= lifespan.lmin()) { - manager.deleteThread(this); - } - else if (snap <= lifespan.lmax()) { - doSetLifespan(lifespan.withMax(snap - 1)); - } + try (LockHold hold = object.getTrace().lockWrite()) { + object.removeTree(Lifespan.nowOn(snap)); } } @Override public boolean isValid(long snap) { - try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - return lifespan.contains(snap); - } + return object.isAlive(snap); } @Override public boolean isAlive(Lifespan span) { - try (LockHold hold = LockHold.lock(manager.lock.readLock())) { - return lifespan.intersects(span); - } + return object.isAlive(span); + } + + @Override + public TraceChangeRecord translateEvent(TraceChangeRecord rec) { + return translator.translate(rec); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThreadManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThreadManager.java index 0ba940b0cd..9d14e3c575 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThreadManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/thread/DBTraceThreadManager.java @@ -16,7 +16,7 @@ package ghidra.trace.database.thread; import java.io.IOException; -import java.util.*; +import java.util.Collection; import java.util.concurrent.locks.ReadWriteLock; import java.util.stream.Collectors; @@ -27,11 +27,9 @@ import ghidra.trace.database.DBTraceManager; import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.database.target.DBTraceObjectManager; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.thread.*; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceEvents; +import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.model.thread.TraceThreadManager; import ghidra.util.LockHold; -import ghidra.util.database.*; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; @@ -39,25 +37,14 @@ import ghidra.util.task.TaskMonitor; public class DBTraceThreadManager implements TraceThreadManager, DBTraceManager { protected final ReadWriteLock lock; protected final DBTrace trace; - protected final DBTraceObjectManager objectManager; - protected final DBCachedObjectStore threadStore; - protected final DBCachedObjectIndex threadsByPath; - public DBTraceThreadManager(DBHandle dbh, OpenMode openMode, ReadWriteLock lock, TaskMonitor monitor, DBTrace trace, DBTraceObjectManager objectManager) throws IOException, VersionException { this.lock = lock; this.trace = trace; - this.objectManager = objectManager; - - DBCachedObjectStoreFactory factory = trace.getStoreFactory(); - - threadStore = factory.getOrCreateCachedStore(DBTraceThread.TABLE_NAME, DBTraceThread.class, - (s, r) -> new DBTraceThread(this, s, r), true); - threadsByPath = threadStore.getIndex(String.class, DBTraceThread.PATH_COLUMN); } @Override @@ -67,41 +54,12 @@ public class DBTraceThreadManager implements TraceThreadManager, DBTraceManager @Override public void invalidateCache(boolean all) { - threadStore.invalidateCache(); + // NOTE: This is only a wrapper around the object manager } // Internal public TraceThread assertIsMine(TraceThread thread) { - if (thread == null) { - return null; - } - if (objectManager.hasSchema()) { - return objectManager.assertMyThread(thread); - } - if (!(thread instanceof DBTraceThread dbThread)) { - throw new IllegalArgumentException("Thread " + thread + " is not part of this trace"); - } - if (dbThread.manager != this) { - throw new IllegalArgumentException("Thread " + thread + " is not part of this trace"); - } - if (!getAllThreads().contains(dbThread)) { - throw new IllegalArgumentException("Thread " + thread + " is not part of this trace"); - } - return dbThread; - } - - protected void checkConflictingPath(DBTraceThread ignore, String path, Lifespan lifespan) - throws DuplicateNameException { - for (DBTraceThread pc : threadsByPath.get(path)) { - if (pc == ignore) { - continue; - } - if (!pc.isAlive(lifespan)) { - continue; - } - throw new DuplicateNameException( - "A thread having path '" + path + "' already exists within an overlapping snap"); - } + return objectManager.assertMyThread(thread); } @Override @@ -112,81 +70,35 @@ public class DBTraceThreadManager implements TraceThreadManager, DBTraceManager @Override public TraceThread addThread(String path, String display, Lifespan lifespan) throws DuplicateNameException { - if (objectManager.hasSchema()) { - return objectManager.addThread(path, display, lifespan); - } - DBTraceThread thread; - try (LockHold hold = LockHold.lock(lock.writeLock())) { - checkConflictingPath(null, path, lifespan); - thread = threadStore.create(); - thread.set(path, display, lifespan); - } - trace.setChanged(new TraceChangeRecord<>(TraceEvents.THREAD_ADDED, null, thread)); - return thread; + return objectManager.addThread(path, display, lifespan); } @Override public Collection getAllThreads() { - if (objectManager.hasSchema()) { - return objectManager.getAllObjects(TraceObjectThread.class); - } - return Collections.unmodifiableCollection(threadStore.asMap().values()); + return objectManager.getAllObjects(TraceThread.class); } @Override public Collection getThreadsByPath(String path) { - if (objectManager.hasSchema()) { - return objectManager.getObjectsByPath(path, TraceObjectThread.class); - } - return Collections.unmodifiableCollection(threadsByPath.get(path)); + return objectManager.getObjectsByPath(path, TraceThread.class); } @Override public TraceThread getLiveThreadByPath(long snap, String path) { - if (objectManager.hasSchema()) { - return objectManager.getObjectByPath(snap, path, TraceObjectThread.class); - } - try (LockHold hold = LockHold.lock(lock.readLock())) { - return threadsByPath.get(path) - .stream() - .filter(t -> t.isValid(snap)) - .findAny() - .orElse(null); - } + return objectManager.getObjectByPath(snap, path, TraceThread.class); } @Override public TraceThread getThread(long key) { - if (objectManager.hasSchema()) { - DBTraceObject object = objectManager.getObjectById(key); - return object == null ? null : object.queryInterface(TraceObjectThread.class); - } - return threadStore.getObjectAt(key); + DBTraceObject object = objectManager.getObjectById(key); + return object == null ? null : object.queryInterface(TraceThread.class); } @Override public Collection getLiveThreads(long snap) { - if (objectManager.hasSchema()) { - try (LockHold hold = LockHold.lock(lock.readLock())) { - return objectManager.queryAllInterface(Lifespan.at(snap), TraceObjectThread.class) - .collect(Collectors.toSet()); - } - } try (LockHold hold = LockHold.lock(lock.readLock())) { - // NOTE: Should be few enough threads that this is fast - Collection result = new LinkedHashSet<>(); - for (DBTraceThread thread : threadStore.asMap().values()) { - // Don't use .getLifespan().contains(snap). Exclude the destruction. - if (thread.isValid(snap)) { - result.add(thread); - } - } - return result; + return objectManager.queryAllInterface(Lifespan.at(snap), TraceThread.class) + .collect(Collectors.toSet()); } } - - public void deleteThread(DBTraceThread thread) { - threadStore.delete(thread); - trace.setChanged(new TraceChangeRecord<>(TraceEvents.THREAD_DELETED, null, thread)); - } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/time/DBTraceSnapshot.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/time/DBTraceSnapshot.java index 3cd9599ec2..809e5cbfda 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/time/DBTraceSnapshot.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/time/DBTraceSnapshot.java @@ -22,8 +22,7 @@ import ghidra.trace.database.target.DBTraceObject; import ghidra.trace.model.Trace; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; -import ghidra.trace.model.target.iface.TraceObjectEventScope; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.target.iface.TraceEventScope; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.schedule.TraceSchedule; @@ -157,18 +156,18 @@ public class DBTraceSnapshot extends DBAnnotatedObject implements TraceSnapshot if (root == null) { return null; } - if (!root.getSchema().getInterfaces().contains(TraceObjectEventScope.class)) { + if (!root.getSchema().getInterfaces().contains(TraceEventScope.class)) { return null; } TraceObjectValue eventAttr = - root.getAttribute(getKey(), TraceObjectEventScope.KEY_EVENT_THREAD); + root.getAttribute(getKey(), TraceEventScope.KEY_EVENT_THREAD); if (eventAttr == null) { return null; } if (!(eventAttr.getValue() instanceof TraceObject eventObj)) { return null; } - return eventObj.queryInterface(TraceObjectThread.class); + return eventObj.queryInterface(TraceThread.class); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/Trace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/Trace.java index 9e7fa16137..1e8c51a7b7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/Trace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/Trace.java @@ -20,7 +20,6 @@ import java.util.Collection; import javax.swing.Icon; import generic.theme.GIcon; -import ghidra.lifecycle.Transitional; import ghidra.program.model.address.AddressFactory; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.data.DataTypeManagerDomainObject; @@ -28,7 +27,7 @@ import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.Language; import ghidra.program.model.listing.Program; import ghidra.trace.model.bookmark.TraceBookmarkManager; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.breakpoint.TraceBreakpointManager; import ghidra.trace.model.context.TraceRegisterContextManager; import ghidra.trace.model.data.TraceBasedDataTypeManager; @@ -57,24 +56,13 @@ import ghidra.util.LockHold; * Conceptually, this is the same as a {@link Program}, but multiplied by a concrete dimension of * time and organized into {@link TraceSnapshot snapshots}. This also includes information about * other objects not ordinarily of concern for static analysis, for example, {@link TraceThread - * threads}, {@link TraceModule modules}, and {@link TraceBreakpoint breakpoints}. To view a + * threads}, {@link TraceModule modules}, and {@link TraceBreakpointLocation breakpoints}. To view a * specific snapshot and/or manipulate the trace as if it were a program, use * {@link #getProgramView()}. */ public interface Trace extends DataTypeManagerDomainObject { Icon TRACE_ICON = new GIcon("icon.content.handler.trace"); - /** - * TEMPORARY: An a/b switch while both table- (legacy) and object-mode traces are supported - * - * @param trace the trace, or null - * @return true if the trace is non-null and has no root schema - */ - @Transitional - public static boolean isLegacy(Trace trace) { - return trace != null && trace.getObjectManager().getRootSchema() == null; - } - public interface TraceProgramViewListener { void viewCreated(TraceProgramView view); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/bookmark/TraceBookmarkSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/bookmark/TraceBookmarkSpace.java index 95cfb674b3..4367395f53 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/bookmark/TraceBookmarkSpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/bookmark/TraceBookmarkSpace.java @@ -4,9 +4,9 @@ * 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. @@ -15,17 +15,24 @@ */ package ghidra.trace.model.bookmark; +import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.lang.Register; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.Trace; +import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.util.TraceRegisterUtils; public interface TraceBookmarkSpace extends TraceBookmarkOperations { + Trace getTrace(); + AddressSpace getAddressSpace(); default TraceBookmark addBookmark(Lifespan lifespan, Register register, TraceBookmarkType type, String category, String comment) { - return addBookmark(lifespan, register.getAddress(), type, category, comment); + TracePlatform host = getTrace().getPlatformManager().getHostPlatform(); + AddressRange range = host.getConventionalRegisterRange(getAddressSpace(), register); + return addBookmark(lifespan, range.getMinAddress(), type, category, comment); } default Iterable getBookmarksEnclosed(Lifespan lifespan, diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointCommon.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointCommon.java new file mode 100644 index 0000000000..bbf5ae1d40 --- /dev/null +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointCommon.java @@ -0,0 +1,156 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.trace.model.breakpoint; + +import ghidra.trace.model.*; +import ghidra.trace.model.target.iface.TraceObjectInterface; + +public interface TraceBreakpointCommon extends TraceUniqueObject, TraceObjectInterface { + // LATER?: Hit count + + /** + * Get the trace containing this breakpoint + * + * @return the trace + */ + Trace getTrace(); + + /** + * Get the "full name" of this breakpoint + * + *

+ * This is a name unique to this breakpoint, which may not be suitable for display on the + * screen. + * + * @return the path + */ + String getPath(); + + /** + * Set the "short name" of this breakpoint + * + *

+ * This should be a name suitable for display on the screen + * + * @param lifespan the span of time + * @param name the new name + */ + void setName(Lifespan lifespan, String name); + + /** + * Set the "short name" of this breakpoint + * + *

+ * This should be a name suitable for display on the screen + * + * @param snap the first effective snap + * @param name the new name + */ + void setName(long snap, String name); + + /** + * Get the "short name" of this breakpoint + * + *

+ * This defaults to the "full name," but can be modified via {@link #setName(long, String)} + * + * @param snap the snap + * @return the name + */ + String getName(long snap); + + /** + * Set whether this breakpoint was enabled or disabled + * + * @param lifespan the span of time + * @param enabled true if enabled, false if disabled + */ + void setEnabled(Lifespan lifespan, boolean enabled); + + /** + * Set whether this breakpoint was enabled or disabled + * + * @param snap the first effective snap + * @param enabled true if enabled, false if disabled + */ + void setEnabled(long snap, boolean enabled); + + /** + * Check whether this breakpoint is enabled or disabled at the given snap + * + * @param snap the snap + * @return true if enabled, false if disabled + */ + boolean isEnabled(long snap); + + /** + * Set a comment on this breakpoint + * + * @param lifespan the span of time + * @param comment the comment, possibly {@code null} + */ + void setComment(Lifespan lifespan, String comment); + + /** + * Set a comment on this breakpoint + * + * @param snap the snap + * @param comment the comment, possibly {@code null} + */ + void setComment(long snap, String comment); + + /** + * Get the comment on this breakpoint + * + * @param snap the snap + * @return the comment, possibly {@code null} + */ + String getComment(long snap); + + /** + * Remove this breakpoint from the given snap on + * + * @param snap the snap + */ + void remove(long snap); + + /** + * Delete this breakpoint from the trace + */ + void delete(); + + /** + * Check if the breakpoint is present at the given snapshot + * + *

+ * In object mode, a breakpoint's life may be disjoint, so checking if the snap occurs between + * creation and destruction is not quite sufficient. This method encapsulates validity. In + * object mode, it checks that the breakpoint object has a canonical parent at the given + * snapshot. In table mode, it checks that the lifespan contains the snap. + * + * @param snap the snapshot key + * @return true if valid, false if not + */ + boolean isValid(long snap); + + /** + * Check if the breakpoint is present for any of the given span + * + * @param span the span + * @return true if its life intersects the span + */ + boolean isAlive(Lifespan span); +} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpoint.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointLocation.java similarity index 52% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpoint.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointLocation.java index 90cb2d3a26..50f6722be9 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpoint.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointLocation.java @@ -15,62 +15,71 @@ */ package ghidra.trace.model.breakpoint; -import java.util.Collection; import java.util.Set; import ghidra.pcode.emu.DefaultPcodeThread.PcodeEmulationLibrary; import ghidra.pcode.exec.SleighUtils; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; -import ghidra.trace.model.*; +import ghidra.trace.model.Lifespan; +import ghidra.trace.model.target.info.TraceObjectInfo; import ghidra.trace.model.thread.TraceThread; -/** - * A breakpoint in a trace - */ -public interface TraceBreakpoint extends TraceUniqueObject { - /** - * Get the trace containing this breakpoint - * - * @return the trace - */ - Trace getTrace(); +@TraceObjectInfo( + schemaName = "BreakpointLocation", + shortName = "breakpoint location", + attributes = { + TraceBreakpointLocation.KEY_RANGE, + TraceBreakpointLocation.KEY_EMU_ENABLED, + TraceBreakpointLocation.KEY_EMU_SLEIGH, + }, + fixedKeys = { + TraceBreakpointLocation.KEY_RANGE, + }) +public interface TraceBreakpointLocation extends TraceBreakpointCommon { + String KEY_RANGE = "_range"; + String KEY_EMU_ENABLED = "_emu_enabled"; + String KEY_EMU_SLEIGH = "_emu_sleigh"; /** - * Get the "full name" of this breakpoint + * Get the specification that caused this location to exist * - *

- * This is a name unique to this breakpoint, which may not be suitable for display on the - * screen. - * - * @return the path + * @return the specification */ - String getPath(); + TraceBreakpointSpec getSpecification(); /** - * Set the "short name" of this breakpoint - * - *

- * This should be a name suitable for display on the screen - * - * @param snap the first effective snap - * @param name the new name - */ - void setName(long snap, String name); - - /** - * Get the "short name" of this breakpoint - * - *

- * This defaults to the "full name," but can be modified via {@link #setName(long, String)} + * See {@link TraceBreakpointSpec#getKinds(long)} * * @param snap the snap - * @return the name + * @return the kinds */ - String getName(long snap); + default Set getKinds(long snap) { + return getSpecification().getKinds(snap); + } /** - * Get the range covered by this breakpoint + * Get the set of threads to which this breakpoint's application is limited + * + *

+ * Note, an empty set here implies all contemporary live threads, i.e., the process. + * + * @param snap the snap + * @return the (possibly empty) set of affected threads + */ + @Deprecated(forRemoval = true, since = "11.5") + Set getThreads(long snap); + + /** + * Set the range covered by this breakpoint location + * + * @param lifespan the span of time + * @param range the span of addresses + */ + void setRange(Lifespan lifespan, AddressRange range); + + /** + * Get the range covered by this breakpoint location * *

* Most often, esp. for execution breakpoints, this is a single address. @@ -107,20 +116,12 @@ public interface TraceBreakpoint extends TraceUniqueObject { long getLength(long snap); /** - * Set whether this breakpoint was enabled or disabled + * Set whether this breakpoint is enabled or disabled for emulation * - * @param snap the first effective snap + * @param lifespan the span of time * @param enabled true if enabled, false if disabled */ - void setEnabled(long snap, boolean enabled); - - /** - * Check whether this breakpoint is enabled or disabled at the given snap - * - * @param snap the snap - * @return true if enabled, false if disabled - */ - boolean isEnabled(long snap); + void setEmuEnabled(Lifespan lifespan, boolean enabled); /** * Set whether this breakpoint is enabled or disabled for emulation @@ -139,56 +140,12 @@ public interface TraceBreakpoint extends TraceUniqueObject { boolean isEmuEnabled(long snap); /** - * Set the kinds included in this breakpoint + * As in {@link #setEmuSleigh(long, String)}, but for a specific lifespan * - *

- * See {@link #getKinds(long)}. Note that it is unusual for a breakpoint to change kinds during - * its life. Nevertheless, in the course of recording a trace, it may happen, or at least appear - * to happen. - * - * @param snap the snap - * @param kinds the set of kinds + * @param lifespan the span of time + * @param sleigh the Sleigh source */ - void setKinds(long snap, Collection kinds); - - /** - * Get the kinds included in this breakpoint - * - *

- * For example, an "access breakpoint" or "access watchpoint," depending on terminology, would - * include both {@link TraceBreakpointKind#READ} and {@link TraceBreakpointKind#WRITE}. - * - * @param snap the snap - * @return the set of kinds - */ - Set getKinds(long snap); - - /** - * Get the set of threads to which this breakpoint's application is limited - * - *

- * Note, an empty set here implies all contemporary live threads, i.e., the process. - * - * @param snap the snap - * @return the (possibly empty) set of affected threads - */ - Set getThreads(long snap); - - /** - * Set a comment on this breakpoint - * - * @param snap the snap - * @param comment the comment, possibly {@code null} - */ - void setComment(long snap, String comment); - - /** - * Get the comment on this breakpoint - * - * @param snap the snap - * @return the comment, possibly {@code null} - */ - String getComment(long snap); + void setEmuSleigh(Lifespan lifespan, String sleigh); /** * Set Sleigh source to replace the breakpointed instruction in emulation @@ -227,38 +184,4 @@ public interface TraceBreakpoint extends TraceUniqueObject { * @return the Sleigh source */ String getEmuSleigh(long snap); - - /** - * Remove this breakpoint from the given snap on - * - * @param snap the snap - */ - void remove(long snap); - - /** - * Delete this breakpoint from the trace - */ - void delete(); - - /** - * Check if the breakpoint is present at the given snapshot - * - *

- * In object mode, a breakpoint's life may be disjoint, so checking if the snap occurs between - * creation and destruction is not quite sufficient. This method encapsulates validity. In - * object mode, it checks that the breakpoint object has a canonical parent at the given - * snapshot. In table mode, it checks that the lifespan contains the snap. - * - * @param snap the snapshot key - * @return true if valid, false if not - */ - boolean isValid(long snap); - - /** - * Check if the breakpoint is present for any of the given span - * - * @param span the span - * @return true if its life intersects the span - */ - boolean isAlive(Lifespan span); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointManager.java index d0cbb577df..3c2c3d9c6b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointManager.java @@ -4,9 +4,9 @@ * 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. @@ -42,7 +42,7 @@ public interface TraceBreakpointManager { * @throws DuplicateNameException if a breakpoint with the same path already exists within an * overlapping snap */ - TraceBreakpoint addBreakpoint(String path, Lifespan lifespan, AddressRange range, + TraceBreakpointLocation addBreakpoint(String path, Lifespan lifespan, AddressRange range, Collection threads, Collection kinds, boolean enabled, String comment) throws DuplicateNameException; @@ -51,7 +51,7 @@ public interface TraceBreakpointManager { * * @see #addBreakpoint(String, Lifespan, AddressRange, Collection, Collection, boolean, String) */ - default TraceBreakpoint addBreakpoint(String path, Lifespan lifespan, Address address, + default TraceBreakpointLocation addBreakpoint(String path, Lifespan lifespan, Address address, Collection threads, Collection kinds, boolean enabled, String comment) throws DuplicateNameException { return addBreakpoint(path, lifespan, new AddressRangeImpl(address, address), threads, kinds, @@ -63,7 +63,7 @@ public interface TraceBreakpointManager { * * @see #addBreakpoint(String, Lifespan, AddressRange, Collection, Collection, boolean, String) */ - default TraceBreakpoint placeBreakpoint(String path, long snap, AddressRange range, + default TraceBreakpointLocation placeBreakpoint(String path, long snap, AddressRange range, Collection threads, Collection kinds, boolean enabled, String comment) throws DuplicateNameException { return addBreakpoint(path, Lifespan.nowOn(snap), range, threads, kinds, enabled, @@ -75,7 +75,7 @@ public interface TraceBreakpointManager { * * @see #addBreakpoint(String, Lifespan, AddressRange, Collection, Collection, boolean, String) */ - default TraceBreakpoint placeBreakpoint(String path, long snap, Address address, + default TraceBreakpointLocation placeBreakpoint(String path, long snap, Address address, Collection threads, Collection kinds, boolean enabled, String comment) throws DuplicateNameException { return addBreakpoint(path, Lifespan.nowOn(snap), new AddressRangeImpl(address, address), @@ -83,19 +83,34 @@ public interface TraceBreakpointManager { } /** - * Collect all breakpoints in the trace + * Collect all breakpoint specifications in the trace * - * @return the collection of all breakpoints + * @return the specifications */ - Collection getAllBreakpoints(); + Collection getAllBreakpointSpecifications(); /** - * Collect breakpoints having the given "full name" + * Collect all breakpoint locations in the trace + * + * @return the locations + */ + Collection getAllBreakpointLocations(); + + /** + * Collect breakpoints specifications having the given "full name" * * @param path the path - * @return the collection of breakpoints + * @return the specifications */ - Collection getBreakpointsByPath(String path); + Collection getBreakpointSpecificationsByPath(String path); + + /** + * Collect breakpoints locations having the given "full name" + * + * @param path the path + * @return the locations + */ + Collection getBreakpointLocationsByPath(String path); /** * Get the placed breakpoint at the given snap by the given path @@ -104,7 +119,7 @@ public interface TraceBreakpointManager { * @param path the path of the breakpoint * @return the breakpoint, or {@code null} if no breakpoint matches */ - TraceBreakpoint getPlacedBreakpointByPath(long snap, String path); + TraceBreakpointLocation getPlacedBreakpointByPath(long snap, String path); /** * Collect breakpoints containing the given snap and address @@ -113,7 +128,7 @@ public interface TraceBreakpointManager { * @param address the location * @return the collection of breakpoints */ - Collection getBreakpointsAt(long snap, Address address); + Collection getBreakpointsAt(long snap, Address address); /** * Collect breakpoints intersecting the given span and address range @@ -122,6 +137,6 @@ public interface TraceBreakpointManager { * @param range the address range * @return the collection of breakpoints */ - Collection getBreakpointsIntersecting(Lifespan span, + Collection getBreakpointsIntersecting(Lifespan span, AddressRange range); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointSpec.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointSpec.java new file mode 100644 index 0000000000..5c288058cf --- /dev/null +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceBreakpointSpec.java @@ -0,0 +1,120 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.trace.model.breakpoint; + +import java.util.Collection; +import java.util.Set; + +import ghidra.trace.model.Lifespan; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.iface.TraceTogglable; +import ghidra.trace.model.target.info.TraceObjectInfo; + +/** + * The specification of a breakpoint applied to a target object + * + *

+ * Note that a single specification could result in several locations, or no locations at all. For + * example, a breakpoint placed on a function within a module which has not been loaded ("pending" + * in GDB's nomenclature), will not have any location. On the other hand, a breakpoint expressed by + * line number in a C++ template or a C macro could resolve to many addresses. The children of this + * object include the resolved {@link TraceBreakpointLocation}s. If the debugger does not share this + * same concept, then its breakpoints should implement both the specification and the location; the + * specification need not have any children. + * + *

+ * This object extends {@link TraceTogglable} for a transitional period only. Implementations + * whose breakpoint specifications can be toggled should declare this interface explicitly. When the + * specification is user togglable, toggling it should effectively toggle all locations -- whether + * or not the locations are user togglable. + * + *

+ * NOTE: When enumerating trace breakpoints, use the locations, not the specifications. + */ +@TraceObjectInfo( + schemaName = "BreakpointSpec", + shortName = "breakpoint specification", + attributes = { + TraceBreakpointSpec.KEY_EXPRESSION, + TraceBreakpointSpec.KEY_KINDS, + TraceBreakpointSpec.KEY_AS_BPT, + }, + fixedKeys = { + TraceObjectInterface.KEY_DISPLAY, + TraceBreakpointSpec.KEY_EXPRESSION, + TraceBreakpointSpec.KEY_KINDS, + }) +public interface TraceBreakpointSpec extends TraceBreakpointCommon { + String KEY_EXPRESSION = "_expression"; + String KEY_KINDS = "_kinds"; + String KEY_AS_BPT = "_bpt"; + // LATER?: Command List + // LATER?: Condition + + /** + * Get the expression used to specify this breakpoint. + * + * @param snap the snap + * @return the expression + */ + String getExpression(long snap); + + /** + * Set the kinds included in this breakpoint + * + *

+ * See {@link #getKinds(long)}. Note that it is unusual for a breakpoint to change kinds during + * its life. Nevertheless, in the course of recording a trace, it may happen, or at least appear + * to happen. + * + * @param lifespan the span of time + * @param kinds the set of kinds + */ + void setKinds(Lifespan lifespan, Collection kinds); + + /** + * Set the kinds included in this breakpoint + * + *

+ * See {@link #getKinds(long)}. Note that it is unusual for a breakpoint to change kinds during + * its life. Nevertheless, in the course of recording a trace, it may happen, or at least appear + * to happen. + * + * @param snap the snap + * @param kinds the set of kinds + */ + void setKinds(long snap, Collection kinds); + + /** + * Get the kinds included in this breakpoint + * + *

+ * For example, an "access breakpoint" or "access watchpoint," depending on terminology, would + * include both {@link TraceBreakpointKind#READ} and {@link TraceBreakpointKind#WRITE}. + * + * @param snap the snap + * @return the set of kinds + */ + Set getKinds(long snap); + + /** + * Get the locations for this breakpoint + * + * @param snap the snap + * @return the locations + */ + Collection getLocations(long snap); +} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceObjectBreakpointLocation.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceObjectBreakpointLocation.java deleted file mode 100644 index ba0324b666..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceObjectBreakpointLocation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.breakpoint; - -import java.util.Collection; - -import ghidra.program.model.address.AddressRange; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -@TraceObjectInfo( - schemaName = "BreakpointLocation", - shortName = "breakpoint location", - attributes = { - TraceObjectBreakpointLocation.KEY_RANGE, - TraceObjectBreakpointLocation.KEY_EMU_ENABLED, - TraceObjectBreakpointLocation.KEY_EMU_SLEIGH, - }, - fixedKeys = { - TraceObjectBreakpointLocation.KEY_RANGE, - }) -public interface TraceObjectBreakpointLocation extends TraceBreakpoint, TraceObjectInterface { - String KEY_RANGE = "_range"; - String KEY_EMU_ENABLED = "_emu_enabled"; - String KEY_EMU_SLEIGH = "_emu_sleigh"; - - TraceObjectBreakpointSpec getSpecification(); - - void setRange(Lifespan lifespan, AddressRange range); - - void setName(Lifespan lifespan, String name); - - void setKinds(Lifespan lifespan, Collection kinds); - - void setEnabled(Lifespan lifespan, boolean enabled); - - void setEmuEnabled(Lifespan lifespan, boolean emuEnabled); - - void setEmuSleigh(Lifespan lifespan, String sleigh); - - void setComment(Lifespan lifespan, String comment); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceObjectBreakpointSpec.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceObjectBreakpointSpec.java deleted file mode 100644 index e2d40cf47f..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/breakpoint/TraceObjectBreakpointSpec.java +++ /dev/null @@ -1,72 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.breakpoint; - -import java.util.Collection; - -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -/** - * The specification of a breakpoint applied to a target object - * - *

- * Note that a single specification could result in several locations, or no locations at all. For - * example, a breakpoint placed on a function within a module which has not been loaded ("pending" - * in GDB's nomenclature), will not have any location. On the other hand, a breakpoint expressed by - * line number in a C++ template or a C macro could resolve to many addresses. The children of this - * object include the resolved {@link TargetBreakpointLocation}s. If the debugger does not share - * this same concept, then its breakpoints should implement both the specification and the location; - * the specification need not have any children. - * - *

- * This object extends {@link TargetTogglable} for a transitional period only. Implementations whose - * breakpoint specifications can be toggled should declare this interface explicitly. When the - * specification is user togglable, toggling it should effectively toggle all locations -- whether - * or not the locations are user togglable. - * - *

- * NOTE: When enumerating trace breakpoints, use the locations, not the specifications. - */ -@TraceObjectInfo( - schemaName = "BreakpointSpec", - shortName = "breakpoint specification", - attributes = { - TraceObjectBreakpointSpec.KEY_EXPRESSION, - TraceObjectBreakpointSpec.KEY_KINDS, - TraceObjectBreakpointSpec.KEY_AS_BPT, - }, - fixedKeys = { - TraceObjectInterface.KEY_DISPLAY, - TraceObjectBreakpointSpec.KEY_EXPRESSION, - TraceObjectBreakpointSpec.KEY_KINDS, - }) -public interface TraceObjectBreakpointSpec extends TraceBreakpoint, TraceObjectInterface { - String KEY_EXPRESSION = "_expression"; - String KEY_KINDS = "_kinds"; - String KEY_AS_BPT = "_bpt"; - - // TODO: Make hit count part of the common interface? - // TODO: Make command list part of the common interface? - // TODO: Make condition part of the common interface? - - Collection getLocations(long snap); - - String getExpression(long snap); - - void setKinds(Lifespan lifespan, Collection kinds); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java index c0c44f6983..7f7a0ca2a0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java @@ -22,7 +22,7 @@ import ghidra.program.model.lang.*; import ghidra.program.model.mem.MemBuffer; import ghidra.trace.model.Trace; import ghidra.trace.model.data.TraceBasedDataTypeManager; -import ghidra.trace.model.memory.TraceObjectRegister; +import ghidra.trace.model.memory.TraceRegister; import ghidra.trace.model.symbol.TraceLabelSymbol; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.path.KeyPath; @@ -239,11 +239,11 @@ public interface TracePlatform { PathFilter getConventionalRegisterPath(AddressSpace overlay, Register register); /** - * Add a label the conventionally maps the value of a {@link TraceObjectRegister} in the object + * Add a label the conventionally maps the value of a {@link TraceRegister} in the object * manager to a register from this platform * * @param register the language register - * @param objectName the name of the {@link TraceObjectRegister} in the object tree + * @param objectName the name of the {@link TraceRegister} in the object tree * @return the label */ TraceLabelSymbol addRegisterMapOverride(Register register, String objectName); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceBaseCodeUnitsView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceBaseCodeUnitsView.java index 3fc43a8a59..0dc8d0ebaf 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceBaseCodeUnitsView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceBaseCodeUnitsView.java @@ -19,7 +19,6 @@ import ghidra.program.model.address.*; import ghidra.program.model.lang.Register; import ghidra.trace.model.*; import ghidra.trace.model.guest.TracePlatform; -import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.IntersectionAddressSetView; import ghidra.util.UnionAddressSetView; @@ -305,6 +304,19 @@ public interface TraceBaseCodeUnitsView { * @return the iterable of units */ default Iterable get(long snap, Register register, boolean forward) { - return get(snap, TraceRegisterUtils.rangeForRegister(register), forward); + return get(getTrace().getPlatformManager().getHostPlatform(), snap, register, forward); } + + /** + * Get the live units whose start addresses are within the given register + * + * + * @param platform the platform whose language defines the register + * @param snap the snap during which the units must be alive + * @param register the register + * @param forward true to order the units by increasing address, false for descending + * @return the iterable of units + */ + Iterable get(TracePlatform platform, long snap, Register register, + boolean forward); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeManager.java index 761c0b2efe..cc9e14590b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeManager.java @@ -26,7 +26,6 @@ import ghidra.trace.model.Trace; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; /** * The manager for trace code units, i.e., the equivalent of {@link Listing} @@ -54,15 +53,6 @@ import ghidra.trace.util.TraceAddressSpace; */ public interface TraceCodeManager extends TraceCodeOperations { - /** - * Get the code space for the memory or registers of the given trace address space - * - * @param space the trace address space (thread, stack frame, address space) - * @param createIfAbsent true to create the space if it's not already present - * @return the space, of {@code null} if absent and not created - */ - TraceCodeSpace getCodeSpace(TraceAddressSpace space, boolean createIfAbsent); - /** * Get the code space for the memory of the given address space * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeUnit.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeUnit.java index 18feb5b9c8..92d56472d7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeUnit.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/listing/TraceCodeUnit.java @@ -4,9 +4,9 @@ * 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. @@ -25,7 +25,6 @@ import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.symbol.TraceReference; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; import ghidra.util.Saveable; import ghidra.util.map.TypeMismatchException; @@ -50,13 +49,6 @@ public interface TraceCodeUnit extends CodeUnit { @Override TraceProgramView getProgram(); - /** - * Get a key that can be used to obtain the same space in another manager - * - * @return the space, including thread and frame, if applicable - */ - TraceAddressSpace getTraceSpace(); - /** * Get the thread associated with this code unit * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/RegisterValueConverter.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/RegisterValueConverter.java index e81d4312e2..1704e79671 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/RegisterValueConverter.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/RegisterValueConverter.java @@ -71,7 +71,7 @@ public class RegisterValueConverter { int getRegisterValueBitLength() throws RegisterValueException { Object objBitLength = registerValue.getParent() - .getValue(registerValue.getMinSnap(), TraceObjectRegister.KEY_BITLENGTH) + .getValue(registerValue.getMinSnap(), TraceRegister.KEY_BITLENGTH) .getValue(); if (!(objBitLength instanceof Number numBitLength)) { throw new RegisterValueException( diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectMemory.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemory.java similarity index 73% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectMemory.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemory.java index ca980005f6..79aa910727 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectMemory.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemory.java @@ -23,14 +23,14 @@ import ghidra.trace.model.target.info.TraceObjectInfo; * *

* The convention for modeling valid addresses is to have children supporting - * {@link TraceObjectMemoryRegion}. If no such children exist, then the client should assume no - * address is valid. Thus, for the client to confidently access any memory, at least one child - * region must exist. It may present the memory's entire address space in a single region. + * {@link TraceMemoryRegion}. If no such children exist, then the client should assume no address is + * valid. Thus, for the client to confidently access any memory, at least one child region must + * exist. It may present the memory's entire address space in a single region. */ @TraceObjectInfo( schemaName = "Memory", shortName = "memory", attributes = {}, fixedKeys = {}) -public interface TraceObjectMemory extends TraceObjectInterface { +public interface TraceMemory extends TraceObjectInterface { } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryManager.java index 74a4507b23..0ed48179b7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryManager.java @@ -15,10 +15,13 @@ */ package ghidra.trace.model.memory; +import java.util.Arrays; import java.util.Collection; import java.util.Map.Entry; +import java.util.function.Predicate; -import ghidra.program.model.address.AddressSpace; +import ghidra.program.model.address.*; +import ghidra.trace.model.Lifespan; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.thread.TraceThread; @@ -90,6 +93,124 @@ public interface TraceMemoryManager extends TraceMemoryOperations { */ void deleteOverlayAddressSpace(String name); + /** + * Add a new region with the given properties + * + *

+ * Regions model the memory mappings of a debugging target. As such, they are never allowed to + * overlap. Additionally, to ensure {@link #getLiveRegionByPath(long, String)} returns a unique + * region, duplicate paths cannot exist in the same snap. + * + *

+ * Regions have a "full name" (path) as well as a short name. The path is immutable and can be + * used to reliably retrieve the same region later. The short name should be something suitable + * for display on the screen. Short names are mutable and can be -- but probbaly shouldn't be -- + * duplicated. + * + * @param path the "full name" of the region + * @param lifespan the lifespan of the region + * @param range the address range of the region + * @param flags the flags, e.g., permissions, of the region + * @return the newly-added region + * @throws TraceOverlappedRegionException if the specified region would overlap an existing one + */ + TraceMemoryRegion addRegion(String path, Lifespan lifespan, AddressRange range, + Collection flags) throws TraceOverlappedRegionException; + + /** + * @see #addRegion(String, Lifespan, AddressRange, Collection) + */ + default TraceMemoryRegion addRegion(String path, Lifespan lifespan, + AddressRange range, TraceMemoryFlag... flags) throws TraceOverlappedRegionException { + return addRegion(path, lifespan, range, Arrays.asList(flags)); + } + + /** + * Add a region created at the given snap, with no specified destruction snap + * + * @see #addRegion(String, Lifespan, AddressRange, Collection) + */ + default TraceMemoryRegion createRegion(String path, long snap, AddressRange range, + Collection flags) + throws TraceOverlappedRegionException, DuplicateNameException { + return addRegion(path, Lifespan.nowOn(snap), range, flags); + } + + /** + * @see #createRegion(String, long, AddressRange, Collection) + */ + default TraceMemoryRegion createRegion(String path, long snap, AddressRange range, + TraceMemoryFlag... flags) + throws TraceOverlappedRegionException, DuplicateNameException { + return addRegion(path, Lifespan.nowOn(snap), range, flags); + } + + /** + * Get all the regions in this space or manager + * + * @return the collection of all regions + */ + Collection getAllRegions(); + + /** + * Get the region with the given path at the given snap + * + * @param snap the snap which must be within the region's lifespan + * @param path the "full name" of the region + * @return the region, or {@code null} if no region matches + */ + TraceMemoryRegion getLiveRegionByPath(long snap, String path); + + /** + * Get the region at the given address and snap + * + * @param snap the snap which must be within the region's lifespan + * @param address the address which must be within the region's range + * @return the region, or {@code null} if no region matches + */ + TraceMemoryRegion getRegionContaining(long snap, Address address); + + /** + * Collect regions intersecting the given lifespan and range + * + * @param lifespan the lifespan + * @param range the range + * @return the collection of matching regions + */ + Collection getRegionsIntersecting(Lifespan lifespan, + AddressRange range); + + /** + * Collect regions at the given snap + * + * @param snap the snap which must be within the regions' lifespans + * @return the collection of matching regions + */ + Collection getRegionsAtSnap(long snap); + + /** + * Get the addresses contained by regions at the given snap + * + *

+ * The implementation may provide a view that updates with changes. + * + * @param snap the snap which must be within the regions' lifespans + * @return the union of ranges of matching regions + */ + AddressSetView getRegionsAddressSet(long snap); + + /** + * Get the addresses contained by regions at the given snap satisfying the given predicate + * + *

+ * The implementation may provide a view that updates with changes. + * + * @param snap the snap which must be within the region's lifespans + * @param predicate a predicate on regions to search for + * @return the address set + */ + AddressSetView getRegionsAddressSetWith(long snap, Predicate predicate); + /** * Obtain a memory space bound to a particular address space * @@ -135,24 +256,6 @@ public interface TraceMemoryManager extends TraceMemoryOperations { */ TraceMemorySpace getMemoryRegisterSpace(TraceStackFrame frame, boolean createIfAbsent); - /** - * Collect all the regions added between two given snaps - * - * @param from the earlier snap - * @param to the later snap - * @return the collection of regions added - */ - Collection getRegionsAdded(long from, long to); - - /** - * Collect all the regions removed between two given snaps - * - * @param from the earlier snap - * @param to the later snap - * @return the collection of regions removed - */ - Collection getRegionsRemoved(long from, long to); - /** * Collect all the state changes between two given snaps * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryOperations.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryOperations.java index 93cfaf7222..acddf1fa6f 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryOperations.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryOperations.java @@ -17,7 +17,6 @@ package ghidra.trace.model.memory; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.Arrays; import java.util.Collection; import java.util.Map.Entry; import java.util.function.Predicate; @@ -29,7 +28,6 @@ import ghidra.program.model.mem.MemBuffer; import ghidra.trace.model.*; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.time.TraceSnapshot; -import ghidra.util.exception.DuplicateNameException; import ghidra.util.task.TaskMonitor; /** @@ -101,128 +99,6 @@ public interface TraceMemoryOperations { */ Trace getTrace(); - /** - * Add a new region with the given properties - * - *

- * Regions model the memory mappings of a debugging target. As such, they are never allowed to - * overlap. Additionally, to ensure {@link #getLiveRegionByPath(long, String)} returns a unique - * region, duplicate paths cannot exist in the same snap. - * - *

- * Regions have a "full name" (path) as well as a short name. The path is immutable and can be - * used to reliably retrieve the same region later. The short name should be something suitable - * for display on the screen. Short names are mutable and can be -- but probbaly shouldn't be -- - * duplicated. - * - * @param path the "full name" of the region - * @param lifespan the lifespan of the region - * @param range the address range of the region - * @param flags the flags, e.g., permissions, of the region - * @return the newly-added region - * @throws TraceOverlappedRegionException if the specified region would overlap an existing one - * @throws DuplicateNameException if the specified region has a name which duplicates another at - * any intersecting snap - */ - TraceMemoryRegion addRegion(String path, Lifespan lifespan, AddressRange range, - Collection flags) - throws TraceOverlappedRegionException, DuplicateNameException; - - /** - * @see #addRegion(String, Lifespan, AddressRange, Collection) - */ - default TraceMemoryRegion addRegion(String path, Lifespan lifespan, - AddressRange range, TraceMemoryFlag... flags) - throws TraceOverlappedRegionException, DuplicateNameException { - return addRegion(path, lifespan, range, Arrays.asList(flags)); - } - - /** - * Add a region created at the given snap, with no specified destruction snap - * - * @see #addRegion(String, Lifespan, AddressRange, Collection) - */ - default TraceMemoryRegion createRegion(String path, long snap, AddressRange range, - Collection flags) - throws TraceOverlappedRegionException, DuplicateNameException { - return addRegion(path, Lifespan.nowOn(snap), range, flags); - } - - /** - * @see #createRegion(String, long, AddressRange, Collection) - */ - default TraceMemoryRegion createRegion(String path, long snap, AddressRange range, - TraceMemoryFlag... flags) - throws TraceOverlappedRegionException, DuplicateNameException { - return addRegion(path, Lifespan.nowOn(snap), range, flags); - } - - /** - * Get all the regions in this space or manager - * - * @return the collection of all regions - */ - Collection getAllRegions(); - - /** - * Get the region with the given path at the given snap - * - * @param snap the snap which must be within the region's lifespan - * @param path the "full name" of the region - * @return the region, or {@code null} if no region matches - */ - TraceMemoryRegion getLiveRegionByPath(long snap, String path); - - /** - * Get the region at the given address and snap - * - * @param snap the snap which must be within the region's lifespan - * @param address the address which must be within the region's range - * @return the region, or {@code null} if no region matches - */ - TraceMemoryRegion getRegionContaining(long snap, Address address); - - /** - * Collect regions intersecting the given lifespan and range - * - * @param lifespan the lifespan - * @param range the range - * @return the collection of matching regions - */ - Collection getRegionsIntersecting(Lifespan lifespan, - AddressRange range); - - /** - * Collect regions at the given snap - * - * @param snap the snap which must be within the regions' lifespans - * @return the collection of matching regions - */ - Collection getRegionsAtSnap(long snap); - - /** - * Get the addresses contained by regions at the given snap - * - *

- * The implementation may provide a view that updates with changes. - * - * @param snap the snap which must be within the regions' lifespans - * @return the union of ranges of matching regions - */ - AddressSetView getRegionsAddressSet(long snap); - - /** - * Get the addresses contained by regions at the given snap satisfying the given predicate - * - *

- * The implementation may provide a view that updates with changes. - * - * @param snap the snap which must be within the region's lifespans - * @param predicate a predicate on regions to search for - * @return the address set - */ - AddressSetView getRegionsAddressSetWith(long snap, Predicate predicate); - /** * Set the state of memory over a given time and address range * @@ -341,7 +217,7 @@ public interface TraceMemoryOperations { * {@code state -> state != null && state != TraceMemoryState.UNKNOWN} and subtract the result * from {@code set}. * - * @param snap the time + * @param span the range of time * @param set the set to examine * @param predicate a predicate on state to search for * @return the address set diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegion.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegion.java index bce6baa355..5bc4c0bfd8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegion.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceMemoryRegion.java @@ -18,13 +18,34 @@ package ghidra.trace.model.memory; import java.util.*; import ghidra.program.model.address.*; -import ghidra.trace.model.Trace; -import ghidra.trace.model.TraceUniqueObject; +import ghidra.trace.model.*; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInfo; /** * A region of mapped target memory in a trace */ -public interface TraceMemoryRegion extends TraceUniqueObject { + +@TraceObjectInfo( + schemaName = "MemoryRegion", + shortName = "region", + attributes = { + TraceMemoryRegion.KEY_RANGE, + TraceMemoryRegion.KEY_READABLE, + TraceMemoryRegion.KEY_WRITABLE, + TraceMemoryRegion.KEY_EXECUTABLE, + TraceMemoryRegion.KEY_VOLATILE, + }, + fixedKeys = { + TraceObjectInterface.KEY_DISPLAY, + TraceMemoryRegion.KEY_RANGE, + }) +public interface TraceMemoryRegion extends TraceUniqueObject, TraceObjectInterface { + String KEY_RANGE = "_range"; + String KEY_READABLE = "_readable"; + String KEY_WRITABLE = "_writable"; + String KEY_EXECUTABLE = "_executable"; + String KEY_VOLATILE = "_volatile"; /** * Get the trace containing this region @@ -44,6 +65,17 @@ public interface TraceMemoryRegion extends TraceUniqueObject { */ String getPath(); + /** + * Set the "short name" of this region + * + *

+ * The given name should be suitable for display on the screen. + * + * @param lifespan the span of time + * @param name the name + */ + void setName(Lifespan lifespan, String name); + /** * Set the "short name" of this region * @@ -66,6 +98,19 @@ public interface TraceMemoryRegion extends TraceUniqueObject { */ String getName(long snap); + /** + * Set the virtual memory address range of this region + * + *

+ * The addresses in the range should be those the target's CPU would use to access the region, + * i.e., the virtual memory address if an MMU is involved, or the physical address if no MMU is + * involved. + * + * @param lifespan the span of time + * @param range the address range + */ + void setRange(Lifespan lifespan, AddressRange range); + /** * Set the virtual memory address range of this region * @@ -164,6 +209,14 @@ public interface TraceMemoryRegion extends TraceUniqueObject { */ long getLength(long snap); + /** + * Set the flags, e.g., permissions, of this region + * + * @param lifespan the span of time + * @param flags the flags + */ + void setFlags(Lifespan lifespan, Collection flags); + /** * Set the flags, e.g., permissions, of this region * @@ -182,6 +235,14 @@ public interface TraceMemoryRegion extends TraceUniqueObject { setFlags(snap, Arrays.asList(flags)); } + /** + * Add the given flags, e.g., permissions, to this region + * + * @param lifespan the span of time + * @param flags the flags + */ + void addFlags(Lifespan lifespan, Collection flags); + /** * Add the given flags, e.g., permissions, to this region * @@ -200,6 +261,14 @@ public interface TraceMemoryRegion extends TraceUniqueObject { addFlags(snap, Arrays.asList(flags)); } + /** + * Remove the given flags, e.g., permissions, from this region + * + * @param lifespan the span of time + * @param flags the flags + */ + void clearFlags(Lifespan lifespan, Collection flags); + /** * Remove the given flags, e.g., permissions, from this region * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectMemoryRegion.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectMemoryRegion.java deleted file mode 100644 index 62695177a7..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectMemoryRegion.java +++ /dev/null @@ -1,69 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.memory; - -import java.util.Collection; -import java.util.Set; - -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressRange; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -@TraceObjectInfo( - schemaName = "MemoryRegion", - shortName = "region", - attributes = { - TraceObjectMemoryRegion.KEY_RANGE, - TraceObjectMemoryRegion.KEY_READABLE, - TraceObjectMemoryRegion.KEY_WRITABLE, - TraceObjectMemoryRegion.KEY_EXECUTABLE, - TraceObjectMemoryRegion.KEY_VOLATILE, - }, - fixedKeys = { - TraceObjectInterface.KEY_DISPLAY, - TraceObjectMemoryRegion.KEY_RANGE, - }) -public interface TraceObjectMemoryRegion extends TraceMemoryRegion, TraceObjectInterface { - String KEY_RANGE = "_range"; - String KEY_READABLE = "_readable"; - String KEY_WRITABLE = "_writable"; - String KEY_EXECUTABLE = "_executable"; - String KEY_VOLATILE = "_volatile"; - - void setName(Lifespan lifespan, String name); - - void setRange(Lifespan lifespan, AddressRange range); - - @Override - AddressRange getRange(long snap); - - @Override - Address getMinAddress(long snap); - - @Override - Address getMaxAddress(long snap); - - void setFlags(Lifespan lifespan, Collection flags); - - void addFlags(Lifespan lifespan, Collection flags); - - void clearFlags(Lifespan lifespan, Collection flags); - - @Override - Set getFlags(long snap); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectRegister.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceRegister.java similarity index 82% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectRegister.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceRegister.java index c1a71d63f7..2aadc36736 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectRegister.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceRegister.java @@ -20,7 +20,7 @@ import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectManager; import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.info.TraceObjectInfo; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; /** * A register @@ -33,7 +33,7 @@ import ghidra.trace.model.thread.TraceObjectThread; * connector, then the trace database itself will try to convert the object-model tree presentation * to it, because the only way to annotate data types and references in registers is to instantiate * the appropriate register space. See the manager's documentation for how to set these up. - * NOTE: The {@link TraceObjectRegisterContainer} for the relevant thread or frame + * NOTE: The {@link TraceRegisterContainer} for the relevant thread or frame * must exist in this convention, even if the tree convention is not presented. *

  • In the {@link TraceObjectManager}: This convention is required when a register is not * known to Ghidra's slaspec, which is certainly the case if the connector falls back to the @@ -48,28 +48,28 @@ import ghidra.trace.model.thread.TraceObjectThread; * *

    * Some connectors may present registers in groups. To support this, there is an explicit - * {@link TraceObjectRegisterContainer}. Ordinarily, the client would use the schema to detect a - * "container" of {@link TraceObjectRegister}; however, that is not sufficient with groups. The root - * container (per thread or per frame) is marked as the {@link TraceObjectRegisterContainer}. The + * {@link TraceRegisterContainer}. Ordinarily, the client would use the schema to detect a + * "container" of {@link TraceRegister}; however, that is not sufficient with groups. The root + * container (per thread or per frame) is marked as the {@link TraceRegisterContainer}. The * connector may then organize the registers into groups, each group being a plain - * {@link TraceObject}, so long as each {@link TraceObjectRegister} is a successor to the register + * {@link TraceObject}, so long as each {@link TraceRegister} is a successor to the register * container. */ @TraceObjectInfo( schemaName = "Register", shortName = "register", attributes = { - TraceObjectRegister.KEY_BITLENGTH, - TraceObjectRegister.KEY_STATE, + TraceRegister.KEY_BITLENGTH, + TraceRegister.KEY_STATE, }, fixedKeys = { - TraceObjectRegister.KEY_BITLENGTH, + TraceRegister.KEY_BITLENGTH, }) -public interface TraceObjectRegister extends TraceObjectInterface { +public interface TraceRegister extends TraceObjectInterface { String KEY_BITLENGTH = "_length"; String KEY_STATE = "_state"; - TraceObjectThread getThread(); + TraceThread getThread(); String getName(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectRegisterContainer.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceRegisterContainer.java similarity index 85% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectRegisterContainer.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceRegisterContainer.java index 057bc07669..9deb95f0af 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceObjectRegisterContainer.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/memory/TraceRegisterContainer.java @@ -24,15 +24,15 @@ import ghidra.trace.model.target.schema.TraceObjectSchema; * *

    * NOTE: This is a special case of "container", since it need not be the immediate parent of the - * {@link TraceObjectRegister}s it contains. Thus, this cannot be supplanted by + * {@link TraceRegister}s it contains. Thus, this cannot be supplanted by * {@link TraceObjectSchema#searchForCanonicalContainer(Class)}. * - * @see TraceObjectRegister + * @see TraceRegister */ @TraceObjectInfo( schemaName = "RegisterContainer", shortName = "register container", attributes = {}, fixedKeys = {}) -public interface TraceObjectRegisterContainer extends TraceObjectInterface { +public interface TraceRegisterContainer extends TraceObjectInterface { } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceModule.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceModule.java index 9583441b9e..854540cffb 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceModule.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceModule.java @@ -19,15 +19,32 @@ import java.util.Collection; import ghidra.program.model.address.*; import ghidra.trace.model.*; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInfo; import ghidra.util.exception.DuplicateNameException; /** - * A module loaded in a target process + * A binary module loaded by the target and/or debugger * *

    - * This also serves as a namespace for storing the module's sections. + * This also serves as a namespace for storing the module's sections. If the debugger cares to parse + * the modules for section information, those sections should be presented as successors to the + * module. */ -public interface TraceModule extends TraceUniqueObject { +@TraceObjectInfo( + schemaName = "Module", + shortName = "module", + attributes = { + TraceModule.KEY_RANGE, + TraceModule.KEY_MODULE_NAME, + }, + fixedKeys = { + TraceModule.KEY_DISPLAY, + TraceModule.KEY_RANGE, + }) +public interface TraceModule extends TraceUniqueObject, TraceObjectInterface { + String KEY_RANGE = "_range"; + String KEY_MODULE_NAME = "_module_name"; /** * Get the trace containing this module @@ -69,7 +86,7 @@ public interface TraceModule extends TraceUniqueObject { */ default TraceSection addSection(long snap, String sectionPath, AddressRange range) throws DuplicateNameException { - return addSection(snap, sectionPath, sectionPath, range); + return addSection(snap, sectionPath, null, range); } /** @@ -84,6 +101,18 @@ public interface TraceModule extends TraceUniqueObject { */ String getPath(); + /** + * Set the "short name" of this module + * + *

    + * The given name is typically the file system path of the module's image, which is considered + * suitable for display on the screen. + * + * @param lifespan the span of time + * @param name the name + */ + void setName(Lifespan lifespan, String name); + /** * Set the "short name" of this module * @@ -107,6 +136,18 @@ public interface TraceModule extends TraceUniqueObject { */ String getName(long snap); + /** + * Set the address range of the module + * + *

    + * Typically, the minimum address in this range is the module's base address. If sections are + * given, this range should enclose all sections mapped into memory. + * + * @param lifespan the span of time + * @param range the address range. + */ + void setRange(Lifespan lifespan, AddressRange range); + /** * Set the address range of the module * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceObjectModule.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceObjectModule.java deleted file mode 100644 index cc4f171359..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceObjectModule.java +++ /dev/null @@ -1,57 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.modules; - -import java.util.Collection; - -import ghidra.program.model.address.AddressRange; -import ghidra.trace.database.module.TraceObjectSection; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -/** - * A binary module loaded by the target and/or debugger - * - *

    - * If the debugger cares to parse the modules for section information, those sections should be - * presented as successors to the module. - */ -@TraceObjectInfo( - schemaName = "Module", - shortName = "module", - attributes = { - TraceObjectModule.KEY_RANGE, - TraceObjectModule.KEY_MODULE_NAME, - }, - fixedKeys = { - TraceObjectModule.KEY_DISPLAY, - TraceObjectModule.KEY_RANGE, - }) -public interface TraceObjectModule extends TraceModule, TraceObjectInterface { - String KEY_RANGE = "_range"; - String KEY_MODULE_NAME = "_module_name"; - - void setName(Lifespan lifespan, String name); - - void setRange(Lifespan lifespan, AddressRange range); - - @Override - Collection getSections(long snap); - - @Override - TraceObjectSection getSectionByName(long snap, String sectionName); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceSection.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceSection.java index 492cf3bf7f..dc34d54cdc 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceSection.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/modules/TraceSection.java @@ -17,14 +17,36 @@ package ghidra.trace.model.modules; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; -import ghidra.trace.model.Trace; -import ghidra.trace.model.TraceUniqueObject; +import ghidra.trace.model.*; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInfo; import ghidra.util.exception.DuplicateNameException; /** - * A section of a module in a trace + * An allocated section of a binary module + * + *

    + * Note that the model should only present those sections which are allocated in memory. Otherwise + * strange things may happen, such as zero-length ranges (which AddressRange hates), or overlapping + * ranges (which Trace hates). + * + *

    + * LATER?: Present all sections, but include isAllocated */ -public interface TraceSection extends TraceUniqueObject { +@TraceObjectInfo( + schemaName = "Section", + shortName = "section", + attributes = { + TraceSection.KEY_MODULE, + TraceSection.KEY_RANGE, + }, + fixedKeys = { + TraceSection.KEY_DISPLAY, + TraceSection.KEY_RANGE + }) +public interface TraceSection extends TraceUniqueObject, TraceObjectInterface { + String KEY_MODULE = "_module"; + String KEY_RANGE = "_range"; /** * Get the trace containing this section @@ -51,6 +73,18 @@ public interface TraceSection extends TraceUniqueObject { */ String getPath(); + /** + * Set the short name of this section + * + *

    + * The given name should be the section's name from its module's image, which is considered + * suitable for display on the screen. + * + * @param lifespan the span of time + * @param name the name + */ + void setName(Lifespan lifespan, String name); + /** * Set the short name of this section * @@ -76,6 +110,14 @@ public interface TraceSection extends TraceUniqueObject { */ String getName(long snap); + /** + * Set the virtual memory address range of this section + * + * @param lifespan the span of time + * @param range the span of addresses + */ + void setRange(Lifespan lifespan, AddressRange range); + /** * Get the virtual memory address range of this section * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/program/TraceProgramView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/program/TraceProgramView.java index b93b524fa6..eb21cfd9fc 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/program/TraceProgramView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/program/TraceProgramView.java @@ -4,9 +4,9 @@ * 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. @@ -18,7 +18,6 @@ package ghidra.trace.model.program; import ghidra.program.model.listing.Program; import ghidra.trace.model.Trace; import ghidra.trace.model.TraceTimeViewport; -import ghidra.trace.model.thread.TraceThread; /** * View of a trace at a particular time, as a program @@ -55,13 +54,4 @@ public interface TraceProgramView extends Program { * @return the maximum snap */ Long getMaxSnap(); - - /** - * Get a view for registers of a given thread - * - * @param thread the thread - * @param createIfAbsent true to create code and memory tables if absent (requires transaction) - * @return the view, of null if either code or memory table was absent and not created - */ - TraceProgramView getViewRegisters(TraceThread thread, boolean createIfAbsent); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/property/TracePropertyMap.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/property/TracePropertyMap.java index 234a073c24..f1c9535a61 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/property/TracePropertyMap.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/property/TracePropertyMap.java @@ -4,9 +4,9 @@ * 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. @@ -18,7 +18,6 @@ package ghidra.trace.model.property; import ghidra.program.model.address.AddressSpace; import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; /** * A range map for storing properties in a trace @@ -70,22 +69,6 @@ public interface TracePropertyMap extends TracePropertyMapOperations { createIfAbsent); } - /** - * Get the map space for the given trace space - * - * @param traceSpace the trace space, giving the memory space or thread/frame register space - * @param createIfAbsent true to create the map space if it doesn't already exist - * @return the space, or null - */ - default TracePropertyMapSpace getPropertyMapSpace(TraceAddressSpace traceSpace, - boolean createIfAbsent) { - if (traceSpace.getAddressSpace().isRegisterSpace()) { - return getPropertyMapRegisterSpace(traceSpace.getThread(), traceSpace.getFrameLevel(), - createIfAbsent); - } - return getPropertyMapSpace(traceSpace.getAddressSpace(), createIfAbsent); - } - /** * Delete this property and remove all of its maps * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceObjectStack.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceObjectStack.java deleted file mode 100644 index 919ecd2522..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceObjectStack.java +++ /dev/null @@ -1,38 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.stack; - -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -/** - * Represents the execution stack, as unwound into frames by the debugger - * - *

    - * Conventionally, if the debugger can also unwind register values, then each frame should present a - * register bank. Otherwise, the same object presenting this stack should present the register bank. - * - *

    - * TODO: Probably remove this. It serves only as a container of {@link TraceObjectStackFrame}, which - * can be discovered using the schema. - */ -@TraceObjectInfo( - schemaName = "Stack", - shortName = "stack", - attributes = {}, - fixedKeys = {}) -public interface TraceObjectStack extends TraceStack, TraceObjectInterface { -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceObjectStackFrame.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceObjectStackFrame.java deleted file mode 100644 index 97f3a73886..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceObjectStackFrame.java +++ /dev/null @@ -1,30 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.stack; - -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -@TraceObjectInfo( - schemaName = "StackFrame", - shortName = "frame", - attributes = { - TraceObjectStackFrame.KEY_PC, - }, - fixedKeys = {}) -public interface TraceObjectStackFrame extends TraceStackFrame, TraceObjectInterface { - String KEY_PC = "_pc"; -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStack.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStack.java index d342a8b11f..30076e0dcf 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStack.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStack.java @@ -20,19 +20,31 @@ import java.util.List; import ghidra.lifecycle.Transitional; import ghidra.trace.model.TraceUniqueObject; import ghidra.trace.model.memory.TraceMemoryManager; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInfo; import ghidra.trace.model.thread.TraceThread; /** * A trace of the connected debugger's stack unwind * + *

    * Most of the information stored here is ancillary, since with sufficient analysis of associated * images, it could be recovered, in the same fashion as the connected debugger did. Nevertheless, * during a debug session, this information should be recorded if offered, as it makes it * immediately accessible, before sufficient analysis has been performed, and provides some check * for that analysis. If this information wasn't recorded during a session, this can store the * result of that analysis. + * + *

    + * Conventionally, if the debugger can also unwind register values, then each frame should present a + * register bank. Otherwise, the same object presenting this stack should present the register bank. */ -public interface TraceStack extends TraceUniqueObject { +@TraceObjectInfo( + schemaName = "Stack", + shortName = "stack", + attributes = {}, + fixedKeys = {}) +public interface TraceStack extends TraceUniqueObject, TraceObjectInterface { /** * Get the thread whose stack this is diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStackFrame.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStackFrame.java index 605cf74d3b..2835e85a39 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStackFrame.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/stack/TraceStackFrame.java @@ -4,9 +4,9 @@ * 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. @@ -18,11 +18,30 @@ package ghidra.trace.model.stack; import ghidra.lifecycle.Experimental; import ghidra.program.model.address.Address; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.Trace; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInfo; /** * A frame in a {@link TraceStack} */ -public interface TraceStackFrame { +@TraceObjectInfo( + schemaName = "StackFrame", + shortName = "frame", + attributes = { + TraceStackFrame.KEY_PC, + }, + fixedKeys = {}) +public interface TraceStackFrame extends TraceObjectInterface { + String KEY_PC = "_pc"; + + /** + * Get the trace containing this frame + * + * @return the trace + */ + Trace getTrace(); + /** * Get the containing stack * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceLabelSymbolView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceLabelSymbolView.java index 175ee7c613..3bc9f0cc24 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceLabelSymbolView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceLabelSymbolView.java @@ -4,9 +4,9 @@ * 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. @@ -15,21 +15,24 @@ */ package ghidra.trace.model.symbol; -import ghidra.program.model.address.Address; +import ghidra.program.model.address.*; +import ghidra.program.model.lang.Register; import ghidra.program.model.symbol.SourceType; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.exception.InvalidInputException; /** * The label symbol view. */ public interface TraceLabelSymbolView extends TraceSymbolWithLocationView { + /** * Add a new label symbol. * * @param lifespan the lifespan of the symbol - * @param thread the thread, if in register space * @param address the address of the label * @param name the name of the label * @param parent the parent namespace @@ -37,16 +40,14 @@ public interface TraceLabelSymbolView extends TraceSymbolWithLocationView { + /** + * Get the trace that contains this view + * + * @return the trace + */ + default Trace getTrace() { + return getManager().getTrace(); + } + /** * Get the symbol manager for the trace. * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolWithLocationView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolWithLocationView.java index 81c92b5da4..1311e114fd 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolWithLocationView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolWithLocationView.java @@ -4,9 +4,9 @@ * 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. @@ -18,8 +18,11 @@ package ghidra.trace.model.symbol; import java.util.*; import ghidra.program.model.address.*; +import ghidra.program.model.lang.Register; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.LockHold; /** @@ -38,42 +41,113 @@ public interface TraceSymbolWithLocationView extends Trac * * @param name the name of the symbol * @param snap the snapshot key - * @param thread the thread, if in register space * @param address the address of the symbol * @param parent the parent namespace * @return the symbol, or null */ - T getChildWithNameAt(String name, long snap, TraceThread thread, Address address, - TraceNamespaceSymbol parent); + T getChildWithNameAt(String name, long snap, Address address, TraceNamespaceSymbol parent); /** - * A shorthand for - * {@link #getChildWithNameAt(String, long, TraceThread, Address, TraceNamespaceSymbol)} where - * parent is the global namespace. + * Get the child of the given parent having the given name at the given register's min address. + * + * @param name the name of the symbol + * @param platform the platform defining the register + * @param snap the snapshot key + * @param thread the thread + * @param register the register whose min address to check + * @param parent the parent namespace + * @return the symbol, or null + */ + default T getChildWithNameAt(String name, TracePlatform platform, long snap, TraceThread thread, + Register register, TraceNamespaceSymbol parent) { + AddressSpace space = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + if (space == null) { + return null; + } + AddressRange range = platform.getConventionalRegisterRange(space, register); + return getChildWithNameAt(name, snap, range.getMinAddress(), parent); + } + + /** + * Get the child of the given parent having the given name at the given register's min address. + * + * @param name the name of the symbol + * @param snap the snapshot key + * @param thread the thread + * @param register the register whose min address to check + * @param parent the parent namespace + * @return the symbol, or null + */ + default T getChildWithNameAt(String name, long snap, TraceThread thread, Register register, + TraceNamespaceSymbol parent) { + return getChildWithNameAt(name, getTrace().getPlatformManager().getHostPlatform(), snap, + thread, register, parent); + } + + /** + * A shorthand for {@link #getChildWithNameAt(String, long, Address, TraceNamespaceSymbol)} + * where parent is the global namespace. * * @param name the name of the symbol * @param snap the snapshot key - * @param thread the thread, if in register space * @param address the address of the symbol * @return the symbol, or null */ - default T getGlobalWithNameAt(String name, long snap, TraceThread thread, Address address) { - return getChildWithNameAt(name, snap, thread, address, getManager().getGlobalNamespace()); + default T getGlobalWithNameAt(String name, long snap, Address address) { + return getChildWithNameAt(name, snap, address, getManager().getGlobalNamespace()); } /** * Get symbols in this view intersecting the given box. * * @param span the time bound of the box - * @param thread the thread, if in register space * @param range the address bound of the box * @param includeDynamicSymbols true to include dynamically-generated symbols * @param forward true if the collection should be ordered forward by address, false for * backward by address. * @return the symbols in this view satisfying the query */ - Collection getIntersecting(Lifespan span, TraceThread thread, - AddressRange range, boolean includeDynamicSymbols, boolean forward); + Collection getIntersecting(Lifespan span, AddressRange range, + boolean includeDynamicSymbols, boolean forward); + + /** + * Get symbols in this view intersecting the given register. + * + * @param platform the platform defining the register + * @param span the time bound of the box + * @param thread the thread + * @param register the register + * @param includeDynamicSymbols true to include dynamically-generated symbols + * @param forward true if the collection should be ordered forward by address, false for + * backward by address. + * @return the symbols in this view satisfying the query + */ + default Collection getIntersecting(TracePlatform platform, Lifespan span, + TraceThread thread, Register register, boolean includeDynamicSymbols, boolean forward) { + AddressSpace space = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + if (space == null) { + return List.of(); + } + AddressRange range = platform.getConventionalRegisterRange(space, register); + return getIntersecting(span, range, includeDynamicSymbols, forward); + } + + /** + * Get symbols in this view intersecting the given register. + * + * @param span the time bound of the box + * @param thread the thread + * @param register the register + * @param includeDynamicSymbols true to include dynamically-generated symbols + * @param forward true if the collection should be ordered forward by address, false for + * backward by address. + * @return the symbols in this view satisfying the query + */ + default Collection getIntersecting(Lifespan span, TraceThread thread, + Register register, boolean includeDynamicSymbols, boolean forward) { + return getIntersecting(getTrace().getPlatformManager().getHostPlatform(), span, thread, + register, includeDynamicSymbols, forward); + } /** * Get symbols in this view at the given point. @@ -82,22 +156,62 @@ public interface TraceSymbolWithLocationView extends Trac * The result will be ordered with the primary symbol first. * * @param snap the snapshot key - * @param thread the thread, if in register space * @param address the address of the symbols * @param includeDynamicSymbols true to include dynamically-generated symbols * @return the symbols in this view satisfying the query */ - default Collection getAt(long snap, TraceThread thread, Address address, + default Collection getAt(long snap, Address address, boolean includeDynamicSymbols) { try (LockHold hold = getManager().getTrace().lockRead()) { List result = - new ArrayList<>(getIntersecting(Lifespan.at(snap), thread, + new ArrayList<>(getIntersecting(Lifespan.at(snap), new AddressRangeImpl(address, address), includeDynamicSymbols, true)); result.sort(TraceSymbolManager.PRIMALITY_COMPARATOR); return result; } } + /** + * Get symbols in this view at the given register's min address. + * + *

    + * The result will be ordered with the primary symbol first. + * + * @param platform the platform defining the register + * @param snap the snapshot key + * @param thread the thread + * @param register the register + * @param includeDynamicSymbols true to include dynamically-generated symbols + * @return the symbols in this view satisfying the query + */ + default Collection getAt(TracePlatform platform, long snap, TraceThread thread, + Register register, boolean includeDynamicSymbols) { + AddressSpace space = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + if (space == null) { + return List.of(); + } + AddressRange range = platform.getConventionalRegisterRange(space, register); + return getAt(snap, range.getMinAddress(), includeDynamicSymbols); + } + + /** + * Get symbols in this view at the given register's min address. + * + *

    + * The result will be ordered with the primary symbol first. + * + * @param snap the snapshot key + * @param thread the thread + * @param register the register + * @param includeDynamicSymbols true to include dynamically-generated symbols + * @return the symbols in this view satisfying the query + */ + default Collection getAt(long snap, TraceThread thread, + Register register, boolean includeDynamicSymbols) { + return getAt(getTrace().getPlatformManager().getHostPlatform(), snap, thread, register, + includeDynamicSymbols); + } + /** * Check if this view contains any symbols at the given point. * @@ -107,11 +221,10 @@ public interface TraceSymbolWithLocationView extends Trac * @param includeDynamicSymbols true to include dynamically-generated symbols * @return true if any symbols in this view satisfy the query */ - default boolean hasAt(long snap, TraceThread thread, Address address, - boolean includeDynamicSymbols) { + default boolean hasAt(long snap, Address address, boolean includeDynamicSymbols) { try (LockHold hold = getManager().getTrace().lockRead()) { - return !getIntersecting(Lifespan.at(snap), thread, - new AddressRangeImpl(address, address), includeDynamicSymbols, true).isEmpty(); + return !getIntersecting(Lifespan.at(snap), new AddressRangeImpl(address, address), + includeDynamicSymbols, true).isEmpty(); } } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObject.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObject.java index b937319e08..09004d5641 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObject.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObject.java @@ -18,16 +18,16 @@ package ghidra.trace.model.target; import java.util.Collection; import java.util.stream.Stream; -import ghidra.trace.database.module.TraceObjectSection; import ghidra.trace.model.*; import ghidra.trace.model.Lifespan.LifeSet; import ghidra.trace.model.memory.*; -import ghidra.trace.model.modules.TraceObjectModule; +import ghidra.trace.model.modules.TraceModule; +import ghidra.trace.model.modules.TraceSection; import ghidra.trace.model.target.iface.*; import ghidra.trace.model.target.path.*; import ghidra.trace.model.target.schema.TraceObjectSchema; -import ghidra.trace.model.thread.TraceObjectProcess; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceProcess; +import ghidra.trace.model.thread.TraceThread; /** * A record of a target object in a debugger @@ -72,9 +72,9 @@ import ghidra.trace.model.thread.TraceObjectThread; *

      *
    1. The object itself: Test if the context target object supports the desired interface. * If it does, take it.
    2. - *
    3. Aggregate objects: If the object is marked with {@link TraceObjectAggregate}, collect + *
    4. Aggregate objects: If the object is marked with {@link TraceAggregate}, collect * all attributes supporting the desired interface. If there are any, take them. This step is - * applied recursively if any child attribute is also marked with {@link TraceObjectAggregate}.
    5. + * applied recursively if any child attribute is also marked with {@link TraceAggregate}. *
    6. Ancestry: Apply these same steps to the object's (canonical) parent, recursively.
    7. *
    * @@ -94,37 +94,37 @@ import ghidra.trace.model.thread.TraceObjectThread; *
      *
    • "Session" : {@link TraceObject}
    • *
        - *
      • "Process 789" : {@link TraceObjectProcess}, {@link TraceObjectAggregate}
      • + *
      • "Process 789" : {@link TraceProcess}, {@link TraceAggregate}
      • *
          *
        • "Threads" : {@link TraceObject}
        • *
            - *
          • "Thread 1" : {@link TraceObjectThread}, {@link TraceObjectExecutionStateful}, - * {@link TraceObjectAggregate}
          • + *
          • "Thread 1" : {@link TraceThread}, {@link TraceExecutionStateful}, + * {@link TraceAggregate}
          • *
              - *
            • "Registers" : {@link TraceObjectRegisterContainer}
            • + *
            • "Registers" : {@link TraceRegisterContainer}
            • *
                - *
              • "r1" : {@link TraceObjectRegister}
              • + *
              • "r1" : {@link TraceRegister}
              • *
              • ...
              • *
              *
            *
          • ...more threads
          • *
          - *
        • "Memory" : {@link TraceObjectMemory}
        • + *
        • "Memory" : {@link TraceMemory}
        • *
            - *
          • "[0x00400000:0x00401234]" : {@link TraceObjectMemoryRegion}
          • + *
          • "[0x00400000:0x00401234]" : {@link TraceMemoryRegion}
          • *
          • ...more regions
          • *
          *
        • "Modules" : {@link TraceObject}
        • *
            - *
          • "/usr/bin/echo" : {@link TraceObjectModule}
          • + *
          • "/usr/bin/echo" : {@link TraceModule}
          • *
              - *
            • ".text" : {@link TraceObjectSection}
            • + *
            • ".text" : {@link TraceSection}
            • *
            • ...more sections
            • *
            *
          • ...more modules
          • *
          *
        - *
      • "Environment": {@link TraceObjectEnvironment}
      • + *
      • "Environment": {@link TraceEnvironment}
      • *
          *
        • "Process 321" : {@link TraceObject}
        • *
        • ...more processes
        • @@ -691,7 +691,7 @@ public interface TraceObject extends TraceUniqueObject { * @return true if a method */ default boolean isMethod(long snap) { - if (getSchema().getInterfaces().contains(TraceObjectMethod.class)) { + if (getSchema().getInterfaces().contains(TraceMethod.class)) { return true; } TraceObjectValue extras = getAttribute(snap, TraceObject.EXTRA_INTERFACES_ATTRIBUTE_NAME); @@ -797,12 +797,12 @@ public interface TraceObject extends TraceUniqueObject { * @return the state or null */ default TraceExecutionState getExecutionState(long snap) { - TraceObject stateful = findSuitableInterface(TraceObjectExecutionStateful.class); + TraceObject stateful = findSuitableInterface(TraceExecutionStateful.class); if (stateful == null) { return null; } TraceObjectValue stateVal = - stateful.getAttribute(snap, TraceObjectExecutionStateful.KEY_STATE); + stateful.getAttribute(snap, TraceExecutionStateful.KEY_STATE); if (stateVal == null) { return TraceExecutionState.INACTIVE; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObjectManager.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObjectManager.java index 4cc0e49ed8..5336ee9740 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObjectManager.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/TraceObjectManager.java @@ -62,10 +62,17 @@ public interface TraceObjectManager { /** * Get the schema of the root object * - * @return the schema + * @return the schema or null */ TraceObjectSchema getRootSchema(); + /** + * Get the schema of the root object, failing if no root object exists + * + * @return the schema + */ + TraceObjectSchema requireRootSchema(); + /** * Get the root object, if it has been created * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectActivatable.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceActivatable.java similarity index 96% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectActivatable.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceActivatable.java index 3ec8824faa..6c5dec266c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectActivatable.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceActivatable.java @@ -42,5 +42,5 @@ import ghidra.trace.model.target.info.TraceObjectInfo; shortName = "activatable", attributes = {}, fixedKeys = {}) -public interface TraceObjectActivatable extends TraceObjectInterface { +public interface TraceActivatable extends TraceObjectInterface { } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectAggregate.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceAggregate.java similarity index 87% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectAggregate.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceAggregate.java index a739a0bb0b..e9368dc19d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectAggregate.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceAggregate.java @@ -25,12 +25,12 @@ import ghidra.trace.model.target.info.TraceObjectInfo; * children when visited. * *

          - * TODO: This should be an attribute of the schema, not an interface. + * LATER (GP-5754): This should be an attribute of the schema, not an interface. */ @TraceObjectInfo( schemaName = "Aggregate", shortName = "aggregate", attributes = {}, fixedKeys = {}) -public interface TraceObjectAggregate extends TraceObjectInterface { +public interface TraceAggregate extends TraceObjectInterface { } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectEnvironment.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceEnvironment.java similarity index 85% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectEnvironment.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceEnvironment.java index b4cd03996e..21758d1961 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectEnvironment.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceEnvironment.java @@ -32,17 +32,17 @@ import ghidra.trace.model.target.info.TraceObjectInfo; schemaName = "Environment", shortName = "environment", attributes = { - TraceObjectEnvironment.KEY_ARCH, - TraceObjectEnvironment.KEY_DEBUGGER, - TraceObjectEnvironment.KEY_ENDIAN, - TraceObjectEnvironment.KEY_OS, + TraceEnvironment.KEY_ARCH, + TraceEnvironment.KEY_DEBUGGER, + TraceEnvironment.KEY_ENDIAN, + TraceEnvironment.KEY_OS, }, fixedKeys = {}) -public interface TraceObjectEnvironment extends TraceObjectInterface { +public interface TraceEnvironment extends TraceObjectInterface { String KEY_ARCH = "_arch"; String KEY_DEBUGGER = "_debugger"; String KEY_ENDIAN = "_endian"; String KEY_OS = "_os"; - // TODO: Devices? File System? + // LATER?: Devices, File System } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectEventScope.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceEventScope.java similarity index 87% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectEventScope.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceEventScope.java index fda2619638..85dcf5664d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectEventScope.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceEventScope.java @@ -28,11 +28,11 @@ import ghidra.trace.model.time.schedule.TraceSchedule.ScheduleForm; schemaName = "EventScope", shortName = "event scope", attributes = { - TraceObjectEventScope.KEY_EVENT_THREAD, - TraceObjectEventScope.KEY_TIME_SUPPORT, + TraceEventScope.KEY_EVENT_THREAD, + TraceEventScope.KEY_TIME_SUPPORT, }, fixedKeys = {}) -public interface TraceObjectEventScope extends TraceObjectInterface { +public interface TraceEventScope extends TraceObjectInterface { String KEY_EVENT_THREAD = "_event_thread"; /** See {@link ScheduleForm} */ String KEY_TIME_SUPPORT = "_time_support"; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectExecutionStateful.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceExecutionStateful.java similarity index 87% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectExecutionStateful.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceExecutionStateful.java index 079aa31df9..5ac1d9f2c9 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectExecutionStateful.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceExecutionStateful.java @@ -21,9 +21,9 @@ import ghidra.trace.model.target.info.TraceObjectInfo; schemaName = "ExecutionStateful", shortName = "exec stateful", attributes = { - TraceObjectExecutionStateful.KEY_STATE + TraceExecutionStateful.KEY_STATE }, fixedKeys = {}) -public interface TraceObjectExecutionStateful extends TraceObjectInterface { +public interface TraceExecutionStateful extends TraceObjectInterface { String KEY_STATE = "_state"; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectFocusScope.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceFocusScope.java similarity index 91% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectFocusScope.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceFocusScope.java index 2a14f52d14..f2d0e6184e 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectFocusScope.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceFocusScope.java @@ -32,9 +32,9 @@ import ghidra.trace.model.target.info.TraceObjectInfo; schemaName = "FocusScope", shortName = "focus scope", attributes = { - TraceObjectFocusScope.KEY_FOCUS, + TraceFocusScope.KEY_FOCUS, }, fixedKeys = {}) -public interface TraceObjectFocusScope extends TraceObjectInterface { +public interface TraceFocusScope extends TraceObjectInterface { String KEY_FOCUS = "_focus"; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectMethod.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceMethod.java similarity index 98% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectMethod.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceMethod.java index 1529f6e1e1..d04561c5c0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectMethod.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceMethod.java @@ -41,10 +41,10 @@ import ghidra.trace.model.target.info.TraceObjectInfo; schemaName = "Method", shortName = "method", attributes = { - // TODO: Parameter map, return type? + // LATER?: Parameter map, return type }, fixedKeys = {}) -public interface TraceObjectMethod extends TraceObjectInterface { +public interface TraceMethod extends TraceObjectInterface { interface Value { boolean specified(); @@ -467,7 +467,7 @@ public interface TraceObjectMethod extends TraceObjectInterface { * *

          * You must validate the arguments, using - * {@link TraceObjectMethod#validateArguments(Map, Map, boolean)}, first. + * {@link TraceMethod#validateArguments(Map, Map, boolean)}, first. * * @param arguments the validated arguments * @return the parameter diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectInterface.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectInterface.java index b173320f66..14148439c6 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectInterface.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectInterface.java @@ -17,11 +17,11 @@ package ghidra.trace.model.target.iface; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.info.TraceObjectInfo; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; /** * A common interface for object-based implementations of other trace manager entries, e.g., - * {@link TraceObjectThread}. + * {@link TraceThread}. */ @TraceObjectInfo( schemaName = "OBJECT", diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectTogglable.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceTogglable.java similarity index 89% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectTogglable.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceTogglable.java index 251fa84de2..216a9ba5a8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceObjectTogglable.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/iface/TraceTogglable.java @@ -24,9 +24,9 @@ import ghidra.trace.model.target.info.TraceObjectInfo; schemaName = "Togglable", shortName = "togglable", attributes = { - TraceObjectTogglable.KEY_ENABLED, + TraceTogglable.KEY_ENABLED, }, fixedKeys = {}) -public interface TraceObjectTogglable extends TraceObjectInterface { +public interface TraceTogglable extends TraceObjectInterface { String KEY_ENABLED = "_enabled"; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/info/BuiltinTraceObjectInterfaceFactory.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/info/BuiltinTraceObjectInterfaceFactory.java index 8114123e2d..3d1b87ae6a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/info/BuiltinTraceObjectInterfaceFactory.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/info/BuiltinTraceObjectInterfaceFactory.java @@ -19,48 +19,50 @@ import static ghidra.trace.model.target.info.TraceObjectInterfaceFactory.ctor; import java.util.List; -import ghidra.trace.database.breakpoint.DBTraceObjectBreakpointLocation; -import ghidra.trace.database.breakpoint.DBTraceObjectBreakpointSpec; +import ghidra.trace.database.breakpoint.DBTraceBreakpointLocation; +import ghidra.trace.database.breakpoint.DBTraceBreakpointSpec; import ghidra.trace.database.memory.*; -import ghidra.trace.database.module.*; -import ghidra.trace.database.stack.DBTraceObjectStack; -import ghidra.trace.database.stack.DBTraceObjectStackFrame; +import ghidra.trace.database.module.DBTraceModule; +import ghidra.trace.database.module.DBTraceSection; +import ghidra.trace.database.stack.DBTraceStack; +import ghidra.trace.database.stack.DBTraceStackFrame; import ghidra.trace.database.target.iface.*; import ghidra.trace.database.thread.DBTraceObjectProcess; -import ghidra.trace.database.thread.DBTraceObjectThread; -import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation; -import ghidra.trace.model.breakpoint.TraceObjectBreakpointSpec; +import ghidra.trace.database.thread.DBTraceThread; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.breakpoint.TraceBreakpointSpec; import ghidra.trace.model.memory.*; -import ghidra.trace.model.modules.TraceObjectModule; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.modules.TraceModule; +import ghidra.trace.model.modules.TraceSection; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.iface.*; -import ghidra.trace.model.thread.TraceObjectProcess; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceProcess; +import ghidra.trace.model.thread.TraceThread; public class BuiltinTraceObjectInterfaceFactory implements TraceObjectInterfaceFactory { private static final List> BUILTINS = List.of( - ctor(TraceObjectActivatable.class, DBTraceObjectActivatable::new), - ctor(TraceObjectAggregate.class, DBTraceObjectAggregate::new), - ctor(TraceObjectBreakpointLocation.class, DBTraceObjectBreakpointLocation::new), - ctor(TraceObjectBreakpointSpec.class, DBTraceObjectBreakpointSpec::new), - ctor(TraceObjectEnvironment.class, DBTraceObjectEnvironment::new), - ctor(TraceObjectEventScope.class, DBTraceObjectEventScope::new), - ctor(TraceObjectExecutionStateful.class, DBTraceObjectExecutionStateful::new), - ctor(TraceObjectFocusScope.class, DBTraceObjectFocusScope::new), - ctor(TraceObjectMemory.class, DBTraceObjectMemory::new), - ctor(TraceObjectMemoryRegion.class, DBTraceObjectMemoryRegion::new), - ctor(TraceObjectMethod.class, DBTraceObjectMethod::new), - ctor(TraceObjectModule.class, DBTraceObjectModule::new), - ctor(TraceObjectProcess.class, DBTraceObjectProcess::new), - ctor(TraceObjectRegister.class, DBTraceObjectRegister::new), - ctor(TraceObjectRegisterContainer.class, DBTraceObjectRegisterContainer::new), - ctor(TraceObjectSection.class, DBTraceObjectSection::new), - ctor(TraceObjectStack.class, DBTraceObjectStack::new), - ctor(TraceObjectStackFrame.class, DBTraceObjectStackFrame::new), - ctor(TraceObjectThread.class, DBTraceObjectThread::new), - ctor(TraceObjectTogglable.class, DBTraceObjectTogglable::new)); + ctor(TraceActivatable.class, DBTraceObjectActivatable::new), + ctor(TraceAggregate.class, DBTraceObjectAggregate::new), + ctor(TraceBreakpointLocation.class, DBTraceBreakpointLocation::new), + ctor(TraceBreakpointSpec.class, DBTraceBreakpointSpec::new), + ctor(TraceEnvironment.class, DBTraceObjectEnvironment::new), + ctor(TraceEventScope.class, DBTraceObjectEventScope::new), + ctor(TraceExecutionStateful.class, DBTraceObjectExecutionStateful::new), + ctor(TraceFocusScope.class, DBTraceObjectFocusScope::new), + ctor(TraceMemory.class, DBTraceObjectMemory::new), + ctor(TraceMemoryRegion.class, DBTraceMemoryRegion::new), + ctor(TraceMethod.class, DBTraceObjectMethod::new), + ctor(TraceModule.class, DBTraceModule::new), + ctor(TraceProcess.class, DBTraceObjectProcess::new), + ctor(TraceRegister.class, DBTraceObjectRegister::new), + ctor(TraceRegisterContainer.class, DBTraceObjectRegisterContainer::new), + ctor(TraceSection.class, DBTraceSection::new), + ctor(TraceStack.class, DBTraceStack::new), + ctor(TraceStackFrame.class, DBTraceStackFrame::new), + ctor(TraceThread.class, DBTraceThread::new), + ctor(TraceTogglable.class, DBTraceObjectTogglable::new)); @Override public List> getInterfaceConstructors() { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/DefaultSchemaContext.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/DefaultSchemaContext.java index ca3ac325b6..6273fe9010 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/DefaultSchemaContext.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/DefaultSchemaContext.java @@ -32,10 +32,27 @@ public class DefaultSchemaContext implements SchemaContext { } } + public DefaultSchemaContext(SchemaContext ctx) { + this(); + for (TraceObjectSchema schema : ctx.getAllSchemas()) { + if (!(schema instanceof PrimitiveTraceObjectSchema)) { + this.builder(schema).buildAndAdd(); + } + } + } + + public SchemaBuilder builder(TraceObjectSchema schema) { + return new SchemaBuilder(this, schema); + } + public SchemaBuilder builder(SchemaName name) { return new SchemaBuilder(this, name); } + public SchemaBuilder modify(SchemaName name) { + return new SchemaBuilder(this, getSchema(name)); + } + public synchronized void putSchema(TraceObjectSchema schema) { if (schemas.containsKey(schema.getName())) { throw new IllegalArgumentException("Name already in context: " + schema.getName()); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/SchemaBuilder.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/SchemaBuilder.java index 234c4f3b02..7e87b546ac 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/SchemaBuilder.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/SchemaBuilder.java @@ -244,6 +244,12 @@ public class SchemaBuilder { return schema; } + public TraceObjectSchema buildAndReplace() { + TraceObjectSchema schema = build(); + context.replaceSchema(schema); + return schema; + } + public TraceObjectSchema build() { return new DefaultTraceObjectSchema( context, name, type, interfaces, isCanonicalContainer, diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java index 6a49ac738e..689fc389c8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java @@ -21,11 +21,11 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.memory.TraceObjectRegisterContainer; -import ghidra.trace.model.stack.TraceObjectStack; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.memory.TraceRegisterContainer; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectAggregate; +import ghidra.trace.model.target.iface.TraceAggregate; import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.path.*; import ghidra.trace.model.target.schema.DefaultTraceObjectSchema.DefaultAttributeSchema; @@ -555,7 +555,7 @@ public interface TraceObjectSchema { @Override public boolean descendAttributes(SearchEntry ent) { - return ent.schema.getInterfaces().contains(TraceObjectAggregate.class); + return ent.schema.getInterfaces().contains(TraceAggregate.class); } @Override @@ -599,7 +599,7 @@ public interface TraceObjectSchema { if (!visited.add(sch)) { return; } - if (requireAggregate && !sch.getInterfaces().contains(TraceObjectAggregate.class)) { + if (requireAggregate && !sch.getInterfaces().contains(TraceAggregate.class)) { return; } SchemaContext ctx = sch.getContext(); @@ -1009,18 +1009,17 @@ public interface TraceObjectSchema { * *

          * This places some conventional restrictions / expectations on models where registers are given - * on a frame-by-frame basis. The schema should present the {@link TraceObjectRegisterContainer} - * as the same object or a successor to {@link TraceObjectStackFrame}, which must in turn be a - * successor to {@link TraceObjectStack}. The frame level (an index) must be in the path from - * stack to frame. There can be no wildcards between the frame and the register container. For - * example, the container for {@code Threads[1]} may be {@code Threads[1].Stack[n].Registers}, - * where {@code n} is the frame level. {@code Threads[1].Stack} would have the - * {@link TraceObjectStack} interface, {@code Threads[1].Stack[0]} would have the - * {@link TraceObjectStackFrame} interface, and {@code Threads[1].Stack[0].Registers} would have - * the {@link TraceObjectRegisterContainer} interface. Note it is not sufficient for - * {@link TraceObjectRegisterContainer} to be a successor of {@link TraceObjectStack} with a - * single index between. There must be an intervening {@link TraceObjectStackFrame}, - * and the frame level (index) must precede it. + * on a frame-by-frame basis. The schema should present the {@link TraceRegisterContainer} + * as the same object or a successor to {@link TraceStackFrame}, which must in turn be a + * successor to {@link TraceStack}. The frame level (an index) must be in the path from stack to + * frame. There can be no wildcards between the frame and the register container. For example, + * the container for {@code Threads[1]} may be {@code Threads[1].Stack[n].Registers}, where + * {@code n} is the frame level. {@code Threads[1].Stack} would have the {@link TraceStack} + * interface, {@code Threads[1].Stack[0]} would have the {@link TraceStackFrame} interface, and + * {@code Threads[1].Stack[0].Registers} would have the {@link TraceRegisterContainer} + * interface. Note it is not sufficient for {@link TraceRegisterContainer} to be a + * successor of {@link TraceStack} with a single index between. There must be an + * intervening {@link TraceStackFrame}, and the frame level (index) must precede it. * * @param frameLevel the frame level. May be ignored if not applicable * @param path the path of the seed object relative to the root @@ -1028,16 +1027,16 @@ public interface TraceObjectSchema { * {@link PathFilter#NONE} */ default PathFilter searchForRegisterContainer(int frameLevel, KeyPath path) { - KeyPath simple = searchForSuitable(TraceObjectRegisterContainer.class, path); + KeyPath simple = searchForSuitable(TraceRegisterContainer.class, path); if (simple != null) { return PathFilter.pattern(simple); } - KeyPath stackPath = searchForSuitable(TraceObjectStack.class, path); + KeyPath stackPath = searchForSuitable(TraceStack.class, path); if (stackPath == null) { return PathFilter.NONE; } PathPattern framePatternRelStack = - getSuccessorSchema(stackPath).searchFor(TraceObjectStackFrame.class, false) + getSuccessorSchema(stackPath).searchFor(TraceStackFrame.class, false) .getSingletonPattern(); if (framePatternRelStack == null) { return PathFilter.NONE; @@ -1053,7 +1052,7 @@ public interface TraceObjectSchema { KeyPath framePathRelStack = framePatternRelStack.applyKeys(index).getSingletonPath(); KeyPath framePath = stackPath.extend(framePathRelStack); - KeyPath regsPath = searchForSuitable(TraceObjectRegisterContainer.class, framePath); + KeyPath regsPath = searchForSuitable(TraceRegisterContainer.class, framePath); if (regsPath != null) { patterns.add(new PathPattern(regsPath)); } @@ -1065,11 +1064,11 @@ public interface TraceObjectSchema { * Compute the frame level of the object at the given path relative to this schema * *

          - * If there is no {@link TraceObjectStackFrame} in the path, this will return 0 since it is not + * If there is no {@link TraceStackFrame} in the path, this will return 0 since it is not * applicable to the object. If there is a stack frame in the path, this will examine its - * ancestry, up to and excluding the {@link TraceObjectStack} for an index. If there isn't a - * stack in the path, it is assumed to be an ancestor of this schema, meaning the examination - * will exhaust the ancestry provided in the path. If no index is found, an exception is thrown, + * ancestry, up to and excluding the {@link TraceStack} for an index. If there isn't a stack in + * the path, it is assumed to be an ancestor of this schema, meaning the examination will + * exhaust the ancestry provided in the path. If no index is found, an exception is thrown, * because the frame level is applicable, but couldn't be computed from the path given. In that * case, the client should include more ancestry in the path. Ideally, this is invoked relative * to the root schema. @@ -1079,11 +1078,11 @@ public interface TraceObjectSchema { * @throws IllegalArgumentException if frame level is applicable but not given in the path */ default int computeFrameLevel(KeyPath path) { - KeyPath framePath = searchForAncestor(TraceObjectStackFrame.class, path); + KeyPath framePath = searchForAncestor(TraceStackFrame.class, path); if (framePath == null) { return 0; } - KeyPath stackPath = searchForAncestor(TraceObjectStack.class, framePath); + KeyPath stackPath = searchForAncestor(TraceStack.class, framePath); for (int i = stackPath == null ? 0 : stackPath.size(); i < framePath.size(); i++) { String key = framePath.key(i); if (KeyPath.isIndex(key)) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceObjectThread.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceObjectThread.java deleted file mode 100644 index 625ff91bdd..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceObjectThread.java +++ /dev/null @@ -1,44 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.model.thread; - -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.iface.TraceObjectExecutionStateful; -import ghidra.trace.model.target.iface.TraceObjectInterface; -import ghidra.trace.model.target.info.TraceObjectInfo; - -/** - * A marker interface which indicates a thread, usually within a process - * - *

          - * This object must be associated with a suitable {@link TraceObjectExecutionStateful}. In most - * cases, the object should just implement it. - */ -@TraceObjectInfo( - schemaName = "Thread", - shortName = "thread", - attributes = { - TraceObjectThread.KEY_TID, - }, - fixedKeys = { - TraceObjectInterface.KEY_DISPLAY, - TraceObjectInterface.KEY_COMMENT, - }) -public interface TraceObjectThread extends TraceThread, TraceObjectInterface { - String KEY_TID = "_tid"; - - void setName(Lifespan lifespan, String name); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceObjectProcess.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceProcess.java similarity index 76% rename from Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceObjectProcess.java rename to Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceProcess.java index a929f412ca..b80f079c13 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceObjectProcess.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceProcess.java @@ -16,7 +16,7 @@ package ghidra.trace.model.thread; import ghidra.trace.model.TraceExecutionState; -import ghidra.trace.model.target.iface.TraceObjectExecutionStateful; +import ghidra.trace.model.target.iface.TraceExecutionStateful; import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.info.TraceObjectInfo; @@ -24,18 +24,18 @@ import ghidra.trace.model.target.info.TraceObjectInfo; * A marker interface which indicates a process, usually on a host operating system * *

          - * If this object does not support {@link TraceObjectExecutionStateful}, then its mere existence in + * If this object does not support {@link TraceExecutionStateful}, then its mere existence in * the model implies that it is {@link TraceExecutionState#ALIVE}. TODO: Should allow association - * via convention to a different {@link TraceObjectExecutionStateful}, but that may have to wait + * via convention to a different {@link TraceExecutionStateful}, but that may have to wait * until schemas are introduced. */ @TraceObjectInfo( schemaName = "Process", shortName = "process", attributes = { - TraceObjectProcess.KEY_PID, + TraceProcess.KEY_PID, }, fixedKeys = {}) -public interface TraceObjectProcess extends TraceObjectInterface { +public interface TraceProcess extends TraceObjectInterface { String KEY_PID = "_pid"; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceThread.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceThread.java index 09538bdd69..cd28aab04a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceThread.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/thread/TraceThread.java @@ -19,11 +19,30 @@ import java.util.List; import ghidra.program.model.lang.Register; import ghidra.trace.model.*; +import ghidra.trace.model.target.iface.TraceExecutionStateful; +import ghidra.trace.model.target.iface.TraceObjectInterface; +import ghidra.trace.model.target.info.TraceObjectInfo; /** * A thread in a trace + * + *

          + * This object must be associated with a suitable {@link TraceExecutionStateful}. In most + * cases, the object should just implement it. */ -public interface TraceThread extends TraceUniqueObject { +@TraceObjectInfo( + schemaName = "Thread", + shortName = "thread", + attributes = { + TraceThread.KEY_TID, + }, + fixedKeys = { + TraceObjectInterface.KEY_DISPLAY, + TraceObjectInterface.KEY_COMMENT, + }) +public interface TraceThread extends TraceUniqueObject, TraceObjectInterface { + /** The key that gives the TID, as assigned by the target's platform */ + String KEY_TID = "_tid"; /** * Get the trace containing this thread @@ -57,7 +76,15 @@ public interface TraceThread extends TraceUniqueObject { /** * Set the "short name" of this thread * - * @param snap the snap + * @param lifespan the span of time + * @param name the name + */ + void setName(Lifespan lifespan, String name); + + /** + * Set the "short name" of this thread + * + * @param snap the starting snap * @param name the name */ void setName(long snap, String name); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Step.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Step.java index 603b9102db..08067cf1a3 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Step.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/Step.java @@ -106,19 +106,23 @@ public interface Step extends Comparable { return getThreadKey() == -1; } - default TraceThread getThread(TraceThreadManager tm, TraceThread eventThread) { - TraceThread thread = isEventThread() ? eventThread : tm.getThread(getThreadKey()); + static TraceThread requireThread(TraceThread thread, long key) { if (thread == null) { - if (isEventThread()) { + if (key == -1) { throw new IllegalArgumentException("Thread must be given, e.g., 0:t1-3, " + "since the last thread or snapshot event thread is not given."); } throw new IllegalArgumentException( - "Thread with key " + getThreadKey() + " does not exist in given trace"); + "Thread with key %d does not exist in given trace".formatted(key)); } return thread; } + default TraceThread getThread(TraceThreadManager tm, TraceThread eventThread) { + long key = getThreadKey(); + return requireThread(isEventThread() ? eventThread : tm.getThread(key), key); + } + long getTickCount(); long getSkipCount(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/TraceSchedule.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/TraceSchedule.java index 0bb79e511d..2a9c21e31d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/TraceSchedule.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/time/schedule/TraceSchedule.java @@ -530,10 +530,9 @@ public class TraceSchedule implements Comparable { */ public TraceThread getLastThread(Trace trace) { long lastKey = getLastThreadKey(); - if (lastKey == -1) { - return getEventThread(trace); - } - return trace.getThreadManager().getThread(lastKey); + return Step.requireThread( + lastKey == -1 ? getEventThread(trace) : trace.getThreadManager().getThread(lastKey), + lastKey); } /** diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/CopyOnWrite.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/CopyOnWrite.java index 9d2936d269..2ecf04f6a9 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/CopyOnWrite.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/CopyOnWrite.java @@ -4,9 +4,9 @@ * 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. @@ -148,7 +148,7 @@ public interface CopyOnWrite { } /** - * Assumes elements use system hash equality, i.e., {@link E#equals()} is ignored + * Assumes elements use system hash equality, i.e., {@link E#equals(Object)} is ignored * * @param the type of element in the weak set */ diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceAddressSpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceAddressSpace.java deleted file mode 100644 index e35e0eef48..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceAddressSpace.java +++ /dev/null @@ -1,36 +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.util; - -import ghidra.program.model.address.AddressSpace; -import ghidra.trace.model.thread.TraceThread; - -/** - * Identify the "full" address space in a trace. - * - *

          - * Whenever the address space is {@code register}, then the thread and frame level become necessary - * to uniquely identify it. This will be deprecated when either, 1) unique register overlay spaces - * are created for each thread/frame, or 2) register values are fully transitioned to object model - * storage. - */ -public interface TraceAddressSpace { - AddressSpace getAddressSpace(); - - TraceThread getThread(); - - int getFrameLevel(); -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceChangeRecord.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceChangeRecord.java index 2d1e5aebb8..f9e0582bb7 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceChangeRecord.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceChangeRecord.java @@ -4,9 +4,9 @@ * 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. @@ -16,15 +16,16 @@ package ghidra.trace.util; import ghidra.framework.model.DomainObjectChangeRecord; +import ghidra.program.model.address.AddressSpace; public class TraceChangeRecord extends DomainObjectChangeRecord { private static final long serialVersionUID = 1; - private final TraceAddressSpace space; + private final AddressSpace space; private final T affectedObject; private final boolean oldKnown; - public TraceChangeRecord(TraceEvent type, TraceAddressSpace space, T affectedObject, + public TraceChangeRecord(TraceEvent type, AddressSpace space, T affectedObject, U oldValue, U newValue) { super(type, oldValue, newValue); this.space = space; @@ -32,7 +33,7 @@ public class TraceChangeRecord extends DomainObjectChangeRecord { this.oldKnown = true; } - public TraceChangeRecord(TraceEvent type, TraceAddressSpace space, T affectedObject, + public TraceChangeRecord(TraceEvent type, AddressSpace space, T affectedObject, U newValue) { super(type, null, newValue); this.space = space; @@ -40,22 +41,21 @@ public class TraceChangeRecord extends DomainObjectChangeRecord { this.oldKnown = false; } - public TraceChangeRecord(TraceEvent type, TraceAddressSpace space, - T affectedObject) { + public TraceChangeRecord(TraceEvent type, AddressSpace space, T affectedObject) { super(type, null, null); this.space = space; this.affectedObject = affectedObject; this.oldKnown = false; } - public TraceChangeRecord(TraceEvent type, TraceAddressSpace space) { + public TraceChangeRecord(TraceEvent type, AddressSpace space) { super(type, null, null); this.space = space; this.affectedObject = null; this.oldKnown = false; } - public TraceAddressSpace getSpace() { + public AddressSpace getAddressSpace() { return space; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvent.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvent.java index 7b915438d5..8f1a318f8b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvent.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvent.java @@ -4,9 +4,9 @@ * 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. @@ -25,7 +25,7 @@ import ghidra.program.model.symbol.SourceType; import ghidra.trace.model.*; import ghidra.trace.model.bookmark.TraceBookmark; import ghidra.trace.model.bookmark.TraceBookmarkType; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TraceGuestPlatformMappedRange; import ghidra.trace.model.listing.*; @@ -138,7 +138,7 @@ public interface TraceEvent extends EventType { } } - enum TraceBreakpointEvent implements TraceEvent { + enum TraceBreakpointEvent implements TraceEvent { BREAKPOINT_ADDED, BREAKPOINT_CHANGED, BREAKPOINT_DELETED; private final int id = DomainObjectEventIdGenerator.next(); @@ -149,7 +149,7 @@ public interface TraceEvent extends EventType { } } - enum TraceBreakpointLifespanEvent implements TraceEvent { + enum TraceBreakpointLifespanEvent implements TraceEvent { BREAKPOINT_LIFESPAN_CHANGED; private final int id = DomainObjectEventIdGenerator.next(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvents.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvents.java index 607bc3ff10..3117b995d1 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvents.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceEvents.java @@ -23,7 +23,7 @@ import ghidra.program.model.listing.ProgramFragment; import ghidra.trace.model.Trace; import ghidra.trace.model.bookmark.TraceBookmark; import ghidra.trace.model.bookmark.TraceBookmarkType; -import ghidra.trace.model.breakpoint.TraceBreakpoint; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TraceGuestPlatformMappedRange; import ghidra.trace.model.listing.*; @@ -81,14 +81,14 @@ public interface TraceEvents { /** A {@link TraceBookmark} was deleted */ TraceBookmarkEvent BOOKMARK_DELETED = TraceBookmarkEvent.BOOKMARK_DELETED; - /** A {@link TraceBreakpoint} was added */ + /** A {@link TraceBreakpointLocation} was added */ TraceBreakpointEvent BREAKPOINT_ADDED = TraceBreakpointEvent.BREAKPOINT_ADDED; - /** A {@link TraceBreakpoint} was changed */ + /** A {@link TraceBreakpointLocation} was changed */ TraceBreakpointEvent BREAKPOINT_CHANGED = TraceBreakpointEvent.BREAKPOINT_CHANGED; - /** A {@link TraceBreakpoint}'s lifespan was changed */ + /** A {@link TraceBreakpointLocation}'s lifespan was changed */ TraceBreakpointLifespanEvent BREAKPOINT_LIFESPAN_CHANGED = TraceBreakpointLifespanEvent.BREAKPOINT_LIFESPAN_CHANGED; - /** A {@link TraceBreakpoint} was deleted */ + /** A {@link TraceBreakpointLocation} was deleted */ TraceBreakpointEvent BREAKPOINT_DELETED = TraceBreakpointEvent.BREAKPOINT_DELETED; /** A {@link Category} was added. The {@code long} is the category id. */ diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java index bd2dd24d3b..414cafc6c9 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceRegisterUtils.java @@ -4,9 +4,9 @@ * 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. @@ -26,10 +26,14 @@ import ghidra.pcode.utils.Utils; import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.lang.*; +import ghidra.trace.model.Trace; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.listing.TraceData; -import ghidra.trace.model.memory.TraceMemorySpace; -import ghidra.trace.model.memory.TraceMemoryState; +import ghidra.trace.model.memory.*; +import ghidra.trace.model.stack.TraceStackFrame; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.path.KeyPath; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.OverlappingObjectIterator.Ranger; public enum TraceRegisterUtils { @@ -38,8 +42,7 @@ public enum TraceRegisterUtils { private static class RegisterIndex { // Could this all go into RegisterManager instead? // Would need the overlapping object iterator, or replacement, moved up - private record RegEntry(AddressRange base, Set regs) { - } + private record RegEntry(AddressRange base, Set regs) {} private static final Ranger ENTRY_RANGER = new Ranger<>() { @Override @@ -295,4 +298,73 @@ public enum TraceRegisterUtils { "Cannot work with sub-byte registers. Consider a parent instead."); } } + + public static TraceRegisterContainer getRegisterContainer(TraceThread thread, int frameLevel) { + return getRegisterContainer(thread.getObject(), frameLevel); + } + + public static TraceRegisterContainer getRegisterContainer(TraceStackFrame frame) { + // Use frameLevel = 0, because we're already in the frame + // so, no wild cards between here and registers + return getRegisterContainer(frame.getObject(), 0); + } + + public static TraceRegisterContainer getRegisterContainer(TraceObject object, int frameLevel) { + if (object.getSchema() + .getInterfaces() + .contains(TraceRegisterContainer.class)) { + return object.queryInterface(TraceRegisterContainer.class); + } + TraceObject contObj = object.findRegisterContainer(frameLevel); + return contObj == null ? null : contObj.queryInterface(TraceRegisterContainer.class); + } + + public static AddressSpace getRegisterAddressSpace(TraceRegisterContainer cont, + boolean createIfAbsent) { + TraceObject object = cont.getObject(); + Trace trace = object.getTrace(); + String name = object.getCanonicalPath().toString(); + AddressSpace regSpace = trace.getBaseAddressFactory().getRegisterSpace(); + if (createIfAbsent) { + return trace.getMemoryManager().getOrCreateOverlayAddressSpace(name, regSpace); + } + return trace.getBaseAddressFactory().getAddressSpace(name); + } + + public static AddressSpace getRegisterAddressSpace(TraceThread thread, int frameLevel, + boolean createIfAbsent) { + return getRegisterAddressSpace(getRegisterContainer(thread, frameLevel), createIfAbsent); + } + + public static AddressSpace getRegisterAddressSpace(TraceStackFrame frame, + boolean createIfAbsent) { + return getRegisterAddressSpace(getRegisterContainer(frame), createIfAbsent); + } + + public static TraceThread getThread(Trace trace, AddressSpace space) { + if (space.isMemorySpace()) { + return null; + } + TraceObject regs = trace.getObjectManager() + .getObjectByCanonicalPath(KeyPath.parse(space.getName())); + if (regs == null) { + return null; + } + return regs.queryCanonicalAncestorsInterface(TraceThread.class).findAny().orElse(null); + } + + public static int getFrameLevel(Trace trace, AddressSpace space) { + if (space.isMemorySpace()) { + return 0; + } + TraceObject regs = trace.getObjectManager() + .getObjectByCanonicalPath(KeyPath.parse(space.getName())); + if (regs == null) { + return 0; + } + return regs.queryCanonicalAncestorsInterface(TraceStackFrame.class) + .findAny() + .map(r -> r.getLevel()) + .orElse(0); + } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceSpaceMixin.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceSpaceMixin.java new file mode 100644 index 0000000000..1deabcedea --- /dev/null +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TraceSpaceMixin.java @@ -0,0 +1,63 @@ +/* ### + * 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.util; + +import ghidra.program.model.address.AddressSpace; +import ghidra.trace.model.Trace; +import ghidra.trace.model.thread.TraceThread; + +/** + * Add conveniences for getting the thread and frame level, if applicable, from an object's address + * space. + */ +public interface TraceSpaceMixin { + /** + * Get the trace containing the object + * + * @return the trace + */ + Trace getTrace(); + + /** + * Get the object's address space + * + * @return the address space + */ + AddressSpace getAddressSpace(); + + /** + * Get the thread denoted by the object's address space + * + * @return the thread + */ + default TraceThread getThread() { + return TraceRegisterUtils.getThread(getTrace(), getAddressSpace()); + } + + /** + * Get the frame level denoted by the object's address space + * + *

          + * Note this will return 0 if the frame level is not applicable. This is the same as the + * innermost frame level when it is applicable. To distinguish whether or not a 0 return value + * is applicable, you must examine the path or schema. + * + * @return the level or 0 + */ + default int getFrameLevel() { + return TraceRegisterUtils.getFrameLevel(getTrace(), getAddressSpace()); + } +} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TypedEventDispatcher.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TypedEventDispatcher.java index 560ffc8c14..92dd41c16b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TypedEventDispatcher.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/TypedEventDispatcher.java @@ -4,9 +4,9 @@ * 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. @@ -20,6 +20,7 @@ import java.util.Map; import java.util.function.Consumer; import ghidra.framework.model.*; +import ghidra.program.model.address.AddressSpace; public class TypedEventDispatcher { @@ -28,21 +29,21 @@ public class TypedEventDispatcher { } public interface FullEventRecordHandler extends EventRecordHandler { - void handle(TraceAddressSpace space, T affectedObject, U oldValue, U newValue); + void handle(AddressSpace space, T affectedObject, U oldValue, U newValue); @Override default void handle(TraceChangeRecord record) { - handle(record.getSpace(), record.getAffectedObject(), record.getOldValue(), + handle(record.getAddressSpace(), record.getAffectedObject(), record.getOldValue(), record.getNewValue()); } } public interface AffectedObjectHandler extends EventRecordHandler { - void handle(TraceAddressSpace space, T affectedObject); + void handle(AddressSpace space, T affectedObject); @Override default void handle(TraceChangeRecord record) { - handle(record.getSpace(), record.getAffectedObject()); + handle(record.getAddressSpace(), record.getAffectedObject()); } } @@ -65,11 +66,11 @@ public class TypedEventDispatcher { } public interface SpaceValuesHandler extends EventRecordHandler { - void handle(TraceAddressSpace space, U oldValue, U newValue); + void handle(AddressSpace space, U oldValue, U newValue); @Override default void handle(TraceChangeRecord record) { - handle(record.getSpace(), record.getOldValue(), record.getNewValue()); + handle(record.getAddressSpace(), record.getOldValue(), record.getNewValue()); } } @@ -83,11 +84,11 @@ public class TypedEventDispatcher { } public interface IgnoreValuesHandler extends EventRecordHandler { - void handle(TraceAddressSpace space); + void handle(AddressSpace space); @Override default void handle(TraceChangeRecord record) { - handle(record.getSpace()); + handle(record.getAddressSpace()); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/dbg/target/schema/XmlTargetObjectSchemaTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/dbg/target/schema/XmlTargetObjectSchemaTest.java index f4b598eb87..32b9b5a01a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/dbg/target/schema/XmlTargetObjectSchemaTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/dbg/target/schema/XmlTargetObjectSchemaTest.java @@ -15,7 +15,8 @@ */ package ghidra.dbg.target.schema; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import java.io.IOException; @@ -23,12 +24,12 @@ import org.jdom.JDOMException; import org.junit.Ignore; import org.junit.Test; -import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.schema.*; import ghidra.trace.model.target.schema.DefaultTraceObjectSchema.DefaultAttributeSchema; import ghidra.trace.model.target.schema.TraceObjectSchema.*; -import ghidra.trace.model.thread.TraceObjectProcess; +import ghidra.trace.model.thread.TraceProcess; public class XmlTargetObjectSchemaTest { protected static final String SCHEMA_XML = @@ -52,7 +53,7 @@ public class XmlTargetObjectSchemaTest { protected static final SchemaName NAME_ROOT = new SchemaName("root"); protected static final SchemaName NAME_DOWN1 = new SchemaName("down1"); protected static final TraceObjectSchema SCHEMA_ROOT = CTX.builder(NAME_ROOT) - .addInterface(TraceObjectProcess.class) + .addInterface(TraceProcess.class) .setCanonicalContainer(true) .addElementSchema("reserved", PrimitiveTraceObjectSchema.VOID.getName(), null) .addElementSchema("", NAME_DOWN1, null) @@ -107,7 +108,7 @@ public class XmlTargetObjectSchemaTest { """); KeyPath found = ctx.getSchema(new SchemaName("root")) - .searchForSuitable(TraceObjectBreakpointLocation.class, KeyPath.ROOT); + .searchForSuitable(TraceBreakpointLocation.class, KeyPath.ROOT); assertNotNull(found); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/AbstractTracePcodeEmulatorTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/AbstractTracePcodeEmulatorTest.java index ed50d4654a..969dd02a9b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/AbstractTracePcodeEmulatorTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/AbstractTracePcodeEmulatorTest.java @@ -4,9 +4,9 @@ * 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. @@ -26,9 +26,11 @@ import ghidra.program.model.address.AddressRange; import ghidra.program.model.listing.Instruction; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceMemoryManager; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; import ghidra.util.Msg; @@ -40,6 +42,13 @@ public class AbstractTracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegr stateInit, assembly); } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .useRegistersPerFrame() + .noRegisterGroups() + .build(); + } + /** * Build a trace with a program ready for emulation * @@ -52,6 +61,8 @@ public class AbstractTracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegr * memory where it was assembled. * * @param tb the trace builder + * @param text the range of the .text section + * @param stack the range allocated for the stack * @param stateInit Sleigh source to execute to initialize the trace state before emulation * @param assembly lines of assembly to place starting at {@code 0x00400000} * @return a new trace thread, whose register state is initialized as specified @@ -62,10 +73,12 @@ public class AbstractTracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegr TraceMemoryManager mm = tb.trace.getMemoryManager(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - thread = tb.getOrAddThread("Thread1", 0); - mm.addRegion("Regions[bin:.text]", Lifespan.nowOn(0), text, + tb.createRootObject(buildContext(), "Target"); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); + mm.addRegion("Memory[bin:.text]", Lifespan.nowOn(0), text, TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - mm.addRegion("Regions[stack1]", Lifespan.nowOn(0), stack, + mm.addRegion("Memory[stack1]", Lifespan.nowOn(0), stack, TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0)); Iterator block = assembly.isEmpty() ? Collections.emptyIterator() diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java index 50d03ba72d..0e5ec59dd0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/BytesTracePcodeEmulatorTest.java @@ -37,18 +37,15 @@ import ghidra.program.model.lang.*; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.context.DBTraceRegisterContextManager; import ghidra.trace.database.target.DBTraceObjectManager; -import ghidra.trace.database.target.DBTraceObjectManagerTest; import ghidra.trace.model.Lifespan; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.memory.*; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.thread.TraceThread; import ghidra.util.NumericUtilities; +@SuppressWarnings("javadoc") public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest { /** @@ -891,9 +888,8 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest TraceThread thread; TraceGuestPlatform x64; try (Transaction tx = tb.startTransaction()) { - SchemaContext ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX); DBTraceObjectManager objects = tb.trace.getObjectManager(); - objects.createRootObject(ctx.getSchema(new SchemaName("Session"))); + tb.createRootObject(); thread = tb.getOrAddThread("Targets[0].Threads[0]", 0); mm.addRegion("Targets[0].Memory[bin:.text]", Lifespan.nowOn(0), diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java index 9c6b3660ed..051e4520d5 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TraceSleighUtilsTest.java @@ -4,9 +4,9 @@ * 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. @@ -15,7 +15,8 @@ */ package ghidra.pcode.exec.trace; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import java.math.BigInteger; import java.util.Map; @@ -31,8 +32,11 @@ import ghidra.program.model.lang.*; import ghidra.program.util.DefaultLanguageService; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; +import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemorySpace; import ghidra.trace.model.memory.TraceMemoryState; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest { @@ -62,12 +66,21 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest } } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .useRegistersPerFrame() + .noRegisterGroups() + .build(); + } + @Test public void testRegister() throws Exception { try (ToyDBTraceBuilder b = new ToyDBTraceBuilder("test", TOY_BE_64_HARVARD)) { TraceThread thread; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); Register r0 = language.getRegister("r0"); TraceMemorySpace regs = @@ -111,7 +124,9 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest try (ToyDBTraceBuilder b = new ToyDBTraceBuilder("test", TOY_BE_64_HARVARD)) { TraceThread thread; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); Register r0 = language.getRegister("r0"); TraceMemorySpace regs = @@ -131,7 +146,9 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest try (ToyDBTraceBuilder b = new ToyDBTraceBuilder("test", TOY_BE_64_HARVARD)) { TraceThread thread; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); Register r0 = language.getRegister("r0"); TraceMemorySpace regs = @@ -154,7 +171,9 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest try (ToyDBTraceBuilder b = new ToyDBTraceBuilder("test", TOY_BE_64_HARVARD)) { TraceThread thread; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); Register r0 = language.getRegister("r0"); TraceMemorySpace regs = @@ -184,7 +203,9 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest try (ToyDBTraceBuilder b = new ToyDBTraceBuilder("test", TOY_BE_64_HARVARD)) { TraceThread thread; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); Register r0 = language.getRegister("r0"); TraceMemorySpace regs = @@ -216,7 +237,9 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest """, PcodeUseropLibrary.NIL); TraceThread thread; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); PcodeExecutor executor = new PcodeExecutor<>(sp.getLanguage(), BytesPcodeArithmetic.forLanguage(b.language), diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java index 7c38a1f340..01085b6e0c 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/ToyDBTraceBuilder.java @@ -28,6 +28,8 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; +import org.jdom.JDOMException; + import db.DBHandle; import db.Transaction; import generic.test.AbstractGenericTest; @@ -55,14 +57,19 @@ import ghidra.trace.database.thread.DBTraceThreadManager; import ghidra.trace.model.*; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TracePlatform; +import ghidra.trace.model.memory.TraceRegister; import ghidra.trace.model.symbol.TraceReferenceManager; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.target.schema.*; +import ghidra.trace.model.target.schema.DefaultTraceObjectSchema.DefaultAttributeSchema; +import ghidra.trace.model.target.schema.TraceObjectSchema.Hidden; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.Msg; import ghidra.util.exception.*; import ghidra.util.task.ConsoleTaskMonitor; @@ -85,6 +92,148 @@ public class ToyDBTraceBuilder implements AutoCloseable { public final TracePlatform host; public final LanguageService languageService = DefaultLanguageService.getLanguageService(); + public static final String CTX_XML_DEFAULT = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """; + + public static final SchemaContext CTX_DEFAULT; + + public static class ToySchemaBuilder { + private final DefaultSchemaContext ctx = new DefaultSchemaContext(CTX_DEFAULT); + + public ToySchemaBuilder useRegistersPerThread() { + ctx.modify(new SchemaName("Thread")) + .addAttributeSchema(new DefaultAttributeSchema("Registers", + new SchemaName("RegisterContainer"), false, false, Hidden.FALSE), this) + .buildAndReplace(); + ctx.modify(new SchemaName("Frame")) + .removeAttributeSchema("Registers") + .buildAndReplace(); + return this; + } + + public ToySchemaBuilder useRegistersPerFrame() { + ctx.modify(new SchemaName("Frame")) + .addAttributeSchema(new DefaultAttributeSchema("Registers", + new SchemaName("RegisterContainer"), false, false, Hidden.FALSE), this) + .buildAndReplace(); + ctx.modify(new SchemaName("Thread")) + .removeAttributeSchema("Registers") + .buildAndReplace(); + return this; + } + + public ToySchemaBuilder useRegisterGroups() { + ctx.modify(new SchemaName("RegisterContainer")) + .addAttributeSchema(new DefaultAttributeSchema("User", + new SchemaName("RegisterGroup"), false, false, Hidden.FALSE), this) + .addAttributeSchema(new DefaultAttributeSchema("Float", + new SchemaName("RegisterGroup"), false, false, Hidden.FALSE), this) + .removeElementSchema("") + .setCanonicalContainer(false) + .buildAndReplace(); + return this; + } + + public ToySchemaBuilder noRegisterGroups() { + ctx.modify(new SchemaName("RegisterContainer")) + .addElementSchema("", new SchemaName("Register"), this) + .setCanonicalContainer(true) + .removeAttributeSchema("User") + .removeAttributeSchema("Float") + .buildAndReplace(); + return this; + } + + public SchemaContext build() { + return ctx; + } + } + + static { + try { + CTX_DEFAULT = XmlSchemaContext.deserialize(CTX_XML_DEFAULT); + } + catch (JDOMException e) { + throw new AssertionError(e); + } + } + /** * Open a .gzf compressed trace * @@ -520,6 +669,7 @@ public class ToyDBTraceBuilder implements AutoCloseable { Register register = language.getRegister(registerName); assertNotNull(register); TraceThread thread = getOrAddThread(threadName, snap); + createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), host, 1); DBTraceBookmarkType type = getOrAddBookmarkType(typeName); DBTraceBookmarkManager manager = trace.getBookmarkManager(); DBTraceBookmarkSpace space = manager.getBookmarkRegisterSpace(thread, true); @@ -527,7 +677,9 @@ public class ToyDBTraceBuilder implements AutoCloseable { type, category, comment); assertSame(thread, bm.getThread()); assertEquals(snap, bm.getLifespan().lmin()); - assertEquals(register.getAddress(), bm.getAddress()); + AddressSpace spaceT = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + AddressRange range = host.getConventionalRegisterRange(spaceT, register); + assertEquals(range.getMinAddress(), bm.getAddress()); assertEquals(typeName, bm.getTypeString()); assertEquals(category, bm.getCategory()); return bm; @@ -822,7 +974,7 @@ public class ToyDBTraceBuilder implements AutoCloseable { return getLanguage(langID).getCompilerSpecByID(new CompilerSpecID(compID)); } - public TraceObjectThread createObjectsProcessAndThreads() { + public TraceThread createObjectsProcessAndThreads() { DBTraceObjectManager objs = trace.getObjectManager(); KeyPath pathProc1 = KeyPath.parse("Processes[1]"); TraceObject proc1 = objs.createObject(pathProc1); @@ -835,10 +987,10 @@ public class ToyDBTraceBuilder implements AutoCloseable { proc1.setAttribute(zeroOn, "_state", TraceExecutionState.STOPPED.name()); - return t1.queryInterface(TraceObjectThread.class); + return t1.queryInterface(TraceThread.class); } - public void createObjectsFramesAndRegs(TraceObjectThread thread, Lifespan lifespan, + public void createObjectsFramesAndRegs(TraceThread thread, Lifespan lifespan, TracePlatform platform, int n) { DBTraceObjectManager objs = trace.getObjectManager(); KeyPath pathThread = thread.getObject().getCanonicalPath(); @@ -846,11 +998,44 @@ public class ToyDBTraceBuilder implements AutoCloseable { KeyPath pathContainer = pathThread.key("Stack").index(i).key("Registers"); for (Register reg : platform.getLanguage().getRegisters()) { TraceObject regObj = objs.createObject(pathContainer.index(reg.getName())); + assertNotNull("Registers not at the expected path in schema", + regObj.queryInterface(TraceRegister.class)); regObj.insert(lifespan, ConflictResolution.DENY); } } } + public void createObjectsRegsForThread(TraceThread thread, Lifespan lifespan, + TracePlatform platform) { + DBTraceObjectManager objs = trace.getObjectManager(); + KeyPath pathThread = thread.getObject().getCanonicalPath(); + KeyPath pathContainer = pathThread.key("Registers"); + for (Register reg : platform.getLanguage().getRegisters()) { + TraceObject regObj = objs.createObject(pathContainer.index(reg.getName())); + assertNotNull("Registers not at the expected path in schema", + regObj.queryInterface(TraceRegister.class)); + regObj.insert(lifespan, ConflictResolution.DENY); + } + } + + public TraceObject createRootObject(SchemaContext ctx, String schemaName) { + return trace.getObjectManager() + .createRootObject(ctx.getSchema(new SchemaName(schemaName))) + .getChild(); + } + + public TraceObject createRootObject(SchemaContext ctx) { + return createRootObject(ctx, "Session"); + } + + public TraceObject createRootObject(String schemaName) { + return createRootObject(CTX_DEFAULT, schemaName); + } + + public TraceObject createRootObject() { + return createRootObject(CTX_DEFAULT); + } + /** * Get an object by its canonical path * diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/bookmark/DBTraceBookmarkManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/bookmark/DBTraceBookmarkManagerTest.java index 9dc44c2b78..fda0f65b79 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/bookmark/DBTraceBookmarkManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/bookmark/DBTraceBookmarkManagerTest.java @@ -4,9 +4,9 @@ * 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. @@ -26,7 +26,9 @@ import org.junit.*; import db.Transaction; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; public class DBTraceBookmarkManagerTest extends AbstractGhidraHeadlessIntegrationTest { @@ -82,12 +84,20 @@ public class DBTraceBookmarkManagerTest extends AbstractGhidraHeadlessIntegratio assertNull(found); } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .useRegistersPerFrame() + .noRegisterGroups() + .build(); + } + @Test public void testGetRegisterBookmarkById() throws Exception { // TODO: Should I check that bookmarks in register spaces are enclosed by the corresponding thread's lifespan? DBTraceBookmark bm; try (Transaction tx = b.startTransaction()) { - bm = b.addRegisterBookmark(0, "Thread1", "r4", "Test Type", "Cat1", "Test comment"); + b.createRootObject(buildContext(), "Target"); + bm = b.addRegisterBookmark(0, "Threads[1]", "r4", "Test Type", "Cat1", "Test comment"); } long id = bm.getId(); @@ -98,7 +108,10 @@ public class DBTraceBookmarkManagerTest extends AbstractGhidraHeadlessIntegratio @Test public void testGetCategoriesForType() throws Exception { try (Transaction tx = b.startTransaction()) { - TraceThread thread = b.trace.getThreadManager().createThread("Thread1", 0); + b.createRootObject(buildContext(), "Target"); + + TraceThread thread = b.trace.getThreadManager().createThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); DBTraceBookmarkSpace rSpace = manager.getBookmarkRegisterSpace(thread, true); DBTraceBookmarkType type = b.getOrAddBookmarkType("Test Type"); @@ -111,9 +124,12 @@ public class DBTraceBookmarkManagerTest extends AbstractGhidraHeadlessIntegratio assertEquals(Set.of("Cat1"), manager.getCategoriesForType(type)); assertEquals(Set.of(), rSpace.getCategoriesForType(type)); - b.addRegisterBookmark(0, "Thread1", "r4", "Test Type", "Cat2", "Second"); + b.addRegisterBookmark(0, "Threads[1]", "r4", "Test Type", "Cat2", "Second"); assertEquals(Set.of("Cat1", "Cat2"), type.getCategories()); - assertEquals(Set.of("Cat1"), manager.getCategoriesForType(type)); + assertEquals(Set.of("Cat1", "Cat2"), manager.getCategoriesForType(type)); + assertEquals(Set.of("Cat1"), + manager.getBookmarkSpace(b.language.getDefaultSpace(), false) + .getCategoriesForType(type)); assertEquals(Set.of("Cat2"), rSpace.getCategoriesForType(type)); } } @@ -121,6 +137,8 @@ public class DBTraceBookmarkManagerTest extends AbstractGhidraHeadlessIntegratio @Test public void testGetBookmarksForType() throws Exception { try (Transaction tx = b.startTransaction()) { + b.createRootObject(buildContext(), "Target"); + DBTraceBookmarkType type = b.getOrAddBookmarkType("Test Type"); assertFalse(type.hasBookmarks()); assertEquals(0, type.countBookmarks()); @@ -131,7 +149,7 @@ public class DBTraceBookmarkManagerTest extends AbstractGhidraHeadlessIntegratio assertEquals(Set.of(bm1), new HashSet<>(type.getBookmarks())); DBTraceBookmark bm2 = - b.addRegisterBookmark(0, "Thread1", "r4", "Test Type", "Cat2", "Second"); + b.addRegisterBookmark(0, "Threads[1]", "r4", "Test Type", "Cat2", "Second"); assertTrue(type.hasBookmarks()); assertEquals(2, type.countBookmarks()); assertEquals(Set.of(bm1, bm2), new HashSet<>(type.getBookmarks())); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerObjectTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerObjectTest.java deleted file mode 100644 index 756783fa23..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerObjectTest.java +++ /dev/null @@ -1,59 +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 org.junit.Before; - -import db.Transaction; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.target.schema.XmlSchemaContext; - -public class DBTraceBreakpointManagerObjectTest extends DBTraceBreakpointManagerTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize("" + // - "" + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - ""); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerTest.java index c039275a49..7d6f428ff6 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/breakpoint/DBTraceBreakpointManagerTest.java @@ -15,6 +15,7 @@ */ package ghidra.trace.database.breakpoint; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; import java.util.List; @@ -28,24 +29,57 @@ import db.Transaction; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.thread.TraceThread; import ghidra.util.exception.DuplicateNameException; public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrationTest { + public static final String XML_CTX = """ + + + + + + + + + + + + + + + + + + + + + """; + ToyDBTraceBuilder b; DBTraceBreakpointManager breakpointManager; TraceThread thread; - TraceBreakpoint breakMain; - TraceBreakpoint breakVarA; - TraceBreakpoint breakVarB; + TraceBreakpointLocation breakMain; + TraceBreakpointLocation breakVarA; + TraceBreakpointLocation breakVarB; @Before public void setUpBreakpointManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:default"); + + try (Transaction tx = b.startTransaction()) { + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); + } + breakpointManager = b.trace.getBreakpointManager(); } @@ -70,7 +104,7 @@ public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrat // pass } - assertEquals(1, breakpointManager.getBreakpointsByPath("Breakpoints[0]").size()); + assertEquals(1, breakpointManager.getBreakpointLocationsByPath("Breakpoints[0]").size()); } protected void addBreakpoints() throws Exception { @@ -95,16 +129,16 @@ public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrat addBreakpoints(); // breakVarA == breakVarB in object mode assertEquals(Set.copyOf(List.of(breakMain, breakVarA, breakVarB)), - Set.copyOf(breakpointManager.getAllBreakpoints())); + Set.copyOf(breakpointManager.getAllBreakpointLocations())); } @Test public void testBreakpointsByPath() throws Exception { addBreakpoints(); assertEquals(Set.of(breakMain), - Set.copyOf(breakpointManager.getBreakpointsByPath("Breakpoints[0]"))); + Set.copyOf(breakpointManager.getBreakpointLocationsByPath("Breakpoints[0]"))); assertEquals(Set.copyOf(List.of(breakVarA, breakVarB)), // Same breakpoint in object mode - Set.copyOf(breakpointManager.getBreakpointsByPath("Breakpoints[1]"))); + Set.copyOf(breakpointManager.getBreakpointLocationsByPath("Breakpoints[1]"))); } @Test @@ -161,6 +195,7 @@ public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrat } @Test + @Deprecated public void testGetThreads() throws Exception { addBreakpoints(); assertEquals(Set.of(thread), Set.copyOf(breakMain.getThreads(0))); @@ -198,7 +233,7 @@ public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrat addBreakpoints(); assertEquals(Set.of(TraceBreakpointKind.SW_EXECUTE), Set.copyOf(breakMain.getKinds(0))); try (Transaction tx = b.startTransaction()) { - breakMain.setKinds(0, Set.of(TraceBreakpointKind.HW_EXECUTE)); + breakMain.getSpecification().setKinds(0, Set.of(TraceBreakpointKind.HW_EXECUTE)); assertEquals(Set.of(TraceBreakpointKind.HW_EXECUTE), Set.copyOf(breakMain.getKinds(0))); } assertEquals(Set.of(TraceBreakpointKind.HW_EXECUTE), Set.copyOf(breakMain.getKinds(0))); @@ -215,7 +250,7 @@ public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrat assertEquals("WinMain", breakMain.getComment(0)); } - protected static class InvalidBreakpointMatcher extends BaseMatcher { + protected static class InvalidBreakpointMatcher extends BaseMatcher { private final long snap; public InvalidBreakpointMatcher(long snap) { @@ -224,7 +259,8 @@ public class DBTraceBreakpointManagerTest extends AbstractGhidraHeadlessIntegrat @Override public boolean matches(Object actual) { - return actual == null || actual instanceof TraceBreakpoint bpt && !bpt.isValid(snap); + return actual == null || + actual instanceof TraceBreakpointLocation bpt && !bpt.isValid(snap); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java index f86beb961a..759555e27b 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java @@ -29,39 +29,32 @@ import ghidra.program.model.lang.*; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.target.DBTraceObjectManager; -import ghidra.trace.database.target.DBTraceObjectManagerTest; import ghidra.trace.model.Lifespan; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.memory.TraceMemorySpace; -import ghidra.trace.model.memory.TraceObjectRegister; +import ghidra.trace.model.memory.TraceRegister; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.util.exception.DuplicateNameException; public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessIntegrationTest { protected ToyDBTraceBuilder b; protected DBTraceObjectManager manager; - protected SchemaContext ctx; protected TraceObject root; @Before public void setUpObjectManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:default"); manager = b.trace.getObjectManager(); - - ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX); } @Test public void testRegisterMappingHost() throws DuplicateNameException { try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -74,8 +67,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte .createOverlayAddressSpace("Targets[0].Threads[0].Registers", b.trace.getBaseAddressFactory().getRegisterSpace()); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 64); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x1234); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 64); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x1234); } AddressSpace overlaySpace = @@ -89,7 +82,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte public void testRegisterMappingGuest() throws Throwable { TraceGuestPlatform amd64; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -107,8 +100,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte getSLEIGH_X86_64_LANGUAGE().getCompilerSpecByID(new CompilerSpecID("gcc"))); amd64.addMappedRegisterRange(); - regRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 64); - regRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x1234); + regRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 64); + regRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x1234); } AddressSpace overlaySpace = @@ -123,7 +116,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte TraceGuestPlatform amd64; Register RAX; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -143,9 +136,9 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte RAX = amd64.getLanguage().getRegister("RAX"); amd64.addRegisterMapOverride(RAX, "orig_rax"); - regOrigRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, + regOrigRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 64); - regOrigRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, + regOrigRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x1234); } @@ -160,7 +153,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte public void testRegisterMappingGuestMemoryMapped() throws Throwable { TraceGuestPlatform avr8; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -177,8 +170,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte avr8.addMappedRange(b.addr(0), avr8.getLanguage().getDefaultDataSpace().getAddress(0), 0x1000); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 8); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x12); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 8); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x12); } assertEquals(BigInteger.valueOf(0x12), b.trace.getMemoryManager() @@ -194,7 +187,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte TraceGuestPlatform avr8; AddressSpace overlay; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -215,8 +208,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte avr8.addMappedRange(b.addr(overlay, 0), avr8.getLanguage().getDefaultDataSpace().getAddress(0), 0x1000); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 8); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x12); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 8); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x12); } assertEquals(BigInteger.valueOf(0x12), b.trace.getMemoryManager() @@ -232,7 +225,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte TraceGuestPlatform avr8; Register R0; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -251,8 +244,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte R0 = avr8.getLanguage().getRegister("R0"); avr8.addRegisterMapOverride(R0, "orig_r0"); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 8); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x12); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 8); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x12); } assertEquals(BigInteger.valueOf(0x12), @@ -267,7 +260,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte TraceGuestPlatform amd64; Register RAX; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -285,9 +278,9 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte getSLEIGH_X86_64_LANGUAGE().getCompilerSpecByID(new CompilerSpecID("gcc"))); amd64.addMappedRegisterRange(); - regOrigRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, + regOrigRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 64); - regOrigRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, + regOrigRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x1234); RAX = amd64.getLanguage().getRegister("RAX"); @@ -306,7 +299,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte TraceGuestPlatform avr8; Register R0; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -323,8 +316,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte avr8.addMappedRange(b.addr(0), avr8.getLanguage().getDefaultDataSpace().getAddress(0), 0x1000); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 8); - regR0.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x12); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 8); + regR0.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x12); R0 = avr8.getLanguage().getRegister("R0"); avr8.addRegisterMapOverride(R0, "orig_r0"); @@ -341,7 +334,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte public void testAddGuestMappingCopiesRegisterValues() throws Throwable { TraceGuestPlatform amd64; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -354,8 +347,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte .createOverlayAddressSpace("Targets[0].Threads[0].Registers", b.trace.getBaseAddressFactory().getRegisterSpace()); - regRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 64); - regRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x1234); + regRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 64); + regRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x1234); amd64 = b.trace.getPlatformManager() .addGuestPlatform( @@ -374,7 +367,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte public void testAddOverlaySpaceCopiesRegisterValues() throws Throwable { TraceGuestPlatform amd64; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); TraceObject thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); @@ -384,8 +377,8 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte KeyPath.parse("Targets[0].Threads[0].Registers.User[RAX]")); regRAX.insert(Lifespan.nowOn(0), ConflictResolution.DENY); - regRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_BITLENGTH, 64); - regRAX.setValue(Lifespan.nowOn(0), TraceObjectRegister.KEY_VALUE, 0x1234); + regRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_BITLENGTH, 64); + regRAX.setValue(Lifespan.nowOn(0), TraceRegister.KEY_VALUE, 0x1234); amd64 = b.trace.getPlatformManager() .addGuestPlatform( @@ -410,7 +403,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte AddressSpace registers = b.trace.getBaseAddressFactory().getRegisterSpace(); AddressSpace overlay; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); x86 = b.trace.getPlatformManager() .addGuestPlatform(b.getCompiler("x86:LE:32:default", "gcc")); @@ -441,7 +434,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte Register EAX; Register EBX; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); x86 = b.trace.getPlatformManager() .addGuestPlatform(b.getCompiler("x86:LE:32:default", "gcc")); @@ -469,7 +462,7 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte AddressSpace overlay; Register r0; try (Transaction tx = b.startTransaction()) { - root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); + root = b.createRootObject(); r0 = b.language.getRegister("r0"); overlay = b.trace.getMemoryManager() .createOverlayAddressSpace("Targets[0].Threads[0].Registers", registers); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeManagerTest.java index 50ed138f2d..a3a9c1dd76 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeManagerTest.java @@ -39,13 +39,16 @@ import ghidra.program.model.scalar.Scalar; import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.context.DBTraceRegisterContextManager; import ghidra.trace.database.guest.*; import ghidra.trace.model.ImmutableTraceAddressSnapRange; import ghidra.trace.model.Lifespan; import ghidra.trace.model.listing.*; import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.IntersectionAddressSetView; import ghidra.util.exception.CancelledException; import ghidra.util.task.ConsoleTaskMonitor; @@ -372,6 +375,8 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes * settings while the unit is still being created. This will invalidate the trace's * caches. All of them, including the defined data units, which can become the cause of many * timing issues. + * + * @throws Throwable because */ @Test public void testOverlapErrWithDataTypeSettings() throws Throwable { @@ -1388,6 +1393,12 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes } } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .build(); + } + @Test public void testRegisterSpace() throws Exception { TraceThread thread; @@ -1395,7 +1406,13 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes TraceData dR4; try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread 1", 0); + b.createRootObject(new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(), + "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 2); regCode = manager.getCodeRegisterSpace(thread, true); dR4 = regCode.definedData() .create(Lifespan.nowOn(0), b.language.getRegister("r4"), LongDataType.dataType); @@ -1926,14 +1943,16 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes @Test public void testSaveAndLoad() throws Exception { + Register r4 = b.language.getRegister("r4"); + try (Transaction tx = b.startTransaction()) { + b.createRootObject(buildContext(), "Target"); b.addInstruction(0, b.addr(0x4004), b.host, b.buf(0xf4, 0)); - TraceThread thread = b.getOrAddThread("Thread 1", 0); + TraceThread thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsRegsForThread(thread, Lifespan.nowOn(0), b.host); DBTraceCodeSpace regCode = manager.getCodeRegisterSpace(thread, true); - regCode.definedData() - .create(Lifespan.nowOn(0), b.language.getRegister("r4"), - LongDataType.dataType); + regCode.definedData().create(Lifespan.nowOn(0), r4, LongDataType.dataType); } File file = b.save(); @@ -1943,7 +1962,7 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes DBTraceCodeManager manager = b.trace.getCodeManager(); // No transaction, so it had better exist - TraceThread thread = b.getOrAddThread("Thread 1", 0); + TraceThread thread = b.getOrAddThread("Threads[1]", 0); List units = new ArrayList<>(); for (TraceCodeUnit u : manager.definedUnits().get(0, true)) { units.add(u); @@ -1966,7 +1985,9 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes assertTrue(units.get(1) instanceof TraceData); TraceData data = (TraceData) units.get(1); - assertEquals(b.language.getRegister("r4").getAddress(), data.getAddress()); + AddressSpace spaceT0 = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + AddressRange rngR4 = b.host.getConventionalRegisterRange(spaceT0, r4); + assertEquals(rngR4.getMinAddress(), data.getAddress()); assertEquals(new Scalar(32, 0), data.getValue()); assertEquals(4, data.getLength()); } @@ -1974,25 +1995,33 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes @Test public void testUndoThenRedo() throws Exception { + Register r4 = b.language.getRegister("r4"); + + TraceThread thread; + try (Transaction tx = b.startTransaction()) { + /** + * This part should not be undone: 1) Because asking for threads without a root object + * causes an error. 2) Because the thread is an object, it's subject to the write-back + * cache and cannot be undone. + */ + b.createRootObject(buildContext(), "Target"); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsRegsForThread(thread, Lifespan.nowOn(0), b.host); + } + try (Transaction tx = b.startTransaction()) { b.addInstruction(0, b.addr(0x4004), b.host, b.buf(0xf4, 0)); - TraceThread thread = b.getOrAddThread("Thread 1", 0); DBTraceCodeSpace regCode = manager.getCodeRegisterSpace(thread, true); - regCode.definedData() - .create(Lifespan.nowOn(0), b.language.getRegister("r4"), - LongDataType.dataType); + regCode.definedData().create(Lifespan.nowOn(0), r4, LongDataType.dataType); } b.trace.undo(); assertFalse(manager.definedUnits().get(0, true).iterator().hasNext()); - assertTrue(b.trace.getThreadManager().getAllThreads().isEmpty()); b.trace.redo(); - // No transaction, so it had better exist - TraceThread thread = b.getOrAddThread("Thread 1", 0); List units = new ArrayList<>(); for (TraceCodeUnit u : manager.definedUnits().get(0, true)) { units.add(u); @@ -2000,8 +2029,7 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes // Again, no transaction, so that space had better exist for (TraceCodeUnit u : manager.getCodeRegisterSpace(thread, true) .definedUnits() - .get(0, - true)) { + .get(0, true)) { units.add(u); } @@ -2015,7 +2043,10 @@ public class DBTraceCodeManagerTest extends AbstractGhidraHeadlessIntegrationTes assertTrue(units.get(1) instanceof TraceData); TraceData data = (TraceData) units.get(1); - assertEquals(b.language.getRegister("r4").getAddress(), data.getAddress()); + + AddressSpace spaceT0 = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + AddressRange rngR4 = b.host.getConventionalRegisterRange(spaceT0, r4); + assertEquals(rngR4.getMinAddress(), data.getAddress()); assertEquals(new Scalar(32, 0), data.getValue()); assertEquals(4, data.getLength()); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeUnitTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeUnitTest.java index 5bd7818d5e..83fa301f6f 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeUnitTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/listing/DBTraceCodeUnitTest.java @@ -17,7 +17,6 @@ package ghidra.trace.database.listing; import static org.junit.Assert.*; -import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.*; @@ -27,9 +26,7 @@ import org.junit.*; import db.*; import ghidra.app.plugin.assembler.*; import ghidra.docking.settings.Settings; -import ghidra.lifecycle.Unfinished; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.lang.*; import ghidra.program.model.listing.*; @@ -50,14 +47,69 @@ import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceOverlappedRegionException; import ghidra.trace.model.symbol.TraceReference; import ghidra.trace.model.symbol.TraceStackReference; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.*; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.NoValueException; import ghidra.util.map.TypeMismatchException; -public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest - implements Unfinished { +public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest { + + public static final String XML_CTX = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """; + protected static final String[] EMPTY_STRING_ARRAY = new String[] {}; protected static class TestSaveable implements Saveable { @@ -169,8 +221,14 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest DBTraceCodeManager manager; @Before - public void setUpTraceCodeManagerTest() throws IOException { + public void setUpTraceCodeManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:harvard"); + + try (Transaction tx = b.startTransaction()) { + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); + } + manager = b.trace.getCodeManager(); } @@ -209,7 +267,7 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest try (Transaction tx = b.startTransaction()) { b.trace.getMemoryManager() - .addRegion(".text", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), + .addRegion("Memory[.text]", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), TraceMemoryFlag.READ); } @@ -387,13 +445,6 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest catch (IllegalArgumentException e) { // pass } - try (Transaction tx = b.startTransaction()) { - i4004.setComment(5, "Shouldn't work"); - fail(); - } - catch (IllegalArgumentException e) { - // pass - } assertNull(i4004.getComment(CommentType.EOL)); try (Transaction tx = b.startTransaction()) { @@ -455,12 +506,10 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest @Test public void testAddressRelators() throws CodeUnitInsertionException { TraceInstruction i4004; - TraceInstruction i4006; - TraceData d4008; try (Transaction tx = b.startTransaction()) { i4004 = b.addInstruction(0, b.addr(0x4004), b.host, b.buf(0xf4, 0)); - i4006 = b.addInstruction(0, b.addr(0x4006), b.host, b.buf(0xf4, 0)); - d4008 = b.addData(0, b.addr(0x4008), LongDataType.dataType, b.buf(1, 2, 3, 4)); + b.addInstruction(0, b.addr(0x4006), b.host, b.buf(0xf4, 0)); + b.addData(0, b.addr(0x4008), LongDataType.dataType, b.buf(1, 2, 3, 4)); } assertFalse(i4004.contains(b.addr(0x4003))); @@ -627,12 +676,16 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest instruction = b.addInstruction(0, b.addr(0x4004), b.host, b.buf(0xf4, 0)); undefined = manager.undefinedData().getAt(0, b.addr(0x4006)); - thread = b.getOrAddThread("Thread 1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); DBTraceCodeSpace regCode = manager.getCodeRegisterSpace(thread, true); data = regCode.definedData() .create(Lifespan.nowOn(0), b.language.getRegister("r4"), LongDataType.dataType); // getForRegister requires unit to match size - undReg = regCode.undefinedData().getAt(0, b.language.getRegister("r5").getAddress()); + undReg = regCode.undefinedData() + .get(0, b.language.getRegister("r5"), true) + .iterator() + .next(); } assertEquals(b.trace, instruction.getTrace()); @@ -710,7 +763,8 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest // In space without memory, yet. und = manager.undefinedData().getAt(0, b.data(0x7fff)); - TraceThread thread = b.getOrAddThread("Thread1", 0); + TraceThread thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); DBTraceMemorySpace regMem = b.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); Register r4 = b.language.getRegister("r4"); @@ -825,7 +879,7 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest try (Transaction tx = b.startTransaction()) { // StringDataType accesses memory via program view, so "block" must exist b.trace.getMemoryManager() - .addRegion("myRegion", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), + .addRegion("Memory[myRegion]", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), TraceMemoryFlag.READ); dl4000 = b.addData(0, b.addr(0x4000), LongDataType.dataType, b.buf(1, 2, 3, 4)); @@ -963,7 +1017,7 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest try (Transaction tx = b.startTransaction()) { // Disassembler's new cacheing in mem-buffer uses program view, so "block" must exist b.trace.getMemoryManager() - .addRegion("myRegion", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), + .addRegion("Memory[myRegion]", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), TraceMemoryFlag.READ); i4004 = b.addInstruction(0, b.addr(0x4004), b.host, b.buf(0xc8, 0x47)); @@ -1064,7 +1118,7 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest // Try some mutations try (Transaction tx = b.startTransaction()) { - i4004.addOperandReference(1, b.addr(0x5000), RefType.DATA_IND, SourceType.USER_DEFINED); + i4004.addOperandReference(1, b.addr(0x5000), RefType.DATA, SourceType.USER_DEFINED); // TODO: This should probably be default for first/only reference b.trace.getReferenceManager() .getReference(0, b.addr(0x4004), b.addr(0x5000), 1) @@ -1239,7 +1293,7 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest try (Transaction tx = b.startTransaction()) { // Disassembler's new cacheing in mem-buffer uses program view, so "block" must exist b.trace.getMemoryManager() - .addRegion("myRegion", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), + .addRegion("Memory[myRegion]", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), TraceMemoryFlag.READ); guest = b.trace.getPlatformManager().addGuestPlatform(x86.getDefaultCompilerSpec()); @@ -1355,6 +1409,8 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest @Test public void testComponentProperties() throws Exception { + Register r4 = b.language.getRegister("r4"); + Structure myStruct = new StructureDataType("myStruct", 0); TypeDef myTypedef = new TypedefDataType("myTypedef", ShortDataType.dataType); myStruct.add(ShortDataType.dataType, "sA", null); @@ -1367,10 +1423,10 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest try (Transaction tx = b.startTransaction()) { d4000 = b.addData(0, b.addr(0x4000), myStruct, b.buf(1, 2, 3, 4)); - thread = b.getOrAddThread("Thread 1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); DBTraceCodeSpace regCode = manager.getCodeRegisterSpace(thread, true); - dR4 = regCode.definedData() - .create(Lifespan.nowOn(0), b.language.getRegister("r4"), myStruct); + dR4 = regCode.definedData().create(Lifespan.nowOn(0), r4, myStruct); } myStruct = (Structure) b.trace.getDataTypeManager().getDataType("/myStruct"); myTypedef = (TypeDef) b.trace.getDataTypeManager().getDataType("/myTypedef"); @@ -1409,7 +1465,10 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest assertEquals(0, d4000sB.getStartSnap()); assertEquals(b.addr(0x4002), d4000sB.getAddress()); - assertEquals(b.language.getRegister("r4").getAddress().add(3), dR4sB.getMaxAddress()); + + AddressSpace spaceT0 = TraceRegisterUtils.getRegisterAddressSpace(thread, 0, false); + AddressRange rngR4 = b.host.getConventionalRegisterRange(spaceT0, r4); + assertEquals(rngR4.getMinAddress().add(3), dR4sB.getMaxAddress()); assertEquals(2, d4000sB.getLength()); @@ -1594,7 +1653,7 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest try (Transaction tx = b.startTransaction()) { // StringDataType accesses memory via program view, so "block" must exist b.trace.getMemoryManager() - .addRegion("myRegion", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), + .addRegion("Memory[myRegion]", Lifespan.nowOn(0), b.range(0x4000, 0x4fff), TraceMemoryFlag.READ); d4000 = b.addData(0, b.addr(0x4000), LongDataType.dataType, b.buf(1, 2, 3, 4)); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapAddressSetViewTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapAddressSetViewTest.java index 16b64c6803..7c28309117 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapAddressSetViewTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapAddressSetViewTest.java @@ -4,9 +4,9 @@ * 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. @@ -146,9 +146,8 @@ public class DBTraceAddressSnapRangePropertyMapAddressSetViewTest obj = new MyObject(this); factory = new DBCachedObjectStoreFactory(obj); try (Transaction tx = obj.openTransaction("CreateTable")) { - space = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries", factory, - obj.getReadWriteLock(), toy.getDefaultSpace(), null, 0, MyEntry.class, - MyEntry::new); + space = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries", null, factory, + obj.getReadWriteLock(), toy.getDefaultSpace(), MyEntry.class, MyEntry::new); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoFutureIterableTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoFutureIterableTest.java index 57548e945e..1874a9ef66 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoFutureIterableTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoFutureIterableTest.java @@ -4,9 +4,9 @@ * 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. @@ -157,9 +157,8 @@ public class DBTraceAddressSnapRangePropertyMapOcclusionIntoFutureIterableTest obj = new MyObject(this); factory = new DBCachedObjectStoreFactory(obj); try (Transaction tx = obj.openTransaction("CreateTable")) { - space = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries", factory, - obj.getReadWriteLock(), toy.getDefaultSpace(), null, 0, MyEntry.class, - MyEntry::new); + space = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries", null, factory, + obj.getReadWriteLock(), toy.getDefaultSpace(), MyEntry.class, MyEntry::new); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoPastIterableTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoPastIterableTest.java index 2598452e53..b38b4994b5 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoPastIterableTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapOcclusionIntoPastIterableTest.java @@ -4,9 +4,9 @@ * 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. @@ -157,9 +157,8 @@ public class DBTraceAddressSnapRangePropertyMapOcclusionIntoPastIterableTest obj = new MyObject(this); factory = new DBCachedObjectStoreFactory(obj); try (Transaction tid = obj.openTransaction("CreateTable")) { - space = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries", factory, - obj.getReadWriteLock(), toy.getDefaultSpace(), null, 0, MyEntry.class, - MyEntry::new); + space = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries", null, factory, + obj.getReadWriteLock(), toy.getDefaultSpace(), MyEntry.class, MyEntry::new); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpaceTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpaceTest.java index 86241af88b..4033dc8fa6 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpaceTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMapSpaceTest.java @@ -4,9 +4,9 @@ * 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. @@ -15,7 +15,7 @@ */ package ghidra.trace.database.map; -import static ghidra.lifecycle.Unfinished.*; +import static ghidra.lifecycle.Unfinished.TODO; import static org.junit.Assert.*; import java.io.File; @@ -81,15 +81,15 @@ public class DBTraceAddressSnapRangePropertyMapSpaceTest protected void loadSpaces() throws VersionException, IOException { try (Transaction tx = this.openTransaction("Create Tables")) { - this.space1 = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries1", factory, - getReadWriteLock(), toy.getDefaultSpace(), null, 0, MyEntry.class, - MyEntry::new); - this.space2 = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries2", factory, - getReadWriteLock(), toy.getDefaultSpace(), null, 0, MyEntry.class, - MyEntry::new); - this.space3 = new DBTraceAddressSnapRangePropertyMapSpace<>("Entries3", factory, - getReadWriteLock(), toy.getDefaultSpace(), null, 0, AltEntry.class, - AltEntry::new); + this.space1 = + new DBTraceAddressSnapRangePropertyMapSpace<>("Entries1", null, factory, + getReadWriteLock(), toy.getDefaultSpace(), MyEntry.class, MyEntry::new); + this.space2 = + new DBTraceAddressSnapRangePropertyMapSpace<>("Entries2", null, factory, + getReadWriteLock(), toy.getDefaultSpace(), MyEntry.class, MyEntry::new); + this.space3 = + new DBTraceAddressSnapRangePropertyMapSpace<>("Entries3", null, factory, + getReadWriteLock(), toy.getDefaultSpace(), AltEntry.class, AltEntry::new); } } @@ -226,11 +226,6 @@ public class DBTraceAddressSnapRangePropertyMapSpaceTest assertEquals(toy.getDefaultSpace(), obj.space1.getAddressSpace()); } - @Test - public void testGetThread() { - assertNull(obj.space1.getThread()); - } - @Test public void testGetUserIndex() { assertNotNull(obj.space1.getUserIndex(String.class, MyEntry.NAME_COLUMN)); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerMemoryTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerMemoryTest.java index 98f8bc8380..cd4f047f98 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerMemoryTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerMemoryTest.java @@ -37,6 +37,11 @@ import ghidra.util.task.TaskMonitor; public abstract class AbstractDBTraceMemoryManagerMemoryTest extends AbstractDBTraceMemoryManagerTest { + @Override + protected String getCtxXml() { + return CTX_XML_REGS_PER_FRAME; // per-whatever is not under test here, so just pick one + } + @Test public void testSetState() { try (Transaction tx = b.startTransaction()) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegionsTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegionsTest.java index 6df25f222f..3b84fa4dd2 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegionsTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegionsTest.java @@ -4,9 +4,9 @@ * 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. @@ -15,13 +15,12 @@ */ package ghidra.trace.database.memory; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; -import java.io.IOException; import java.util.Set; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; +import org.hamcrest.*; import org.junit.*; import db.Transaction; @@ -32,10 +31,28 @@ import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.util.LanguageTestWatcher; public abstract class AbstractDBTraceMemoryManagerRegionsTest extends AbstractGhidraHeadlessIntegrationTest { + + public static final String XML_CTX = """ + + + + + + + + + + + + """; + protected ToyDBTraceBuilder b; protected DBTraceMemoryManager memory; @@ -46,11 +63,15 @@ public abstract class AbstractDBTraceMemoryManagerRegionsTest protected abstract LanguageID getLanguageID(); @Before - public void setUp() throws IOException { + public void setUp() throws Exception { b = new ToyDBTraceBuilder("Testing", testLanguage.getLanguage()); + try (Transaction tx = b.startTransaction()) { b.trace.getTimeManager().createSnapshot("Initialize"); + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); } + memory = b.trace.getMemoryManager(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegistersTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegistersTest.java index c14c8587cc..04dc7e35c4 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegistersTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerRegistersTest.java @@ -23,21 +23,43 @@ import org.junit.Test; import db.Transaction; import ghidra.program.model.lang.*; +import ghidra.trace.model.Lifespan; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.thread.TraceThread; public abstract class AbstractDBTraceMemoryManagerRegistersTest extends AbstractDBTraceMemoryManagerTest { protected TraceThread getOrAddThread(String name, long creationSnap) { - return b.getOrAddThread(name, creationSnap); + TraceThread thread = b.getOrAddThread(name, creationSnap); + TraceObject obj = thread.getObject(); + TraceObject objRegs = b.trace.getObjectManager() + .createObject(obj.getCanonicalPath().key("Registers")); + objRegs.insert(Lifespan.ALL, ConflictResolution.DENY); + return thread; } protected abstract boolean isRegistersPerFrame(); + @Override + protected String getCtxXml() { + return isRegistersPerFrame() ? CTX_XML_REGS_PER_FRAME : CTX_XML_REGS_PER_THREAD; + } + + protected void createRegs(TraceThread thread, int frameCount) { + if (isRegistersPerFrame()) { + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, frameCount); + } + else { + b.createObjectsRegsForThread(thread, Lifespan.nowOn(0), b.host); + } + } + @Test public void testRegisters() throws Exception { Register r0 = b.language.getRegister("r0"); @@ -47,6 +69,7 @@ public abstract class AbstractDBTraceMemoryManagerRegistersTest TraceThread thread; try (Transaction tx = b.startTransaction()) { thread = getOrAddThread("Threads[1]", 0); + createRegs(thread, 2); DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(r0, new BigInteger("0123456789ABCDEF", 16))); @@ -98,6 +121,8 @@ public abstract class AbstractDBTraceMemoryManagerRegistersTest TraceThread thread; try (Transaction tx = b.startTransaction()) { thread = getOrAddThread("Threads[1]", 0); + createRegs(thread, 1); + waitForSwing(); DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); @@ -132,6 +157,8 @@ public abstract class AbstractDBTraceMemoryManagerRegistersTest /** * This test is based on the MWE submitted in GitHub issue #2760. + * + * @throws Exception because */ @Test public void testManyStateEntries() throws Exception { @@ -139,6 +166,7 @@ public abstract class AbstractDBTraceMemoryManagerRegistersTest TraceThread thread; try (Transaction tx = b.startTransaction()) { thread = getOrAddThread("Threads[1]", 0); + createRegs(thread, 1); DBTraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); for (int i = 1; i < 2000; i++) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java index c46b8310ab..d0e9d4d425 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/AbstractDBTraceMemoryManagerTest.java @@ -4,9 +4,9 @@ * 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. @@ -17,7 +17,6 @@ package ghidra.trace.database.memory; import static org.junit.Assert.*; -import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -30,11 +29,76 @@ import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.memory.TraceMemoryState; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.util.LanguageTestWatcher; import ghidra.util.database.DBCachedObjectStore; public abstract class AbstractDBTraceMemoryManagerTest extends AbstractGhidraHeadlessIntegrationTest { + public static final String CTX_XML_PART1 = """ + + + + + + + + + + + + + + + + + + + + + + + + + + """; + public static final String CTX_XML_REGS_PER_FRAME = CTX_XML_PART1 + """ + + + + + + + + + + + + """; + public static final String CTX_XML_REGS_PER_THREAD = CTX_XML_PART1 + """ + + + + + + + + + + + + """; + protected ToyDBTraceBuilder b; protected DBTraceMemoryManager memory; @@ -44,11 +108,16 @@ public abstract class AbstractDBTraceMemoryManagerTest protected abstract LanguageID getLanguageID(); + protected abstract String getCtxXml(); + @Before - public void setUp() throws IOException { + public void setUp() throws Exception { b = new ToyDBTraceBuilder("Testing", testLanguage.getLanguage()); try (Transaction tx = b.startTransaction()) { b.trace.getTimeManager().createSnapshot("Initialize"); + + XmlSchemaContext ctx = XmlSchemaContext.deserialize(getCtxXml()); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); } memory = b.trace.getMemoryManager(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegionsTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegionsTest.java deleted file mode 100644 index 5fcb6e2fd5..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegionsTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.database.memory; - -import org.junit.Before; - -import db.Transaction; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; - -public class DBTraceMemoryManagerObjectRegionsTest extends DBTraceMemoryManagerRegionsTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize(""" - - - - - - - - - - - - """); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegistersPerFrameBETest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegistersPerFrameBETest.java deleted file mode 100644 index 804ad8611b..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegistersPerFrameBETest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.database.memory; - -import org.junit.Before; -import org.junit.Test; - -import db.Transaction; -import ghidra.program.model.lang.LanguageID; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.TraceObject.ConflictResolution; -import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.LanguageTestWatcher.TestLanguage; - -public class DBTraceMemoryManagerObjectRegistersPerFrameBETest - extends AbstractDBTraceMemoryManagerRegistersTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize(""" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } - - @Override - protected TraceThread getOrAddThread(String name, long creationSnap) { - TraceThread thread = super.getOrAddThread(name, creationSnap); - TraceObject obj = ((TraceObjectThread) thread).getObject(); - TraceObject objRegs = b.trace.getObjectManager() - .createObject(obj.getCanonicalPath().extend(KeyPath.parse("Stack[0]"))); - objRegs.insert(Lifespan.ALL, ConflictResolution.DENY); - return thread; - } - - @Override - protected LanguageID getLanguageID() { - return new LanguageID("Toy:BE:64:default"); - } - - @Override - protected boolean isRegistersPerFrame() { - return true; - } - - @Test - @TestLanguage("Toy:BE:32:builder") - public void testRegisterBits() throws Exception { - runTestRegisterBits(b.host); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegistersPerThreadLETest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegistersPerThreadLETest.java deleted file mode 100644 index eee48d6086..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerObjectRegistersPerThreadLETest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.database.memory; - -import org.junit.Before; -import org.junit.Test; - -import db.Transaction; -import ghidra.program.model.lang.LanguageID; -import ghidra.trace.model.Lifespan; -import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.TraceObject.ConflictResolution; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.thread.TraceObjectThread; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.LanguageTestWatcher.TestLanguage; - -public class DBTraceMemoryManagerObjectRegistersPerThreadLETest - extends AbstractDBTraceMemoryManagerRegistersTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize(""" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } - - @Override - protected TraceThread getOrAddThread(String name, long creationSnap) { - TraceThread thread = super.getOrAddThread(name, creationSnap); - TraceObject obj = ((TraceObjectThread) thread).getObject(); - TraceObject objRegs = b.trace.getObjectManager() - .createObject(obj.getCanonicalPath().key("Registers")); - objRegs.insert(Lifespan.ALL, ConflictResolution.DENY); - return thread; - } - - @Override - protected LanguageID getLanguageID() { - return new LanguageID("Toy:LE:64:default"); - } - - @Override - protected boolean isRegistersPerFrame() { - return false; - } - - @Test - @TestLanguage("Toy:LE:32:builder") - public void testRegisterBits() throws Exception { - runTestRegisterBits(b.host); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersBETest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersPerFrameBETest.java similarity index 94% rename from Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersBETest.java rename to Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersPerFrameBETest.java index 094d7222fa..9ac6bb0ec8 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersBETest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersPerFrameBETest.java @@ -4,9 +4,9 @@ * 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. @@ -20,7 +20,7 @@ import org.junit.Test; import ghidra.program.model.lang.LanguageID; import ghidra.trace.util.LanguageTestWatcher.TestLanguage; -public class DBTraceMemoryManagerRegistersBETest +public class DBTraceMemoryManagerRegistersPerFrameBETest extends AbstractDBTraceMemoryManagerRegistersTest { @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersLETest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersPerThreadLETest.java similarity index 93% rename from Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersLETest.java rename to Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersPerThreadLETest.java index 48e8658742..4650e2b549 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersLETest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/memory/DBTraceMemoryManagerRegistersPerThreadLETest.java @@ -4,9 +4,9 @@ * 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. @@ -20,7 +20,7 @@ import org.junit.Test; import ghidra.program.model.lang.LanguageID; import ghidra.trace.util.LanguageTestWatcher.TestLanguage; -public class DBTraceMemoryManagerRegistersLETest +public class DBTraceMemoryManagerRegistersPerThreadLETest extends AbstractDBTraceMemoryManagerRegistersTest { @Override @@ -30,7 +30,7 @@ public class DBTraceMemoryManagerRegistersLETest @Override protected boolean isRegistersPerFrame() { - return true; + return false; } @Test diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerObjectTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerObjectTest.java deleted file mode 100644 index 4d1d717301..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerObjectTest.java +++ /dev/null @@ -1,71 +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.module; - -import org.junit.*; - -import db.Transaction; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; - -public class DBTraceModuleManagerObjectTest extends DBTraceModuleManagerTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize("" + // - "" + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - ""); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } - - @Test - @Override - @Ignore // Undo not supported with object-manager's write-back cache - public void testUndoIdentitiesPreserved() throws Exception { - super.testUndoIdentitiesPreserved(); - } - - @Test - @Override - @Ignore // Undo not supported with object-manager's write-back cache - public void testUndoThenRedo() throws Exception { - super.testUndoThenRedo(); - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerTest.java index 18e7ac0d41..54deab8e46 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceModuleManagerTest.java @@ -28,15 +28,46 @@ import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.modules.TraceModule; import ghidra.trace.model.modules.TraceSection; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; public class DBTraceModuleManagerTest extends AbstractGhidraHeadlessIntegrationTest { + public static final String XML_CTX = """ + + + + + + + + + + + + + + + + + + + """; + ToyDBTraceBuilder b; DBTraceModuleManager moduleManager; @Before public void setUpModuleManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:default"); + + try (Transaction tx = b.startTransaction()) { + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); + } + moduleManager = b.trace.getModuleManager(); } @@ -309,6 +340,7 @@ public class DBTraceModuleManagerTest extends AbstractGhidraHeadlessIntegrationT } @Test + @Ignore("Write-back cache doesn't support undo") public void testUndoIdentitiesPreserved() throws Exception { TraceModule mod1; try (Transaction tx = b.startTransaction()) { @@ -330,6 +362,7 @@ public class DBTraceModuleManagerTest extends AbstractGhidraHeadlessIntegrationT } @Test + @Ignore("Write-back cache doesn't support undo") public void testUndoThenRedo() throws Exception { TraceModule mod1; TraceModule mod2; diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceStaticMappingManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceStaticMappingManagerTest.java index 4a6a1ab8e9..e88368c829 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceStaticMappingManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/module/DBTraceStaticMappingManagerTest.java @@ -4,9 +4,9 @@ * 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. @@ -19,6 +19,7 @@ import static org.junit.Assert.*; import java.io.File; import java.io.IOException; +import java.net.URI; import java.net.URL; import java.util.Collection; @@ -47,11 +48,15 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg tb.close(); } + public static URL url(String spec) throws Exception { + return new URI(spec).toURL(); + } + @Test public void testAddAndGet() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), Lifespan.span(2, 5), - new URL("ghidra://static"), "DEADBEEF"); + url("ghidra://static"), "DEADBEEF"); } DBTraceStaticMapping found = staticMappingManager.findContaining(tb.addr(0xdeadbeef), 2); @@ -59,7 +64,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg assertEquals(100, found.getLength()); assertEquals(2, found.getStartSnap()); assertEquals(5, found.getEndSnap()); - assertEquals(new URL("ghidra://static"), found.getStaticProgramURL()); + assertEquals(url("ghidra://static"), found.getStaticProgramURL()); assertEquals("DEADBEEF", found.getStaticAddress()); assertEquals(found, staticMappingManager.findContaining(tb.addr(0xdeadbeef + 99), 2)); @@ -76,8 +81,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testAddAndEnumerate() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); } Collection all = staticMappingManager.getAllEntries(); @@ -88,11 +92,9 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testAddRemoveAndEnumerate() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(7, 9), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(7, 9), url("ghidra://static"), "DEADBEEF"); assertEquals(2, staticMappingManager.getAllEntries().size()); @@ -108,10 +110,9 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testOverlapCausesException() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); staticMappingManager.add(tb.range(0xdeadbeef + 80, 0xdeadbeef + 179), - Lifespan.span(2, 4), new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); fail(); } catch (TraceConflictedMappingException e) { @@ -123,10 +124,9 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testOverlapAgreeingAccepted() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); staticMappingManager.add(tb.range(0xdeadbeef + 80, 0xdeadbeef + 179), - Lifespan.span(2, 4), new URL("ghidra://static"), "DEADBF3F"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBF3F"); } } @@ -134,10 +134,9 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testTouchingProceedingIsNotOverlapping() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); staticMappingManager.add(tb.range(0xdeadbeef + 100, 0xdeadbeef + 199), - Lifespan.span(2, 4), new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); } } @@ -146,7 +145,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testSaveAndLoad() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), Lifespan.span(2, 5), - new URL("ghidra://static"), "DEADBEEF"); + url("ghidra://static"), "DEADBEEF"); } File tmp = tb.save(); @@ -158,7 +157,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg assertEquals(100, found.getLength()); assertEquals(2, found.getStartSnap()); assertEquals(5, found.getEndSnap()); - assertEquals(new URL("ghidra://static"), found.getStaticProgramURL()); + assertEquals(url("ghidra://static"), found.getStaticProgramURL()); assertEquals("DEADBEEF", found.getStaticAddress()); } } @@ -167,8 +166,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testAddButAbortedStillEmpty() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); tx.abort(); } @@ -179,8 +177,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testAddThenUndo() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); } tb.trace.undo(); @@ -191,8 +188,7 @@ public class DBTraceStaticMappingManagerTest extends AbstractGhidraHeadlessInteg public void testAddThenRemoveThenUndo() throws Exception { try (Transaction tx = tb.startTransaction()) { staticMappingManager.add(tb.range(0xdeadbeef, 0xdeadbeef + 99), - Lifespan.span(2, 4), - new URL("ghidra://static"), "DEADBEEF"); + Lifespan.span(2, 4), url("ghidra://static"), "DEADBEEF"); } assertEquals(1, staticMappingManager.getAllEntries().size()); try (Transaction tx = tb.startTransaction()) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java index 816b528514..d308e1b5d4 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceDisassemblerIntegrationTest.java @@ -4,9 +4,9 @@ * 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. @@ -15,7 +15,7 @@ */ package ghidra.trace.database.program; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; @@ -60,11 +60,14 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public LanguageTestWatcher testLanguage = new LanguageTestWatcher(); @Before - public void setUp() throws IOException { + public void setUp() throws Exception { b = new ToyDBTraceBuilder("Testing", testLanguage.getLanguage()); + try (Transaction tx = b.startTransaction()) { + b.createRootObject("Target"); b.trace.getTimeManager().createSnapshot("Initialize"); } + view = b.trace.getProgramView(); } @@ -78,7 +81,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn DuplicateNameException, TraceOverlappedRegionException { try (Transaction tx = b.startTransaction()) { DBTraceMemoryManager memoryManager = b.trace.getMemoryManager(); - memoryManager.createRegion("Region", 0, b.range(0x4000, 0x4fff), + memoryManager.createRegion("Memory[Region]", 0, b.range(0x4000, 0x4fff), TraceMemoryFlag.EXECUTE, TraceMemoryFlag.READ); // NOTE: Disassembler gathers initialized ranges at construction. Disassembler dis = Disassembler.getDisassembler(view, true, true, false, @@ -146,7 +149,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public void testThumbSampleProgramDB() throws Exception { ProgramBuilder b = new ProgramBuilder(getName(), ProgramBuilder._ARM); try (Transaction tx = b.getProgram().openTransaction("Disassemble (THUMB)")) { - MemoryBlock text = b.createMemory(".text", "b6fa2cd0", 32, "Sample", (byte) 0); + MemoryBlock text = b.createMemory("Memory[.text]", "b6fa2cd0", 32, "Sample", (byte) 0); text.putBytes(b.addr(0xb6fa2cdc), new byte[] { // GDB: stmdb sp!, {r4,r5,r6,r7,r8,lr} (byte) 0x2d, (byte) 0xe9, (byte) 0xf0, (byte) 0x41, @@ -173,7 +176,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public void testThumbSampleDBTrace() throws Exception { try (Transaction tx = b.startTransaction()) { DBTraceMemoryManager memory = b.trace.getMemoryManager(); - memory.createRegion(".text", 0, b.range(0xb6fa2cd0, 0xb6fa2cef), + memory.createRegion("Memory[.text]", 0, b.range(0xb6fa2cd0, 0xb6fa2cef), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); memory.putBytes(0, b.addr(0xb6fa2cdc), b.buf( // GDB: stmdb sp!, {r4,r5,r6,r7,r8,lr} @@ -199,7 +202,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public void testDelaySlotSampleDBTrace() throws Exception { try (Transaction tx = b.startTransaction()) { DBTraceMemoryManager memory = b.trace.getMemoryManager(); - memory.createRegion(".text", 0, b.range(0x120000000L, 0x120010000L), + memory.createRegion("Memory[.text]", 0, b.range(0x120000000L, 0x120010000L), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); memory.putBytes(0, b.addr(0x1200035b4L), b.buf( // bal LAB_1200035bc @@ -225,7 +228,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public void test64BitX86DBTrace() throws Exception { try (Transaction tx = b.startTransaction()) { DBTraceMemoryManager memory = b.trace.getMemoryManager(); - memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff)); + memory.createRegion("Memory[.text]", 0, b.range(0x00400000, 0x00400fff)); memory.putBytes(0, b.addr(0x00400000), b.buf( // MOV RCX,RAX; Same encoding as DEC EAX; MOV ECX,EAX outside long mode 0x48, 0x89, 0xc1)); @@ -255,7 +258,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public void test32BitX64CompatDBTrace() throws Exception { try (Transaction tx = b.startTransaction()) { DBTraceMemoryManager memory = b.trace.getMemoryManager(); - memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff)); + memory.createRegion("Memory[.text]", 0, b.range(0x00400000, 0x00400fff)); memory.putBytes(0, b.addr(0x00400000), b.buf( // DEC EAX; but REX.W if context not heeded 0x48, @@ -291,7 +294,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn public void test32BitX86DBTrace() throws Exception { try (Transaction tx = b.startTransaction()) { DBTraceMemoryManager memory = b.trace.getMemoryManager(); - memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff)); + memory.createRegion("Memory[.text]", 0, b.range(0x00400000, 0x00400fff)); memory.putBytes(0, b.addr(0x00400000), b.buf( // DEC EAX 0x48, @@ -311,8 +314,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn } } - record Repetition(Lifespan lifespan, boolean overwrite) { - } + record Repetition(Lifespan lifespan, boolean overwrite) {} protected List toList(Iterable it) { return StreamSupport.stream(it.spliterator(), false).collect(Collectors.toList()); @@ -323,7 +325,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn DBTraceMemoryManager memory = b.trace.getMemoryManager(); DBTraceCodeManager code = b.trace.getCodeManager(); - memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff)); + memory.createRegion("Memory[.text]", 0, b.range(0x00400000, 0x00400fff)); Assembler asm = Assemblers.getAssembler(b.language); Address entry = b.addr(0x00400000); AssemblyBuffer buf = new AssemblyBuffer(asm, entry); @@ -414,7 +416,7 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn DBTraceMemoryManager memory = b.trace.getMemoryManager(); DBTraceCodeManager code = b.trace.getCodeManager(); - memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff)); + memory.createRegion("Memory[.text]", 0, b.range(0x00400000, 0x00400fff)); Assembler asm = Assemblers.getAssembler(b.language); Address entry = b.addr(0x00400000); AssemblyBuffer buf = new AssemblyBuffer(asm, entry); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewListingTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewListingTest.java index c2020f8c5c..ffffd7856e 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewListingTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewListingTest.java @@ -77,6 +77,7 @@ public class DBTraceProgramViewListingTest extends AbstractGhidraHeadlessIntegra public void setUpTraceProgramViewListingTest() throws LanguageNotFoundException, IOException { b = new ToyDBTraceBuilder("Testing", ProgramBuilder._TOY64_BE); try (Transaction tx = b.startTransaction()) { + b.createRootObject("Target"); b.trace.getTimeManager().createSnapshot("Created"); } memory = b.trace.getMemoryManager(); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewMemoryTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewMemoryTest.java index 7c6923f5da..63f9ffb50a 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewMemoryTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/program/DBTraceProgramViewMemoryTest.java @@ -30,9 +30,9 @@ import ghidra.program.model.mem.MemoryBlock; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.memory.DBTraceMemoryManager; -import ghidra.trace.database.memory.DBTraceMemoryRegion; import ghidra.trace.database.program.DBTraceProgramViewMemory.RegionEntry; import ghidra.trace.model.memory.TraceMemoryFlag; +import ghidra.trace.model.memory.TraceMemoryRegion; public class DBTraceProgramViewMemoryTest extends AbstractGhidraHeadlessIntegrationTest { @@ -46,6 +46,7 @@ public class DBTraceProgramViewMemoryTest extends AbstractGhidraHeadlessIntegrat public void setUpTraceProgramViewMemoryTest() throws LanguageNotFoundException, IOException { tb = new ToyDBTraceBuilder("Testing", ProgramBuilder._TOY64_BE); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.trace.getTimeManager().createSnapshot("Created"); } memory = tb.trace.getMemoryManager(); @@ -64,11 +65,11 @@ public class DBTraceProgramViewMemoryTest extends AbstractGhidraHeadlessIntegrat @Test public void testBlockInOverlay() throws Throwable { AddressSpace os; - DBTraceMemoryRegion io; + TraceMemoryRegion io; try (Transaction tx = tb.startTransaction()) { os = memory.createOverlayAddressSpace("test", tb.trace.getBaseAddressFactory().getDefaultAddressSpace()); - io = (DBTraceMemoryRegion) memory.createRegion(".io", 0, tb.range(os, 0x1000, 0x1fff), + io = memory.createRegion("Memory[.io]", 0, tb.range(os, 0x1000, 0x1fff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE, TraceMemoryFlag.VOLATILE); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerObjectTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerObjectTest.java deleted file mode 100644 index 973cc1c9fa..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerObjectTest.java +++ /dev/null @@ -1,66 +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.stack; - -import org.junit.Before; - -import db.Transaction; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; - -public class DBTraceStackManagerObjectTest extends DBTraceStackManagerTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize("" + // - "" + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - ""); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerTest.java index 8a5d1e666e..57e59f5fcd 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/stack/DBTraceStackManagerTest.java @@ -30,16 +30,56 @@ import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStackFrame; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.thread.TraceThread; public class DBTraceStackManagerTest extends AbstractGhidraHeadlessIntegrationTest { + public static final String XML_CTX = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """; + ToyDBTraceBuilder b; DBTraceStackManager stackManager; @Before public void setUpStackManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:default"); + + try (Transaction tx = b.startTransaction()) { + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); + } + stackManager = b.trace.getStackManager(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/symbol/DBTraceSymbolManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/symbol/DBTraceSymbolManagerTest.java index 3825948501..6d901d5613 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/symbol/DBTraceSymbolManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/symbol/DBTraceSymbolManagerTest.java @@ -4,9 +4,9 @@ * 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. @@ -27,24 +27,86 @@ import org.junit.*; import db.Transaction; import ghidra.lifecycle.Unfinished; import ghidra.program.model.address.GlobalNamespace; +import ghidra.program.model.lang.Register; import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.SourceType; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.symbol.TraceLabelSymbol; +import ghidra.trace.model.symbol.TraceLabelSymbolView; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.exception.*; public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationTest implements Unfinished { + + public static final String XML_CTX = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """; + protected ToyDBTraceBuilder b; protected DBTraceSymbolManager manager; @Before - public void setUpTraceSymbolManagerTest() throws IOException { + public void setUpTraceSymbolManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:harvard"); + + try (Transaction tx = b.startTransaction()) { + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); + } + manager = b.trace.getSymbolManager(); } @@ -108,29 +170,24 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT @Test public void testAddLabels() throws Exception { DBTraceNamespaceSymbol global = manager.getGlobalNamespace(); + Register r4 = b.language.getRegister("r4"); try (Transaction tx = b.startTransaction()) { - TraceThread thread = b.getOrAddThread("Thread1", 0); + TraceThread thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); + manager.labels().create(0, b.addr(0x4000), "myLabel", global, SourceType.USER_DEFINED); manager.labels() - .create(0, null, b.addr(0x4000), "myLabel", global, - SourceType.USER_DEFINED); - manager.labels() - .create(0, thread, b.language.getRegister("r4").getAddress(), - "myRegisterLabel", global, SourceType.USER_DEFINED); + .create(0, thread, r4, "myRegisterLabel", global, SourceType.USER_DEFINED); assertEquals(2, manager.labelStore.getRecordCount()); assertRejectsInvalid(name -> manager.labels() - .create(0, null, b.addr(0x4001), name, - global, SourceType.USER_DEFINED)); + .create(0, b.addr(0x4001), name, global, SourceType.USER_DEFINED)); assertRejectsDefault(() -> manager.labels() - .create(0, null, b.addr(0x4001), "myLabel", - global, SourceType.DEFAULT)); + .create(0, b.addr(0x4001), "myLabel", global, SourceType.DEFAULT)); assertEquals(2, manager.labelStore.getRecordCount()); // Accepts duplicates - manager.labels() - .create(0, null, b.addr(0x4001), "myLabel", global, - SourceType.USER_DEFINED); + manager.labels().create(0, b.addr(0x4001), "myLabel", global, SourceType.USER_DEFINED); // TODO: What happens if same name, address, and parent? assertEquals(3, manager.labelStore.getRecordCount()); } @@ -212,12 +269,9 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(0, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "LAB2", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } assertNull(manager.getSymbolByID(-1)); @@ -243,12 +297,9 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(0, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "LAB2", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } // TODO: Test with dynamicSymbols @@ -283,12 +334,9 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(0, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "LAB2", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } assertEquals(Set.of(nsA), @@ -311,12 +359,9 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(0, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "LAB2", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } assertEquals(Set.of(nsA), new HashSet<>(global.getChildren())); assertEquals(Set.of(clsA, lab1), new HashSet<>(nsA.getChildren())); @@ -333,8 +378,8 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - manager.labels().create(0, null, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); - manager.labels().create(0, null, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); + manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } assertEquals(Set.of(nsA), new HashSet<>(manager.namespaces().getGlobalsNamed("a"))); @@ -353,8 +398,8 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - manager.labels().create(0, null, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); - manager.labels().create(0, null, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); + manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } assertEquals(Set.of(nsA), new HashSet<>(manager.namespaces().getGlobals())); @@ -373,12 +418,9 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(0, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "LAB2", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "LAB2", clsA, SourceType.USER_DEFINED); } assertEquals(Set.of(lab1), new HashSet<>(manager.labels().getNamed("LAB1"))); assertEquals(Set.of(lab2), new HashSet<>(manager.allSymbols().getNamed("LAB2"))); @@ -395,12 +437,9 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(0, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(0, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); } assertEquals(Set.of(lab1), new HashSet<>(manager.labels().getWithMatchingName("LAB?", true))); @@ -419,40 +458,31 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT TraceLabelSymbol lab2; TraceLabelSymbol lab3; TraceLabelSymbol lab4; + Register r4 = b.language.getRegister("r4"); + TraceLabelSymbolView labels = manager.labels(); try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(4, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); - lab3 = manager.labels() - .create(0, null, b.addr(0x4001), "lab3", clsA, - SourceType.USER_DEFINED); - lab4 = manager.labels() - .create(0, thread, b.language.getRegister("r4").getAddress(), - "lab4", nsA, SourceType.USER_DEFINED); + lab1 = labels.create(4, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + labels.create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); + lab3 = + labels.create(0, b.addr(0x4001), "lab3", clsA, SourceType.USER_DEFINED); + lab4 = labels.create(0, thread, r4, "lab4", nsA, SourceType.USER_DEFINED); } assertEquals(lab1, - manager.labels().getChildWithNameAt("LAB1", 4, null, b.addr(0x4000), nsA)); - assertNull(manager.labels().getChildWithNameAt("LAB2", 4, null, b.addr(0x4000), nsA)); - assertNull(manager.labels().getChildWithNameAt("LAB1", 0, null, b.addr(0x4000), nsA)); - assertNull(manager.labels() - .getChildWithNameAt("LAB1", 4, thread, - b.language.getRegister("r4").getAddress(), nsA)); - assertNull(manager.labels().getChildWithNameAt("LAB1", 4, null, b.addr(0x4001), nsA)); - assertNull(manager.labels().getChildWithNameAt("LAB1", 4, null, b.addr(0x4000), clsA)); + labels.getChildWithNameAt("LAB1", 4, b.addr(0x4000), nsA)); + assertNull(labels.getChildWithNameAt("LAB2", 4, b.addr(0x4000), nsA)); + assertNull(labels.getChildWithNameAt("LAB1", 0, b.addr(0x4000), nsA)); + assertNull(labels.getChildWithNameAt("LAB1", 4, thread, r4, nsA)); + assertNull(labels.getChildWithNameAt("LAB1", 4, b.addr(0x4001), nsA)); + assertNull(labels.getChildWithNameAt("LAB1", 4, b.addr(0x4000), clsA)); - assertEquals(lab2, - manager.labels().getChildWithNameAt("lab2", 4, null, b.addr(0x4001), clsA)); - assertEquals(lab3, - manager.labels().getChildWithNameAt("lab3", 4, null, b.addr(0x4001), clsA)); - assertEquals(lab4, manager.labels() - .getChildWithNameAt("lab4", 0, thread, - b.language.getRegister("r4").getAddress(), nsA)); + assertEquals(lab2, labels.getChildWithNameAt("lab2", 4, b.addr(0x4001), clsA)); + assertEquals(lab3, labels.getChildWithNameAt("lab3", 4, b.addr(0x4001), clsA)); + assertEquals(lab4, labels.getChildWithNameAt("lab4", 0, thread, r4, nsA)); } @Test @@ -460,11 +490,10 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT DBTraceNamespaceSymbol global = manager.getGlobalNamespace(); TraceLabelSymbol lab1; try (Transaction tx = b.startTransaction()) { - lab1 = manager.labels() - .create(4, null, b.addr(0x4000), "LAB1", global, - SourceType.USER_DEFINED); + lab1 = + manager.labels().create(4, b.addr(0x4000), "LAB1", global, SourceType.USER_DEFINED); } - assertEquals(lab1, manager.labels().getGlobalWithNameAt("LAB1", 4, null, b.addr(0x4000))); + assertEquals(lab1, manager.labels().getGlobalWithNameAt("LAB1", 4, b.addr(0x4000))); } @Test @@ -478,41 +507,30 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT TraceLabelSymbol lab2; TraceLabelSymbol lab3; TraceLabelSymbol lab4; + Register r4 = b.language.getRegister("r4"); + TraceLabelSymbolView labels = manager.labels(); try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(4, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); - lab3 = manager.labels() - .create(0, null, b.addr(0x4001), "lab3", clsA, - SourceType.USER_DEFINED); - lab4 = manager.labels() - .create(0, thread, b.language.getRegister("r4").getAddress(), - "lab4", nsA, SourceType.USER_DEFINED); + lab1 = labels.create(4, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + labels.create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); + lab3 = + labels.create(0, b.addr(0x4001), "lab3", clsA, SourceType.USER_DEFINED); + lab4 = labels.create(0, thread, r4, "lab4", nsA, SourceType.USER_DEFINED); } // TODO: Test that functions are properly excluded from labels() // once I have a means of adding them. - assertEquals(Set.of(), - new HashSet<>(manager.labels() - .getIntersecting(Lifespan.span(0, 0), null, b.range(0x0000, 0x4000), false, - true))); - assertEquals(Set.of(lab1, lab2, lab3), - new HashSet<>(manager.labels() - .getIntersecting(Lifespan.nowOn(0), null, - b.range(0x4000, 0x4001), false, true))); + assertEquals(Set.of(), new HashSet<>( + labels.getIntersecting(Lifespan.span(0, 0), b.range(0x0000, 0x4000), false, true))); + assertEquals(Set.of(lab1, lab2, lab3), new HashSet<>( + labels.getIntersecting(Lifespan.nowOn(0), b.range(0x4000, 0x4001), false, true))); assertEquals(Set.of(lab4), - new HashSet<>(manager.labels() - .getIntersecting(Lifespan.nowOn(0), thread, - TraceRegisterUtils.rangeForRegister(b.language.getRegister("r4")), false, - true))); - assertEquals(Set.of(), new HashSet<>(manager.labels() - .getIntersecting(Lifespan.nowOn(0), - null, b.drng(0x4000, 0x4001), false, true))); + new HashSet<>(labels.getIntersecting(Lifespan.nowOn(0), thread, r4, false, true))); + assertEquals(Set.of(), new HashSet<>( + labels.getIntersecting(Lifespan.nowOn(0), b.drng(0x4000, 0x4001), false, true))); // TODO: Test ordering is by address } @@ -529,25 +547,20 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT try (Transaction tx = b.startTransaction()) { nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(4, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); - lab3 = manager.labels() - .create(0, null, b.addr(0x4001), "lab3", clsA, - SourceType.USER_DEFINED); + lab1 = manager.labels().create(4, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); + lab3 = + manager.labels().create(0, b.addr(0x4001), "lab3", clsA, SourceType.USER_DEFINED); } - assertEquals(Set.of(lab1), - new HashSet<>(manager.labels().getAt(4, null, b.addr(0x4000), false))); + assertEquals(Set.of(lab1), new HashSet<>(manager.labels().getAt(4, b.addr(0x4000), false))); assertEquals(Set.of(lab2, lab3), - new HashSet<>(manager.labels().getAt(4, null, b.addr(0x4001), false))); + new HashSet<>(manager.labels().getAt(4, b.addr(0x4001), false))); // TODO: Test ordering by setPrimary - assertFalse(manager.labels().hasAt(0, null, b.addr(0x4000), false)); - assertTrue(manager.labels().hasAt(4, null, b.addr(0x4000), false)); + assertFalse(manager.labels().hasAt(0, b.addr(0x4000), false)); + assertTrue(manager.labels().hasAt(4, b.addr(0x4000), false)); } @Test @@ -559,20 +572,18 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT DBTraceClassSymbol clsA; TraceLabelSymbol lab2; TraceLabelSymbol lab3; + Register r4 = b.language.getRegister("r4"); try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - manager.labels().create(4, null, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); - lab3 = manager.labels() - .create(0, null, b.addr(0x4001), "lab3", clsA, - SourceType.USER_DEFINED); - manager.labels() - .create(0, thread, b.language.getRegister("r4").getAddress(), "lab4", - nsA, SourceType.USER_DEFINED); + manager.labels().create(4, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = + manager.labels().create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); + lab3 = + manager.labels().create(0, b.addr(0x4001), "lab3", clsA, SourceType.USER_DEFINED); + manager.labels().create(0, thread, r4, "lab4", nsA, SourceType.USER_DEFINED); } try (Transaction tx = b.startTransaction()) { @@ -595,22 +606,17 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT TraceLabelSymbol lab2; TraceLabelSymbol lab3; TraceLabelSymbol lab4; + Register r4 = b.language.getRegister("r4"); try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(4, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); - lab3 = manager.labels() - .create(0, null, b.addr(0x4001), "lab3", clsA, - SourceType.USER_DEFINED); - lab4 = manager.labels() - .create(0, thread, b.language.getRegister("r4").getAddress(), - "lab4", nsA, SourceType.USER_DEFINED); + TraceLabelSymbolView labels = manager.labels(); + lab1 = labels.create(4, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = labels.create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); + lab3 = labels.create(0, b.addr(0x4001), "lab3", clsA, SourceType.USER_DEFINED); + lab4 = labels.create(0, thread, r4, "lab4", nsA, SourceType.USER_DEFINED); } File saved = b.save(); @@ -618,14 +624,12 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT ToyDBTraceBuilder b = new ToyDBTraceBuilder(saved)) { @SuppressWarnings("hiding") DBTraceSymbolManager manager = b.trace.getSymbolManager(); - thread = b.trace.getThreadManager().getThreadsByPath("Thread1").iterator().next(); + thread = b.trace.getThreadManager().getThreadsByPath("Threads[1]").iterator().next(); assertEquals(Set.of(nsA, clsA, lab1, lab2, lab3, lab4), new HashSet<>(manager.allSymbols().getAll(false))); - assertEquals(Set.of(lab2, lab3), - new HashSet<>(manager.labels().getAt(0, null, b.addr(0x4001), false))); - assertEquals(Set.of(lab4), new HashSet<>(manager.labels() - .getAt(0, thread, - b.language.getRegister("r4").getAddress(), false))); + TraceLabelSymbolView labels = manager.labels(); + assertEquals(Set.of(lab2, lab3), new HashSet<>(labels.getAt(0, b.addr(0x4001), false))); + assertEquals(Set.of(lab4), new HashSet<>(labels.getAt(0, thread, r4, false))); } } @@ -640,22 +644,17 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT TraceLabelSymbol lab2; TraceLabelSymbol lab3; TraceLabelSymbol lab4; + Register r4 = b.language.getRegister("r4"); + TraceLabelSymbolView labels = manager.labels(); try (Transaction tx = b.startTransaction()) { - thread = b.getOrAddThread("Thread1", 0); + thread = b.getOrAddThread("Threads[1]", 0); + b.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), b.host, 1); nsA = manager.namespaces().add("a", global, SourceType.USER_DEFINED); clsA = manager.classes().add("A", nsA, SourceType.USER_DEFINED); - lab1 = manager.labels() - .create(4, null, b.addr(0x4000), "LAB1", nsA, - SourceType.USER_DEFINED); - lab2 = manager.labels() - .create(0, null, b.addr(0x4001), "lab2", clsA, - SourceType.USER_DEFINED); - lab3 = manager.labels() - .create(0, null, b.addr(0x4001), "lab3", clsA, - SourceType.USER_DEFINED); - lab4 = manager.labels() - .create(0, thread, b.language.getRegister("r4").getAddress(), - "lab4", nsA, SourceType.USER_DEFINED); + lab1 = labels.create(4, b.addr(0x4000), "LAB1", nsA, SourceType.USER_DEFINED); + lab2 = labels.create(0, b.addr(0x4001), "lab2", clsA, SourceType.USER_DEFINED); + lab3 = labels.create(0, b.addr(0x4001), "lab3", clsA, SourceType.USER_DEFINED); + lab4 = labels.create(0, thread, r4, "lab4", nsA, SourceType.USER_DEFINED); } b.trace.undo(); @@ -666,13 +665,11 @@ public class DBTraceSymbolManagerTest extends AbstractGhidraHeadlessIntegrationT b.trace.redo(); - thread = b.getOrAddThread("Thread1", 0); + thread = b.getOrAddThread("Threads[1]", 0); assertEquals(Set.of(nsA, clsA, lab1, lab2, lab3, lab4), new HashSet<>(manager.allSymbols().getAll(false))); - assertEquals(Set.of(lab2, lab3), - new HashSet<>(manager.labels().getAt(0, null, b.addr(0x4001), false))); - assertEquals(Set.of(lab4), new HashSet<>( - manager.labels().getAt(0, thread, b.language.getRegister("r4").getAddress(), false))); + assertEquals(Set.of(lab2, lab3), new HashSet<>(labels.getAt(0, b.addr(0x4001), false))); + assertEquals(Set.of(lab4), new HashSet<>(labels.getAt(0, thread, r4, false))); } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java index d1ba8ba4cc..96d6c214ca 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java @@ -34,68 +34,20 @@ import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.target.*; import ghidra.trace.model.target.TraceObject.ConflictResolution; -import ghidra.trace.model.target.iface.TraceObjectAggregate; +import ghidra.trace.model.target.iface.TraceAggregate; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.util.database.DBAnnotatedObject; import ghidra.util.database.DBCachedObjectStore; public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationTest { - public static final String XML_CTX = """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """; protected ToyDBTraceBuilder b; protected DBTraceObjectManager manager; - protected SchemaContext ctx; + protected SchemaContext ctx = ToyDBTraceBuilder.CTX_DEFAULT; protected TraceObject root; protected TraceObject targetContainer; @@ -105,8 +57,6 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT public void setUpObjectManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:default"); manager = b.trace.getObjectManager(); - - ctx = XmlSchemaContext.deserialize(XML_CTX); } protected void populateModel(int targetCount) { @@ -317,10 +267,10 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT } assertEquals(Set.of(), - manager.queryAllInterface(Lifespan.toNow(-1), TraceObjectThread.class) + manager.queryAllInterface(Lifespan.toNow(-1), TraceThread.class) .collect(Collectors.toSet())); - assertEquals(Set.of(thread.queryInterface(TraceObjectThread.class)), - manager.queryAllInterface(Lifespan.ALL, TraceObjectThread.class) + assertEquals(Set.of(thread.queryInterface(TraceThread.class)), + manager.queryAllInterface(Lifespan.ALL, TraceThread.class) .collect(Collectors.toSet())); } @@ -431,8 +381,8 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT } assertEquals(Set.of(), root.getInterfaces()); assertEquals(Set.of( - TraceObjectAggregate.class, - TraceObjectThread.class), + TraceAggregate.class, + TraceThread.class), thread.getInterfaces()); } @@ -445,10 +395,10 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT thread = manager.createObject(KeyPath.parse("Targets[0].Threads[0]")); thread.insert(Lifespan.nowOn(0), ConflictResolution.DENY); } - assertNull(root.queryInterface(TraceObjectThread.class)); - TraceObjectThread threadIf = thread.queryInterface(TraceObjectThread.class); + assertNull(root.queryInterface(TraceThread.class)); + TraceThread threadIf = thread.queryInterface(TraceThread.class); assertNotNull(threadIf); - assertSame(threadIf, thread.queryInterface(TraceObjectThread.class)); + assertSame(threadIf, thread.queryInterface(TraceThread.class)); } @Test diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerObjectTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerObjectTest.java deleted file mode 100644 index 543a5c2aec..0000000000 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerObjectTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.trace.database.thread; - -import org.junit.Before; - -import db.Transaction; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; - -public class DBTraceThreadManagerObjectTest extends DBTraceThreadManagerTest { - - protected SchemaContext ctx; - - @Before - public void setUpObjectsMode() throws Exception { - ctx = XmlSchemaContext.deserialize("" + // - "" + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - " " + // - ""); - - try (Transaction tx = b.startTransaction()) { - b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); - } - } -} diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerTest.java index f13fd83a18..2335211c19 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/thread/DBTraceThreadManagerTest.java @@ -15,6 +15,7 @@ */ package ghidra.trace.database.thread; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; import java.util.Set; @@ -27,11 +28,29 @@ import db.Transaction; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; +import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; +import ghidra.trace.model.target.schema.XmlSchemaContext; import ghidra.trace.model.thread.TraceThread; import ghidra.util.exception.DuplicateNameException; public class DBTraceThreadManagerTest extends AbstractGhidraHeadlessIntegrationTest { + public static final String XML_CTX = """ + + + + + + + + + + + + + """; + ToyDBTraceBuilder b; DBTraceThreadManager threadManager; @@ -48,6 +67,12 @@ public class DBTraceThreadManagerTest extends AbstractGhidraHeadlessIntegrationT @Before public void setUpThreadManagerTest() throws Exception { b = new ToyDBTraceBuilder("Testing", "Toy:BE:64:default"); + + try (Transaction tx = b.startTransaction()) { + XmlSchemaContext ctx = XmlSchemaContext.deserialize(XML_CTX); + b.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session"))); + } + threadManager = b.trace.getThreadManager(); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TraceScheduleTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TraceScheduleTest.java index 5f895ea74f..5f0411932e 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TraceScheduleTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/model/time/schedule/TraceScheduleTest.java @@ -31,6 +31,7 @@ import ghidra.test.ToyProgramBuilder; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule.TimeRadix; +import ghidra.util.Msg; import ghidra.util.task.TaskMonitor; public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @@ -279,13 +280,16 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @Test public void testExecute() throws Exception { TestMachine machine = new TestMachine(); - TraceSchedule time = TraceSchedule.parse("1:4;t0-3;t1-2.1"); + TraceSchedule time = TraceSchedule.parse("1:4;t1-3;t3-2.1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", ToyProgramBuilder._TOY64_BE)) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } time.execute(tb.trace, machine, TaskMonitor.DUMMY); @@ -308,13 +312,16 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @Test public void testExecuteWithSkips() throws Exception { TestMachine machine = new TestMachine(); - TraceSchedule time = TraceSchedule.parse("1:4;t0-s3;t1-2.s1"); + TraceSchedule time = TraceSchedule.parse("1:4;t1-s3;t3-2.s1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", ToyProgramBuilder._TOY64_BE)) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } time.execute(tb.trace, machine, TaskMonitor.DUMMY); @@ -339,11 +346,14 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { TestMachine machine = new TestMachine(); TraceSchedule time = TraceSchedule.parse("1:{r0=0x1234};4"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } time.execute(tb.trace, machine, TaskMonitor.DUMMY); @@ -364,6 +374,7 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { TraceSchedule time = TraceSchedule.parse("1:4;t0-3;t1-2.1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.trace.getThreadManager().createThread("Threads[0]", 0); tb.trace.getThreadManager().createThread("Threads[1]", 0); tb.trace.getThreadManager().createThread("Threads[2]", 0); @@ -376,13 +387,16 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @Test(expected = IllegalArgumentException.class) public void testExecuteBadThreadKeyErr() throws Exception { TestMachine machine = new TestMachine(); - TraceSchedule time = TraceSchedule.parse("1:4;t0-3;t5-2.1"); + TraceSchedule time = TraceSchedule.parse("1:4;t1-3;t999-2.1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } time.execute(tb.trace, machine, TaskMonitor.DUMMY); @@ -392,16 +406,19 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @Test public void testFinish() throws Exception { TestMachine machine = new TestMachine(); - TraceSchedule time = TraceSchedule.parse("1:4;t0-3;t1-2.1"); + TraceSchedule time = TraceSchedule.parse("1:4;t1-3;t3-2.1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } - time.finish(tb.trace, TraceSchedule.parse("1:4;t0-2"), machine, TaskMonitor.DUMMY); + time.finish(tb.trace, TraceSchedule.parse("1:4;t1-2"), machine, TaskMonitor.DUMMY); } assertEquals(List.of( @@ -415,16 +432,19 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @Test public void testFinishPcode() throws Exception { TestMachine machine = new TestMachine(); - TraceSchedule time = TraceSchedule.parse("1:4;t0-3;t1-2.1"); + TraceSchedule time = TraceSchedule.parse("1:4;t1-3;t3-2.1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } - time.finish(tb.trace, TraceSchedule.parse("1:4;t0-3;t1-2"), machine, + time.finish(tb.trace, TraceSchedule.parse("1:4;t1-3;t3-2"), machine, TaskMonitor.DUMMY); } @@ -436,40 +456,46 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest { @Test(expected = IllegalArgumentException.class) public void testFinishUnrelatedErr() throws Exception { TestMachine machine = new TestMachine(); - TraceSchedule time = TraceSchedule.parse("1:4;t0-3;t1-2.1"); + TraceSchedule time = TraceSchedule.parse("1:4;t1-3;t3-2.1"); try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { - TraceThread t2; try (Transaction tx = tb.startTransaction()) { - tb.trace.getThreadManager().createThread("Threads[0]", 0); - tb.trace.getThreadManager().createThread("Threads[1]", 0); - t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + tb.createRootObject("Target"); + TraceThread t0 = tb.trace.getThreadManager().createThread("Threads[0]", 0); + Msg.trace(this, "[0] is t%d".formatted(t0.getKey())); + TraceThread t1 = tb.trace.getThreadManager().createThread("Threads[1]", 0); + Msg.trace(this, "[1] is t%d".formatted(t1.getKey())); + TraceThread t2 = tb.trace.getThreadManager().createThread("Threads[2]", 0); + Msg.trace(this, "[2] is t%d".formatted(t2.getKey())); tb.trace.getTimeManager().getSnapshot(1, true).setEventThread(t2); } - time.finish(tb.trace, TraceSchedule.parse("1:4;t0-4"), machine, TaskMonitor.DUMMY); + time.finish(tb.trace, TraceSchedule.parse("1:4;t1-4"), machine, TaskMonitor.DUMMY); } } @Test public void testCoalescePatches() throws Exception { - // TODO: Should parse require coalescing? Can't without passing a language... try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("test", "Toy:BE:64:default")) { TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); thread = tb.trace.getThreadManager().createThread("Threads[0]", 0); } TraceSchedule time = TraceSchedule.parse("0"); time = time.patched(thread, tb.language, "r0l=1"); - assertEquals("0:t0-{r0l=0x1}", time.toString()); + long i = thread.getKey(); + assertEquals("0:t%d-{r0l=0x1}".formatted(i), time.toString()); time = time.patched(thread, tb.language, "r0h=2"); - assertEquals("0:t0-{r0=0x200000001}", time.toString()); + assertEquals("0:t%d-{r0=0x200000001}".formatted(i), time.toString()); time = time.patched(thread, tb.language, "r1l=3") .patched(thread, tb.language, "*[ram]:4 0xcafe:8=0xdeadbeef"); - assertEquals("0:t0-{*:4 0xcafe:8=0xdeadbeef};t0-{r0=0x200000001};t0-{r1l=0x3}", + assertEquals("0:t%d-{*:4 0xcafe:8=0xdeadbeef};t%d-{r0=0x200000001};t%d-{r1l=0x3}" + .formatted(i, i, i), time.toString()); time = time.patched(thread, tb.language, "*:8 0xcb00:8 = 0x1122334455667788"); - assertEquals("0:t0-{*:8 0xcafe:8=0xdead112233445566};t0-{*:2 0xcb06:8=0x7788};" + - "t0-{r0=0x200000001};t0-{r1l=0x3}", time.toString()); + assertEquals(""" + 0:t%d-{*:8 0xcafe:8=0xdead112233445566};t%d-{*:2 0xcb06:8=0x7788};\ + t%d-{r0=0x200000001};t%d-{r1l=0x3}""".formatted(i, i, i, i), time.toString()); } } diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java index 9f060184ea..19bb424538 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java @@ -4,9 +4,9 @@ * 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. @@ -161,6 +161,12 @@ public class DefaultEnumeratedColumnTableModel & EnumeratedTab return modelData; } + public List copyModelData() { + synchronized (modelData) { + return List.copyOf(modelData); + } + } + static class EnumeratedDynamicTableColumn extends AbstractDynamicTableColumn implements EditableDynamicTableColumn { diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java index 5e2f5985a0..c75715684d 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/spatial/AbstractConstraintsTree.java @@ -4,9 +4,9 @@ * 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. @@ -75,7 +75,7 @@ public abstract class AbstractConstraintsTree< // /** * For non-leaf nodes, get the children. - * + *

          * For leaf nodes, the behavior is undefined. Note that the query should not filter the * children, only order them. Filtering is performed by {@link TreeRecordVisitor}. * @@ -86,7 +86,7 @@ public abstract class AbstractConstraintsTree< // /** * For non-leaf nodes, get the children. - * + *

          * For leaf nodes, the behavior is undefined. Note that the query should not filter the * children, only order them, or else the collection will return an incorrect * {@link Collection#size()}. Filtering is performed by {@link TreeRecordVisitor}. @@ -101,7 +101,7 @@ public abstract class AbstractConstraintsTree< // /** * For leaf nodes, get the children. - * + *

          * For non-leaf nodes, the behavior is undefined. Note that the query should not filter the * children, only order them, or else the collection will return an incorrect * {@link Collection#size()}. Filtering is performed by {@link TreeRecordVisitor}. @@ -113,7 +113,7 @@ public abstract class AbstractConstraintsTree< // /** * For leaf nodes, get the children. - * + *

          * For non-leaf nodes, the behavior is undefined. Note that the query should not filter the * children, only order them, or else the collection will return an incorrect * {@link Collection#size()}. Filtering is performed by {@link TreeRecordVisitor}. @@ -129,7 +129,7 @@ public abstract class AbstractConstraintsTree< // /** * Get the children. - * + *

          * Because the children may be either nodes or data, the exact type is not known. The only * guarantee is that it is a tree record, which permits access to its bounds and parent. Note * that the query should not filter the children, only order them, or else the collection will @@ -192,12 +192,12 @@ public abstract class AbstractConstraintsTree< // /** * Called when a node is finished being visited. - * + *

          * This only applies to nodes into which the visitor descends. The visitor will finish a * node in one of three ways: 1) The node's children have all been visited. 2) The visitor * returned {@link VisitResult#TERMINATE} while visiting a descendant. 3) The visitor * returned {@link VisitResult#ASCEND} while visiting a child. - * + *

          * This method may return any result except {@link VisitResult#DESCEND}. If the visitor is * terminating, the return value of this method is ignored. * @@ -602,7 +602,7 @@ public abstract class AbstractConstraintsTree< // /** * Remove a data record from the tree, but keep the orphaned record in the table - * + *

          * Note that at most one orphaned record should be in the table at any time, otherwise behavior * is undefined. It is up to the implementor to provide a means of inserting orphaned data * records back into the tree. This is useful for implementations which allow a data record's @@ -758,7 +758,7 @@ public abstract class AbstractConstraintsTree< // /** * Check the integrity of a single node entry. - * + *

          * This method is for tree developers and testers. Override this method if you have additional * integrity checks. * @@ -853,7 +853,7 @@ public abstract class AbstractConstraintsTree< // /** * Check the integrity of a single data entry. - * + *

          * This method is for tree developers and testers. Override this method if you have additional * integrity checks. * diff --git a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java index b8fef6dd3e..fe25d5e0f0 100644 --- a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java +++ b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java @@ -15,7 +15,8 @@ */ package ghidra.pcode.emu.taint.trace; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.math.BigInteger; import java.nio.ByteBuffer; @@ -36,7 +37,6 @@ import ghidra.program.model.lang.RegisterValue; import ghidra.taint.model.*; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.database.target.DBTraceObjectManager; -import ghidra.trace.database.target.DBTraceObjectManagerTest; import ghidra.trace.model.*; import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.memory.TraceMemoryManager; @@ -45,9 +45,6 @@ import ghidra.trace.model.property.TracePropertyMap; import ghidra.trace.model.property.TracePropertyMapSpace; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.thread.TraceThread; public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest { @@ -299,9 +296,8 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest TraceThread thread; TraceGuestPlatform x64; try (Transaction tx = tb.startTransaction()) { - SchemaContext ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX); DBTraceObjectManager objects = tb.trace.getObjectManager(); - objects.createRootObject(ctx.getSchema(new SchemaName("Session"))); + tb.createRootObject(); thread = tb.getOrAddThread("Targets[0].Threads[0]", 0); x64 = tb.trace.getPlatformManager() diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidraclass/debugger/screenshot/TutorialDebuggerScreenShots.java b/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidraclass/debugger/screenshot/TutorialDebuggerScreenShots.java index 001779ebc2..788aa9fd4a 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidraclass/debugger/screenshot/TutorialDebuggerScreenShots.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/screen/java/ghidraclass/debugger/screenshot/TutorialDebuggerScreenShots.java @@ -100,9 +100,10 @@ import ghidra.program.util.GhidraProgramUtilities; import ghidra.program.util.ProgramSelection; import ghidra.pty.*; import ghidra.test.TestEnv; -import ghidra.trace.model.breakpoint.*; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.guest.TracePlatform; -import ghidra.trace.model.modules.*; +import ghidra.trace.model.modules.TraceModule; +import ghidra.trace.model.modules.TraceSection; import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.time.schedule.*; import ghidra.util.InvalidNameException; @@ -322,16 +323,12 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator } protected void waitBreakSpecExists(String expression) { + long snap = flatDbg.getCurrentSnap(); waitForCondition(() -> flatDbg.getAllBreakpoints() .stream() .flatMap(lb -> lb.getTraceBreakpoints().stream()) - . mapMulti((loc, down) -> { - if (loc instanceof TraceObjectBreakpointLocation oloc) { - down.accept(oloc.getSpecification()); - } - }) .distinct() - .filter(l -> expression.equals(l.getExpression(flatDbg.getCurrentSnap()))) + .filter(l -> expression.equals(l.getSpecification().getExpression(snap))) .count() == 1); } @@ -361,14 +358,9 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator protected Address navigateToBreakpoint(String expression) { long snap = flatDbg.getCurrentSnap(); - TraceBreakpoint bp = flatDbg.getAllBreakpoints() + TraceBreakpointLocation bp = flatDbg.getAllBreakpoints() .stream() .flatMap(l -> l.getTraceBreakpoints().stream()) - . mapMulti((loc, down) -> { - if (loc instanceof TraceObjectBreakpointLocation oloc) { - down.accept(oloc); - } - }) .filter(l -> expression.equals(l.getSpecification().getExpression(snap))) .findAny() .get(); @@ -642,10 +634,9 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator .getSnapshot(snapA, false) .setDescription("Initial snapshot"); } - TraceObjectModule modTermmines = - (TraceObjectModule) Unique.assertOne(flatDbg.getCurrentTrace() - .getModuleManager() - .getModulesAt(snapA, pc)); + TraceModule modTermmines = Unique.assertOne(flatDbg.getCurrentTrace() + .getModuleManager() + .getModulesAt(snapA, pc)); RemoteMethod refreshSections = result.connection().getMethods().get("refresh_sections"); refreshSections.invoke(Map.of("node", modTermmines.getObject())); @@ -679,10 +670,9 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator .getSnapshot(snapA, false) .setDescription("Initial snapshot"); } - TraceObjectModule modTermmines = - (TraceObjectModule) Unique.assertOne(flatDbg.getCurrentTrace() - .getModuleManager() - .getModulesAt(snapA, pc)); + TraceModule modTermmines = Unique.assertOne(flatDbg.getCurrentTrace() + .getModuleManager() + .getModulesAt(snapA, pc)); RemoteMethod refreshSections = result.connection().getMethods().get("refresh_sections"); refreshSections.invoke(Map.of("node", modTermmines.getObject())); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerIntegrationTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerIntegrationTest.java index 38e9331c41..afbd02dd9d 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerIntegrationTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/AbstractGhidraHeadedDebuggerIntegrationTest.java @@ -41,7 +41,7 @@ import ghidra.trace.model.Lifespan; import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; import ghidra.trace.model.memory.TraceMemoryState; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObjectManager; @@ -417,7 +417,7 @@ public class AbstractGhidraHeadedDebuggerIntegrationTest args); } - protected void handleWriteRegInvocation(TraceObjectStackFrame frame, String name, long value) + protected void handleWriteRegInvocation(TraceStackFrame frame, String name, long value) throws Throwable { Map args = rmiMethodWriteReg.expect(); rmiMethodWriteReg.result(null); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java index 83cb2a39d1..55c7f0cbd5 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java @@ -23,7 +23,6 @@ import java.util.*; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import java.util.stream.Stream; import javax.swing.MenuElement; import javax.swing.SwingUtilities; @@ -62,9 +61,9 @@ import ghidra.program.model.mem.MemoryConflictException; import ghidra.program.model.symbol.SourceType; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.program.TraceProgramView; import ghidra.util.SystemUtilities; import ghidra.util.exception.CancelledException; @@ -77,7 +76,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest SystemUtilities.isInTestingBatchMode() ? 5000 : Long.MAX_VALUE; protected static final Map COLOR_FOR_STATE = - Stream.of(State.values()).collect(Collectors.toMap(s -> s, s -> new Color(s.ordinal()))); + State.VALUES.stream().collect(Collectors.toMap(s -> s, s -> new Color(s.ordinal()))); protected static final Set POPUP_ACTIONS = Set.of(AbstractSetBreakpointAction.NAME, AbstractToggleBreakpointAction.NAME, AbstractEnableBreakpointAction.NAME, @@ -109,7 +108,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest */ protected void hackMarkerBackgroundColors(Program p) throws Exception { SwingUtilities.invokeAndWait(() -> { - for (State state : State.values()) { + for (State state : State.VALUES) { if (state == State.NONE) { continue; } @@ -153,11 +152,11 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest protected abstract void handleSetBreakpointInvocation(Set expectedKinds, long dynOffset) throws Throwable; - protected abstract void handleToggleBreakpointInvocation(TraceBreakpoint expectedBreakpoint, - boolean expectedEn) throws Throwable; + protected abstract void handleToggleBreakpointInvocation( + TraceBreakpointLocation expectedBreakpoint, boolean expectedEn) throws Throwable; - protected abstract void handleDeleteBreakpointInvocation(TraceBreakpoint expectedBreakpoint) - throws Throwable; + protected abstract void handleDeleteBreakpointInvocation( + TraceBreakpointLocation expectedBreakpoint) throws Throwable; @Before public void setUpBreakpointMarkerPluginTest() throws Exception { @@ -484,7 +483,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest throws Throwable { addMappedBreakpointOpenAndWait(); // wasteful, but whatever for (LogicalBreakpoint lb : List.copyOf(breakpointService.getAllBreakpoints())) { - TraceBreakpoint brk = Unique.assertOne(lb.getTraceBreakpoints(tb.trace)); + TraceBreakpointLocation brk = Unique.assertOne(lb.getTraceBreakpoints(tb.trace)); CompletableFuture delete = lb.delete(); handleDeleteBreakpointInvocation(brk); waitOn(delete); @@ -523,7 +522,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest public void testActionToggleBreakpointProgramWithNoCurrentBreakpointOnData() throws Throwable { addMappedBreakpointOpenAndWait(); // wasteful, but whatever for (LogicalBreakpoint lb : List.copyOf(breakpointService.getAllBreakpoints())) { - TraceBreakpoint brk = Unique.assertOne(lb.getTraceBreakpoints(tb.trace)); + TraceBreakpointLocation brk = Unique.assertOne(lb.getTraceBreakpoints(tb.trace)); CompletableFuture delete = lb.delete(); handleDeleteBreakpointInvocation(brk); waitOn(delete); @@ -806,7 +805,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest ProgramLocationActionContext ctx = staticCtx(addr(program, 0x00400123)); assertTrue(breakpointMarkerPlugin.actionClearBreakpoint.isAddToPopup(ctx)); - TraceBreakpoint brk = Unique.assertOne(lb.getTraceBreakpoints(trace)); + TraceBreakpointLocation brk = Unique.assertOne(lb.getTraceBreakpoints(trace)); performAction(breakpointMarkerPlugin.actionClearBreakpoint, ctx, true); handleDeleteBreakpointInvocation(brk); @@ -821,7 +820,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest ProgramLocationActionContext ctx = dynamicCtx(trace, addr(trace, 0x55550123)); assertTrue(breakpointMarkerPlugin.actionClearBreakpoint.isAddToPopup(ctx)); - TraceBreakpoint brk = Unique.assertOne(lb.getTraceBreakpoints(trace)); + TraceBreakpointLocation brk = Unique.assertOne(lb.getTraceBreakpoints(trace)); performAction(breakpointMarkerPlugin.actionClearBreakpoint, ctx, true); handleDeleteBreakpointInvocation(brk); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java index b5d282d5ea..b1abe437d6 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java @@ -4,9 +4,9 @@ * 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. @@ -49,9 +49,9 @@ import ghidra.program.model.listing.Program; import ghidra.program.model.mem.MemoryConflictException; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.TraceBreakpoint; import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; import ghidra.trace.model.time.TraceSnapshot; import ghidra.util.SystemUtilities; import ghidra.util.exception.CancelledException; @@ -85,7 +85,7 @@ public abstract class AbstractDebuggerBreakpointsProviderTest protected abstract void addLiveBreakpoint(T target, long offset) throws Throwable; - protected abstract void assertNotLiveBreakpoint(T target, TraceBreakpoint breakpoint) + protected abstract void assertNotLiveBreakpoint(T target, TraceBreakpointLocation breakpoint) throws Throwable; protected void addLiveMemoryAndBreakpoint(P process, T target) throws Throwable { @@ -96,8 +96,8 @@ public abstract class AbstractDebuggerBreakpointsProviderTest protected abstract void handleSetBreakpointInvocation(Set expectedKinds, long dynOffset) throws Throwable; - protected abstract void handleToggleBreakpointInvocation(TraceBreakpoint expectedBreakpoint, - boolean expectedEnabled) throws Throwable; + protected abstract void handleToggleBreakpointInvocation( + TraceBreakpointLocation expectedBreakpoint, boolean expectedEnabled) throws Throwable; protected void addStaticMemoryAndBreakpoint() throws LockException, DuplicateNameException, MemoryConflictException, AddressOverflowException, CancelledException { @@ -600,8 +600,8 @@ public abstract class AbstractDebuggerBreakpointsProviderTest assertEquals(Set.of(trace1, trace3), lb2.getParticipatingTraces()); // Sanity check / experiment: Equal fields, but from different traces - TraceBreakpoint bl1t1 = Unique.assertOne(lb1.getTraceBreakpoints(trace1)); - TraceBreakpoint bl1t3 = Unique.assertOne(lb1.getTraceBreakpoints(trace3)); + TraceBreakpointLocation bl1t1 = Unique.assertOne(lb1.getTraceBreakpoints(trace1)); + TraceBreakpointLocation bl1t3 = Unique.assertOne(lb1.getTraceBreakpoints(trace3)); assertNotEquals(bl1t1, bl1t3); // OK, back to work @@ -710,6 +710,7 @@ public abstract class AbstractDebuggerBreakpointsProviderTest // Do our own launch, so that object mode is enabled during load (region creation) createTrace(program.getLanguageID().getIdAsString()); try (Transaction startTransaction = tb.startTransaction()) { + ProgramEmulationUtils.createObjects(tb.trace); TraceSnapshot initial = tb.trace.getTimeManager().getSnapshot(0, true); ProgramEmulationUtils.loadExecutable(initial, program, List.of()); Address pc = program.getMinAddress(); @@ -767,8 +768,8 @@ public abstract class AbstractDebuggerBreakpointsProviderTest controlService.setCurrentMode(trace, ControlMode.RW_EMULATOR); lbRow1.setEnabled(true); - TraceBreakpoint emuBpt = waitForValue( - () -> Unique.assertAtMostOne(trace.getBreakpointManager().getAllBreakpoints())); + TraceBreakpointLocation emuBpt = waitForValue( + () -> Unique.assertAtMostOne(trace.getBreakpointManager().getAllBreakpointLocations())); assertNotLiveBreakpoint(target, emuBpt); LogicalBreakpointRow lbRow2 = diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointMarkerPluginTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointMarkerPluginTest.java index ca4a19ed74..a152aa39c1 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointMarkerPluginTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointMarkerPluginTest.java @@ -4,9 +4,9 @@ * 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. @@ -28,8 +28,9 @@ import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiTarget; import ghidra.trace.database.target.DBTraceObjectManager; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.*; +import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; @Category(NightlyCategory.class) public class DebuggerRmiBreakpointMarkerPluginTest @@ -135,33 +136,27 @@ public class DebuggerRmiBreakpointMarkerPluginTest } @Override - protected void handleToggleBreakpointInvocation(TraceBreakpoint expectedBreakpoint, + protected void handleToggleBreakpointInvocation(TraceBreakpointLocation expectedLoc, boolean expectedEn) throws Throwable { - if (!(expectedBreakpoint instanceof TraceObjectBreakpointLocation loc)) { - throw new AssertionError("Unexpected trace breakpoint type: " + expectedBreakpoint); - } Map args = rmiMethodToggleBreak.expect(); try (Transaction tx = tb.startTransaction()) { - loc.setEnabled(Lifespan.nowOn(0), expectedEn); + expectedLoc.setEnabled(Lifespan.nowOn(0), expectedEn); } rmiMethodToggleBreak.result(null); assertEquals(Map.ofEntries( - Map.entry("breakpoint", loc.getSpecification().getObject()), + Map.entry("breakpoint", expectedLoc.getSpecification().getObject()), Map.entry("enabled", expectedEn)), args); } @Override - protected void handleDeleteBreakpointInvocation(TraceBreakpoint expectedBreakpoint) + protected void handleDeleteBreakpointInvocation(TraceBreakpointLocation expectedLoc) throws Throwable { - if (!(expectedBreakpoint instanceof TraceObjectBreakpointLocation loc)) { - throw new AssertionError("Unexpected trace breakpoint type: " + expectedBreakpoint); - } Map args = rmiMethodDeleteBreak.expect(); try (Transaction tx = tb.startTransaction()) { - loc.getObject().remove(Lifespan.nowOn(0)); + expectedLoc.getObject().remove(Lifespan.nowOn(0)); } rmiMethodDeleteBreak.result(null); assertEquals(Map.ofEntries( - Map.entry("breakpoint", loc.getSpecification().getObject())), args); + Map.entry("breakpoint", expectedLoc.getSpecification().getObject())), args); } } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java index 1085de4722..d780394a7a 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java @@ -27,9 +27,10 @@ import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiTarget; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; -import ghidra.trace.model.breakpoint.*; +import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.memory.TraceMemoryRegion; public class DebuggerRmiBreakpointsProviderTest extends AbstractDebuggerBreakpointsProviderTest { @@ -107,7 +108,7 @@ public class DebuggerRmiBreakpointsProviderTest try (Transaction tx = trace.openTransaction("Add .text")) { Objects.requireNonNull(addMemoryRegion(trace.getObjectManager(), Lifespan.nowOn(0), tb.range(0x55550000, 0x55550fff), "bin:.text", "rx") - .queryInterface(TraceObjectMemoryRegion.class)); + .queryInterface(TraceMemoryRegion.class)); } } @@ -139,24 +140,21 @@ public class DebuggerRmiBreakpointsProviderTest } @Override - protected void handleToggleBreakpointInvocation(TraceBreakpoint expectedBreakpoint, + protected void handleToggleBreakpointInvocation(TraceBreakpointLocation expectedLoc, boolean expectedEn) throws Throwable { - if (!(expectedBreakpoint instanceof TraceObjectBreakpointLocation loc)) { - throw new AssertionError("Unexpected trace breakpoint type: " + expectedBreakpoint); - } Map args = rmiMethodToggleBreak.expect(); try (Transaction tx = tb.startTransaction()) { - loc.setEnabled(Lifespan.nowOn(0), expectedEn); + expectedLoc.setEnabled(Lifespan.nowOn(0), expectedEn); } rmiMethodToggleBreak.result(null); assertEquals(Map.ofEntries( - Map.entry("breakpoint", loc.getSpecification().getObject()), + Map.entry("breakpoint", expectedLoc.getSpecification().getObject()), Map.entry("enabled", expectedEn)), args); } @Override - protected void assertNotLiveBreakpoint(TraceRmiTarget target, TraceBreakpoint breakpoint) + protected void assertNotLiveBreakpoint(TraceRmiTarget target, TraceBreakpointLocation loc) throws Throwable { - // TODO: Not sure there's anything to do here + // NOTE: Not sure there's anything to do here } } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/control/DebuggerControlPluginTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/control/DebuggerControlPluginTest.java index d187414885..1785086d3a 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/control/DebuggerControlPluginTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/control/DebuggerControlPluginTest.java @@ -54,11 +54,13 @@ import ghidra.program.model.address.Address; import ghidra.program.model.data.ShortDataType; import ghidra.program.model.listing.Instruction; import ghidra.program.util.ProgramLocation; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.model.Lifespan; import ghidra.trace.model.TraceExecutionState; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.program.TraceVariableSnapProgramView; import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.Scheduler; import ghidra.trace.model.time.schedule.TraceSchedule; @@ -247,17 +249,26 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg () -> rmiMethodStepOut); } + SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + TraceThread createToyLoopTrace() throws Throwable { createAndOpenTrace(); Address start = tb.addr(0x00400000); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); Assembler asm = Assemblers.getAssembler(tb.language); AssemblyBuffer buf = new AssemblyBuffer(asm, start); buf.assemble("br 0x" + start); thread = tb.getOrAddThread("Threads[0]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); tb.exec(0, thread, 0, "pc = 0x" + start + ";"); tb.trace.getMemoryManager().putBytes(0, start, ByteBuffer.wrap(buf.getBytes())); } @@ -282,8 +293,10 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg } /** - * Tests the UI so it does not error when the user presses resume after already stepped into a - * pcode instruction. + * Tests the UI so it does not error when the user presses resume after already stepping into a + * p-code instruction. + * + * @throws Throwable because */ @Test public void testEmulateResumeActionAfterPcodeStep() throws Throwable { @@ -291,7 +304,7 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg controlService.setCurrentMode(tb.trace, ControlMode.RW_EMULATOR); traceManager.activateThread(thread); - traceManager.activateTime(TraceSchedule.parse("0:.t0-2")); + traceManager.activateTime(TraceSchedule.parse("0:.t%d-2".formatted(thread.getKey()))); waitForSwing(); performEnabledAction(null, controlPlugin.actionEmulateResume, true); @@ -335,7 +348,7 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg assertFalse(controlPlugin.actionEmulateStepBack.isEnabled()); - traceManager.activateTime(TraceSchedule.parse("0:t0-1")); + traceManager.activateTime(TraceSchedule.parse("0:t%d-1".formatted(thread.getKey()))); waitForSwing(); performEnabledAction(null, controlPlugin.actionEmulateStepBack, true); @@ -354,7 +367,8 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg performEnabledAction(null, controlPlugin.actionEmulateStepInto, true); - assertEquals(TraceSchedule.parse("0:t0-1"), traceManager.getCurrent().getTime()); + assertEquals(TraceSchedule.parse("0:t%d-1".formatted(thread.getKey())), + traceManager.getCurrent().getTime()); } @Test @@ -367,7 +381,8 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg performEnabledAction(null, controlPlugin.actionEmulateSkipOver, true); - assertEquals(TraceSchedule.parse("0:t0-s1"), traceManager.getCurrent().getTime()); + assertEquals(TraceSchedule.parse("0:t%d-s1".formatted(thread.getKey())), + traceManager.getCurrent().getTime()); } protected void create2SnapTrace() throws Throwable { @@ -419,6 +434,7 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg createAndOpenTrace(); TraceVariableSnapProgramView view = tb.trace.getProgramView(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.getOrAddThread("Threads[0]", 0); tb.trace.getMemoryManager() .createRegion("Memory[bin:.text]", 0, tb.range(0x00400000, 0x00401000), @@ -471,6 +487,7 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg createAndOpenTrace(); TraceVariableSnapProgramView view = tb.trace.getProgramView(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.getOrAddThread("Threads[0]", 0); tb.trace.getMemoryManager() .createRegion("Memory[bin:.text]", 0, tb.range(0x00400000, 0x00401000), @@ -527,6 +544,7 @@ public class DebuggerControlPluginTest extends AbstractGhidraHeadedDebuggerInteg createAndOpenTrace(); TraceVariableSnapProgramView view = tb.trace.getProgramView(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.getOrAddThread("Threads[0]", 0); tb.trace.getMemoryManager() .createRegion("Memory[bin:.text]", 0, tb.range(0x00400000, 0x00401000), diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java index 75f2ac9e8c..cbaf3d5c22 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java @@ -39,10 +39,12 @@ import ghidra.program.model.listing.Program; import ghidra.program.model.mem.MemoryBlock; import ghidra.program.util.ProgramLocation; import ghidra.test.ToyProgramBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.model.*; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.schema.SchemaContext; @Category(NightlyCategory.class) public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerIntegrationTest { @@ -78,6 +80,13 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI select(listingProvider, set); } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + @Test public void testActionCopyIntoCurrentProgramWithoutRelocationCreateBlocks() throws Throwable { assertDisabled(copyActionsPlugin.actionCopyIntoCurrentProgram); @@ -89,8 +98,9 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), + .createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.activateTrace(tb.trace); @@ -139,18 +149,19 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI } try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); + mm.createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); mm.putBytes(0, tb.addr(0x00401234), tb.buf(1, 2, 3, 4)); // This region should be excluded, since it cannot be mapped identically into 32-bits - mm.createRegion("lib:.text", 0, tb.range(0x7fff00400000L, 0x7fff0040ffffL), + mm.createRegion("Memory[lib:.text]", 0, tb.range(0x7fff00400000L, 0x7fff0040ffffL), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); // This region should be partially excluded, because 32-bits // This is not likely to ever happen in practice, but be prepared - mm.createRegion(".straddle", 0, tb.range(0xfffff000L, 0x100000fffL), + mm.createRegion("Memory[.straddle]", 0, tb.range(0xfffff000L, 0x100000fffL), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); } @@ -211,8 +222,9 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI intoProject(tb.trace); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), + .createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.activateTrace(tb.trace); @@ -273,8 +285,9 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI intoProject(tb.trace); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), + .createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.activateTrace(tb.trace); @@ -335,8 +348,9 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), + .createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.activateTrace(tb.trace); @@ -377,11 +391,12 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerI createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .createRegion(".text", 0, tb.range(0x55550000, 0x5555ffff), + .createRegion("Memory[.text]", 0, tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); tb.trace.getMemoryManager() - .createRegion(".data", 0, tb.range(0x55560000, 0x5556ffff), + .createRegion("Memory[.data]", 0, tb.range(0x55560000, 0x5556ffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); } traceManager.activateTrace(tb.trace); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java index e8cba9443e..57023fd468 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java @@ -53,6 +53,7 @@ import ghidra.async.SwingExecutorService; import ghidra.debug.api.action.AutoReadMemorySpec; import ghidra.debug.api.control.ControlMode; import ghidra.debug.api.tracemgr.DebuggerCoordinates; +import ghidra.framework.model.*; import ghidra.program.model.address.*; import ghidra.program.model.data.PointerDataType; import ghidra.program.model.lang.Register; @@ -63,6 +64,7 @@ import ghidra.program.model.symbol.SourceType; import ghidra.program.util.OperandFieldLocation; import ghidra.program.util.ProgramLocation; import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.database.stack.DBTraceStackManager; import ghidra.trace.model.*; @@ -71,6 +73,7 @@ import ghidra.trace.model.memory.*; import ghidra.trace.model.modules.TraceModule; import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; @Category(NightlyCategory.class) @@ -114,6 +117,13 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt return data; } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + protected void createMappedTraceAndProgram() throws Exception { createAndOpenTrace(); createAndOpenProgramFromTrace(); @@ -127,8 +137,10 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt monitor, false); } try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceLocation from = new DefaultTraceLocation(tb.trace, null, Lifespan.nowOn(0), tb.addr(0x00400000)); @@ -146,8 +158,10 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt createAndOpenTrace(); traceManager.activateTrace(tb.trace); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForDomainObject(tb.trace); @@ -160,8 +174,10 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt public void testListingViewIsRegionsAddThenActivate() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForDomainObject(tb.trace); @@ -176,10 +192,13 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt public void testRegisterTrackingOnRegisterChange() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - TraceThread thread = tb.getOrAddThread("Thread1", 0); + TraceThread thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); waitForDomainObject(tb.trace); traceManager.activateThread(thread); waitForSwing(); // Ensure the open/activate events are processed first @@ -202,10 +221,13 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt public void testRegisterTrackingOnSnapChange() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - TraceThread thread = tb.getOrAddThread("Thread1", 0); + TraceThread thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); waitForDomainObject(tb.trace); traceManager.activateThread(thread); waitForSwing(); // Ensure the open/activate events are processed first @@ -235,11 +257,15 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread thread1; TraceThread thread2; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); - thread2 = tb.getOrAddThread("Thread2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); // NOTE: PC-tracking should be the default for the main dynamic listing Register pc = tb.trace.getBaseLanguage().getProgramCounter(); @@ -280,11 +306,15 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt () -> listingPlugin.createListingIfMissing(PCLocationTrackingSpec.INSTANCE, true)) .get(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); - thread2 = tb.getOrAddThread("Thread2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); // NOTE: PC-tracking should be the default for the main dynamic listing Register pc = tb.trace.getBaseLanguage().getProgramCounter(); @@ -316,12 +346,15 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt public void testRegisterTrackingOnTrackingSpecChange() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - memory.addRegion("[stack]", Lifespan.nowOn(0), tb.range(0x01000000, 0x01ffffff), + memory.addRegion("Memory[stack]", Lifespan.nowOn(0), tb.range(0x01000000, 0x01ffffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); - TraceThread thread = tb.getOrAddThread("Thread1", 0); + TraceThread thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); waitForDomainObject(tb.trace); traceManager.activateThread(thread); waitForSwing(); // Ensure the open/activate events are processed first @@ -355,11 +388,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread t1, t2; try (Transaction tx = b1.startTransaction()) { + b1.createRootObject(buildContext(), "Target"); b1.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b1.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b1.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b1.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t1 = b1.getOrAddThread("Thread1", 0); + t1 = b1.getOrAddThread("Threads[1]", 0); + b1.createObjectsFramesAndRegs(t1, Lifespan.nowOn(0), b1.host, 1); Register pc = b1.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true); @@ -367,11 +403,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt } waitForDomainObject(b1.trace); try (Transaction tx = b2.startTransaction()) { + b2.createRootObject(buildContext(), "Target"); b2.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b2.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b2.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b2.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t2 = b2.getOrAddThread("Thread2", 0); + t2 = b2.getOrAddThread("Threads[2]", 0); + b2.createObjectsFramesAndRegs(t2, Lifespan.nowOn(0), b2.host, 1); Register pc = b2.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true); @@ -411,11 +450,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread t1, t2; try (Transaction tx = b1.startTransaction()) { + b1.createRootObject(buildContext(), "Target"); b1.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b1.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b1.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b1.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t1 = b1.getOrAddThread("Thread1", 0); + t1 = b1.getOrAddThread("Threads[1]", 0); + b1.createObjectsFramesAndRegs(t1, Lifespan.nowOn(0), b1.host, 1); Register pc = b1.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true); @@ -423,11 +465,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt } waitForDomainObject(b1.trace); try (Transaction tx = b2.startTransaction()) { + b2.createRootObject(buildContext(), "Target"); b2.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b2.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b2.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b2.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t2 = b2.getOrAddThread("Thread2", 0); + t2 = b2.getOrAddThread("Threads[2]", 0); + b2.createObjectsFramesAndRegs(t2, Lifespan.nowOn(0), b2.host, 1); Register pc = b2.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true); @@ -446,7 +491,6 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt loc = listingProvider.getLocation(); assertEquals(b1.trace.getProgramView(), loc.getProgram()); assertEquals(b1.addr(0x00400000), loc.getAddress()); - // TODO: Assert thread? traceManager.activateThread(t2); waitForSwing(); @@ -464,13 +508,16 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); // To keep gray out of the color equation memory.setState(0, tb.range(0x00401233, 0x00401235), TraceMemoryState.KNOWN); - thread = tb.getOrAddThread("Thread1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); Register pc = tb.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234))); @@ -498,15 +545,18 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt } TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceLocation from = new DefaultTraceLocation(tb.trace, null, Lifespan.nowOn(0), tb.addr(0x00400000)); ProgramLocation to = new ProgramLocation(program, ss.getAddress(0x00600000)); DebuggerStaticMappingUtils.addMapping(from, to, 0x8000, false); - thread = tb.getOrAddThread("Thread1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); Register pc = tb.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234))); @@ -635,8 +685,10 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt waitForSwing(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.setState(0, tb.addr(0x00401234), TraceMemoryState.KNOWN); memory.setState(0, tb.addr(0x00401235), TraceMemoryState.ERROR); @@ -694,10 +746,12 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt createAndOpenTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); Register r0 = tb.language.getRegister("r0"); regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16))); @@ -776,12 +830,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt createAndOpenTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - mm.addRegion("[stack]", Lifespan.nowOn(0), tb.range(0x1f000000, 0x1fffffff), + mm.addRegion("Memory[stack]", Lifespan.nowOn(0), tb.range(0x1f000000, 0x1fffffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); Register pc = tb.language.getProgramCounter(); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); @@ -826,12 +882,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt listingProvider.setTrackingSpec(new WatchLocationTrackingSpec("*:4 (r0+0xe000)")); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - mm.addRegion("[stack]", Lifespan.nowOn(0), tb.range(0x1f000000, 0x1fffffff), + mm.addRegion("Memory[stack]", Lifespan.nowOn(0), tb.range(0x1f000000, 0x1fffffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); Register r0 = tb.language.getRegister("r0"); regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16))); @@ -850,11 +908,15 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread thread1; TraceThread thread2; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); - thread2 = tb.getOrAddThread("Thread2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); // NOTE: PC-tracking should be the default for the main dynamic listing Register pc = tb.trace.getBaseLanguage().getProgramCounter(); @@ -977,8 +1039,10 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt assertEquals("(nowhere)", listingProvider.locationLabel.getText()); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .addRegion("test_region", Lifespan.nowOn(0), tb.range(0x55550000, 0x555502ff), + .addRegion("Memory[test_region]", Lifespan.nowOn(0), + tb.range(0x55550000, 0x555502ff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForDomainObject(tb.trace); @@ -987,14 +1051,15 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceModule modExe; try (Transaction tx = tb.startTransaction()) { modExe = tb.trace.getModuleManager() - .addModule("modExe", "modExe", tb.range(0x55550000, 0x555501ff), + .addModule("Modules[modExe]", "modExe", tb.range(0x55550000, 0x555501ff), Lifespan.nowOn(0)); } waitForDomainObject(tb.trace); waitForPass(() -> assertEquals("modExe", listingProvider.locationLabel.getText())); try (Transaction tx = tb.startTransaction()) { - modExe.addSection(0, ".text", tb.range(0x55550000, 0x555500ff)); + modExe.addSection(0, "Modules[modExe].Sections[.text]", + tb.range(0x55550000, 0x555500ff)); } waitForDomainObject(tb.trace); waitForPass(() -> assertEquals("modExe:.text", listingProvider.locationLabel.getText())); @@ -1012,21 +1077,25 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread thread1; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getTimeManager().createSnapshot("First"); tb.trace.getMemoryManager() - .createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), + .createRegion("Memory[.text]", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); tb.exec(0, thread1, 0, "RIP = 0x00400000;"); } TraceThread thread2; try (Transaction tx = tb2.startTransaction()) { + tb2.createRootObject(buildContext(), "Target"); tb2.trace.getTimeManager().createSnapshot("First"); tb2.trace.getMemoryManager() - .createRegion(".text", 0, tb2.range(0x200, 0x3ff), TraceMemoryFlag.READ, - TraceMemoryFlag.EXECUTE); - thread2 = tb2.getOrAddThread("Thread2", 0); + .createRegion("Memory[.text]", 0, tb2.range(0x200, 0x3ff), + TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + thread2 = tb2.getOrAddThread("Threads[2]", 0); + tb2.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); tb2.exec(0, thread2, 0, "PC = 0x100;"); } @@ -1053,11 +1122,15 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt TraceThread thread1; TraceThread thread2; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread 1", 0); - thread2 = tb.getOrAddThread("Thread 2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); + TraceMemorySpace regs1 = mm.getMemoryRegisterSpace(thread1, true); regs1.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); TraceMemorySpace regs2 = mm.getMemoryRegisterSpace(thread2, true); @@ -1084,10 +1157,12 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt Register pc = tb.language.getProgramCounter(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 16))); @@ -1112,10 +1187,11 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt createAndOpenTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); DBTraceStackManager sm = tb.trace.getStackManager(); TraceStack stack = sm.getStack(thread, 0, true); stack.getFrame(0, 0, true).setProgramCounter(Lifespan.ALL, tb.addr(0x00401234)); @@ -1143,9 +1219,11 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt Register pc = tb.language.getProgramCounter(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + tb.createRootObject(buildContext(), "Target"); + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); } @@ -1176,15 +1254,13 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt Register pc = tb.language.getProgramCounter(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + tb.createRootObject(buildContext(), "Target"); + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); - - DBTraceStackManager sm = tb.trace.getStackManager(); - TraceStack stack = sm.getStack(thread, 0, true); - stack.getFrame(0, 0, true); } waitForDomainObject(tb.trace); traceManager.activate(DebuggerCoordinates.NOWHERE.thread(thread).snap(0)); @@ -1210,10 +1286,11 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt DBTraceStackManager sm = tb.trace.getStackManager(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); TraceStack stack = sm.getStack(thread, 0, true); stack.getFrame(0, 0, true).setProgramCounter(Lifespan.ALL, tb.addr(0x00401234)); } @@ -1223,6 +1300,18 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress()); + DomainObjectListener spyListener = new DomainObjectListener() { + @Override + public void domainObjectChanged(DomainObjectChangedEvent ev) { + System.err.println(ev); + for (DomainObjectChangeRecord rec : ev) { + System.err.println(" " + rec); + } + } + }; + tb.trace.addListener(spyListener); + tb.trace.getProgramView().addListener(spyListener); + try (Transaction tx = tb.startTransaction()) { TraceStack stack = sm.getStack(thread, 0, true); stack.getFrame(0, 0, true).setProgramCounter(Lifespan.ALL, tb.addr(0x00404321)); @@ -1234,6 +1323,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt protected Instruction placeGuestInstruction(int guestRangeLength) throws Throwable { try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() .addRegion("Memory[.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); @@ -1357,6 +1447,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerInt ram0 = mm.createOverlayAddressSpace("ram0", ram); ram1 = mm.createOverlayAddressSpace("ram1", ram); + tb.createRootObject(buildContext(), "Target"); mm.createRegion("Memory[0]", 0, tb.range(ram1, 0, 0x1000), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); mm.createRegion("Memory[1]", 0, tb.range(ram0, 0x1000, 0x2000), diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProviderTest.java index 980476c3b6..1b6aa0a3bd 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProviderTest.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.debug.gui.memory; -import static ghidra.lifecycle.Unfinished.TODO; import static org.junit.Assert.*; import static org.junit.Assume.assumeFalse; @@ -62,6 +61,7 @@ import ghidra.program.model.lang.Register; import ghidra.program.model.lang.RegisterValue; import ghidra.program.util.ProgramLocation; import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.database.stack.DBTraceStackManager; @@ -71,6 +71,7 @@ import ghidra.trace.model.memory.*; import ghidra.trace.model.modules.TraceModule; import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.target.TraceObject; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; import ghidra.util.SystemUtilities; @@ -112,13 +113,22 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge return data; } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + @Test public void testBytesViewIsRegionsActivateThenAdd() throws Exception { createAndOpenTrace(); traceManager.activateTrace(tb.trace); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForDomainObject(tb.trace); @@ -133,8 +143,10 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge public void testBytesViewIsRegionsAddThenActivate() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForDomainObject(tb.trace); @@ -149,10 +161,13 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge public void testRegisterTrackingOnRegisterChange() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - TraceThread thread = tb.getOrAddThread("Thread1", 0); + TraceThread thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); waitForDomainObject(tb.trace); traceManager.activateThread(thread); waitForSwing(); // Ensure the open/activate events are processed first @@ -175,10 +190,13 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge public void testRegisterTrackingOnSnapChange() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - TraceThread thread = tb.getOrAddThread("Thread1", 0); + TraceThread thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); waitForDomainObject(tb.trace); traceManager.activateThread(thread); waitForSwing(); // Ensure the open/activate events are processed first @@ -209,11 +227,15 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge TraceThread thread1; TraceThread thread2; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); - thread2 = tb.getOrAddThread("Thread2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); // NOTE: PC-tracking should be the default for the main bytes viewer Register pc = tb.trace.getBaseLanguage().getProgramCounter(); @@ -255,11 +277,15 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge true)) .get(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); - thread2 = tb.getOrAddThread("Thread2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); // NOTE: PC-tracking should be the default for the main bytes viewer Register pc = tb.trace.getBaseLanguage().getProgramCounter(); @@ -291,12 +317,15 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge public void testRegisterTrackingOnTrackingSpecChange() throws Exception { createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - memory.addRegion("[stack]", Lifespan.nowOn(0), tb.range(0x01000000, 0x01ffffff), + memory.addRegion("Memory[stack]", Lifespan.nowOn(0), tb.range(0x01000000, 0x01ffffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); - TraceThread thread = tb.getOrAddThread("Thread1", 0); + TraceThread thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); waitForDomainObject(tb.trace); traceManager.activateThread(thread); waitForSwing(); // Ensure the open/activate events are processed first @@ -329,11 +358,14 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge TraceThread t1, t2; try (Transaction tx = b1.startTransaction()) { + b1.createRootObject(buildContext(), "Target"); b1.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b1.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b1.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b1.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t1 = b1.getOrAddThread("Thread1", 0); + t1 = b1.getOrAddThread("Threads[1]", 0); + b1.createObjectsFramesAndRegs(t1, Lifespan.nowOn(0), b1.host, 1); Register pc = b1.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true); @@ -341,11 +373,14 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge } waitForDomainObject(b1.trace); try (Transaction tx = b2.startTransaction()) { + b2.createRootObject(buildContext(), "Target"); b2.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b2.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b2.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b2.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t2 = b2.getOrAddThread("Thread2", 0); + t2 = b2.getOrAddThread("Threads[2]", 0); + b2.createObjectsFramesAndRegs(t2, Lifespan.nowOn(0), b2.host, 1); Register pc = b2.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true); @@ -380,11 +415,14 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge TraceThread t1, t2; try (Transaction tx = b1.startTransaction()) { + b1.createRootObject(buildContext(), "Target"); b1.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b1.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b1.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b1.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t1 = b1.getOrAddThread("Thread1", 0); + t1 = b1.getOrAddThread("Threads[1]", 0); + b1.createObjectsFramesAndRegs(t1, Lifespan.nowOn(0), b1.host, 1); Register pc = b1.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t1, true); @@ -392,11 +430,14 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge } waitForDomainObject(b1.trace); try (Transaction tx = b2.startTransaction()) { + b2.createRootObject(buildContext(), "Target"); b2.trace.getTimeManager().createSnapshot("First snap"); DBTraceMemoryManager memory = b2.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), b2.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + b2.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - t2 = b2.getOrAddThread("Thread2", 0); + t2 = b2.getOrAddThread("Threads[2]", 0); + b2.createObjectsFramesAndRegs(t2, Lifespan.nowOn(0), b2.host, 1); Register pc = b2.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(t2, true); @@ -412,7 +453,6 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge waitForSwing(); assertEquals(b1.trace.getProgramView(), memBytesProvider.getProgram()); - // TODO: Assert thread? traceManager.activateThread(t2); waitForSwing(); @@ -452,13 +492,16 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); // To keep gray out of the color equation memory.setState(0, tb.range(0x00401233, 0x00401235), TraceMemoryState.KNOWN); - thread = tb.getOrAddThread("Thread1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); Register pc = tb.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, BigInteger.valueOf(0x00401234))); @@ -534,8 +577,10 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge waitForSwing(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); memory.setState(0, tb.addr(0x00401234), TraceMemoryState.KNOWN); memory.setState(0, tb.addr(0x00401235), TraceMemoryState.ERROR); @@ -597,10 +642,12 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge createAndOpenTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); Register r0 = tb.language.getRegister("r0"); regs.setValue(0, new RegisterValue(r0, new BigInteger("00401234", 16))); @@ -641,12 +688,14 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge createAndOpenTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - mm.addRegion("[stack]", Lifespan.nowOn(0), tb.range(0x1f000000, 0x1fffffff), + mm.addRegion("Memory[stack]", Lifespan.nowOn(0), tb.range(0x1f000000, 0x1fffffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); Register pc = tb.language.getProgramCounter(); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); @@ -681,24 +730,21 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge memBytesProvider.actionTrackLocation.getCurrentUserData()); } - @Test - @Ignore("Haven't specified this action, yet") - public void testActionTrackOtherRegister() { - // TODO: Actually, can we make this an arbitrary (pcode/sleigh?) expression. - TODO(); - } - @Test public void testActionFollowsCurrentThread() throws Exception { createAndOpenTrace(); TraceThread thread1; TraceThread thread2; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread1", 0); - thread2 = tb.getOrAddThread("Thread2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); // NOTE: PC-tracking should be the default for the main dynamic listing Register pc = tb.trace.getBaseLanguage().getProgramCounter(); @@ -821,26 +867,30 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge assertEquals("(nowhere)", memBytesProvider.locationLabel.getText()); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() - .addRegion("test_region", Lifespan.nowOn(0), tb.range(0x55550000, 0x555502ff), + .addRegion("Memory[test_region]", Lifespan.nowOn(0), + tb.range(0x55550000, 0x555502ff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForDomainObject(tb.trace); // TODO: This initial goTo should not really be needed goToDyn(tb.addr(0x55550000)); - waitForPass(() -> assertEquals("test_region", memBytesProvider.locationLabel.getText())); + waitForPass( + () -> assertEquals("test_region", memBytesProvider.locationLabel.getText())); TraceModule modExe; try (Transaction tx = tb.startTransaction()) { modExe = tb.trace.getModuleManager() - .addModule("modExe", "modExe", tb.range(0x55550000, 0x555501ff), + .addModule("Modules[modExe]", "modExe", tb.range(0x55550000, 0x555501ff), Lifespan.nowOn(0)); } waitForDomainObject(tb.trace); waitForPass(() -> assertEquals("modExe", memBytesProvider.locationLabel.getText())); try (Transaction tx = tb.startTransaction()) { - modExe.addSection(0, ".text", tb.range(0x55550000, 0x555500ff)); + modExe.addSection(0, "Modules[modExe].Sections[.text]", + tb.range(0x55550000, 0x555500ff)); } waitForDomainObject(tb.trace); waitForPass(() -> assertEquals("modExe:.text", memBytesProvider.locationLabel.getText())); @@ -856,11 +906,15 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge TraceThread thread1; TraceThread thread2; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread1 = tb.getOrAddThread("Thread 1", 0); - thread2 = tb.getOrAddThread("Thread 2", 0); + thread1 = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread1, Lifespan.nowOn(0), tb.host, 1); + thread2 = tb.getOrAddThread("Threads[2]", 0); + tb.createObjectsFramesAndRegs(thread2, Lifespan.nowOn(0), tb.host, 1); + TraceMemorySpace regs1 = mm.getMemoryRegisterSpace(thread1, true); regs1.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); TraceMemorySpace regs2 = mm.getMemoryRegisterSpace(thread2, true); @@ -887,10 +941,12 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge Register pc = tb.language.getProgramCounter(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); regs.setValue(1, new RegisterValue(pc, new BigInteger("00404321", 16))); @@ -915,10 +971,11 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge createAndOpenTrace(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); DBTraceStackManager sm = tb.trace.getStackManager(); TraceStack stack = sm.getStack(thread, 0, true); stack.getFrame(0, 0, true).setProgramCounter(Lifespan.ALL, tb.addr(0x00401234)); @@ -946,9 +1003,11 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge Register pc = tb.language.getProgramCounter(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + tb.createRootObject(buildContext(), "Target"); + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); } @@ -977,15 +1036,13 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge Register pc = tb.language.getProgramCounter(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + tb.createRootObject(buildContext(), "Target"); + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regs = mm.getMemoryRegisterSpace(thread, true); regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16))); - - DBTraceStackManager sm = tb.trace.getStackManager(); - TraceStack stack = sm.getStack(thread, 0, true); - stack.getFrame(0, 0, true); } waitForDomainObject(tb.trace); traceManager.activate(DebuggerCoordinates.NOWHERE.thread(thread).snap(0)); @@ -1011,10 +1068,12 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge DBTraceStackManager sm = tb.trace.getStackManager(); TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + mm.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); - thread = tb.getOrAddThread("Thread 1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceStack stack = sm.getStack(thread, 0, true); stack.getFrame(0, 0, true).setProgramCounter(Lifespan.ALL, tb.addr(0x00401234)); } @@ -1190,6 +1249,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge } @Test + @Ignore("Enable manually") public void testPerformanceManuallyWithManyManySnaps() throws Exception { assumeFalse(SystemUtilities.isInTestingBatchMode()); createAndOpenTrace(); @@ -1197,6 +1257,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge // LATER (GP-5594): 100_000 without checkStateMapIntegrity will crash. final long snapCount = 100_000; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(SCHEMA_CTX); tb.trace.getMemoryManager() .addRegion("Processes[1].Memory[exe:.text]", Lifespan.nowOn(0L), tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/AbstractDebuggerRegistersProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/AbstractDebuggerRegistersProviderTest.java index 16b8e7586c..89bead3088 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/AbstractDebuggerRegistersProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/AbstractDebuggerRegistersProviderTest.java @@ -4,9 +4,9 @@ * 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. @@ -81,6 +81,11 @@ public abstract class AbstractDebuggerRegistersProviderTest waitForComponentProvider(DebuggerListingProvider.class).setAutoDisassemble(false); createTrace(); + + try (Transaction tx = tb.startTransaction()) { + tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); + } + r0 = tb.language.getRegister("r0"); pc = tb.language.getProgramCounter(); sp = tb.language.getDefaultCompilerSpec().getStackPointer(); @@ -109,6 +114,9 @@ public abstract class AbstractDebuggerRegistersProviderTest controlService = addPlugin(tool, DebuggerControlServicePlugin.class); createTrace(); + try (Transaction tx = tb.startTransaction()) { + tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); + } createToyPlatform(); r0 = tb.reg(toy, "r0"); @@ -134,12 +142,14 @@ public abstract class AbstractDebuggerRegistersProviderTest } protected TraceThread addThread() throws DuplicateNameException { - return addThread("Thread1"); + return addThread("Processes[1].Threads[1]"); } protected TraceThread addThread(String threadName) throws DuplicateNameException { try (Transaction tx = tb.startTransaction()) { - return tb.trace.getThreadManager().createThread(threadName, 0); + TraceThread thread = tb.trace.getThreadManager().createThread(threadName, 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); + return thread; } } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRmiRegistersProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRmiRegistersProviderTest.java index e1fa0fdacd..75ec52e151 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRmiRegistersProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRmiRegistersProviderTest.java @@ -26,21 +26,19 @@ import db.Transaction; import ghidra.debug.api.control.ControlMode; import ghidra.program.model.data.DoubleDataType; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; public class DebuggerRmiRegistersProviderTest extends AbstractDebuggerRegistersProviderTest { protected TraceObject setUpRmiTarget() throws Throwable { createRmiConnection(); addRegisterMethods(); - createTrace(); try (Transaction tx = tb.startTransaction()) { - tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); tb.createObjectsProcessAndThreads(); tb.createObjectsFramesAndRegs( - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class), + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class), Lifespan.nowOn(0), tb.host, 2); } rmiCx.publishTarget(tool, tb.trace); @@ -71,7 +69,7 @@ public class DebuggerRmiRegistersProviderTest extends AbstractDebuggerRegistersP setRowText(row, "1234"); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r0", 0x1234); } @@ -93,7 +91,7 @@ public class DebuggerRmiRegistersProviderTest extends AbstractDebuggerRegistersP setRowRepr(row, "1234"); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r0", encodeDouble(1234)); } } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerTraceRegistersProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerTraceRegistersProviderTest.java index 1262d695a4..90b7c1c35e 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerTraceRegistersProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerTraceRegistersProviderTest.java @@ -463,7 +463,7 @@ public class DebuggerTraceRegistersProviderTest extends AbstractDebuggerRegister assertFalse(registersProvider.actionCreateSnapshot.isEnabled()); TraceThread thread1 = addThread(); - TraceThread thread2 = addThread("Thread2"); + TraceThread thread2 = addThread("Processes[1].Threads[2]"); addRegisterValues(thread1); addRegisterTypes(thread1); traceManager.openTrace(tb.trace); @@ -483,7 +483,7 @@ public class DebuggerTraceRegistersProviderTest extends AbstractDebuggerRegister DebuggerRegistersProvider cloned = (DebuggerRegistersProvider) tool.getActiveComponentProvider(); assertEquals("[Registers]", cloned.getTitle()); - assertEquals("Thread1", cloned.getSubTitle()); + assertEquals("Processes[1].Threads[1]", cloned.getSubTitle()); activateThread(thread2); waitForSwing(); @@ -518,7 +518,8 @@ public class DebuggerTraceRegistersProviderTest extends AbstractDebuggerRegister try (Transaction tx = tb.startTransaction()) { // Unconventional start, to ensure goto PC is actually the cause, not just min of view tb.trace.getMemoryManager() - .addRegion("bin:.text", Lifespan.nowOn(0), tb.range(0x00300000, 0x00500000), + .addRegion("Processes[1].Memory[bin:.text]", Lifespan.nowOn(0), + tb.range(0x00300000, 0x00500000), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } addRegisterValues(thread); @@ -589,7 +590,7 @@ public class DebuggerTraceRegistersProviderTest extends AbstractDebuggerRegister public void testTraceThreadActivation() throws Exception { traceManager.openTrace(tb.trace); TraceThread thread1 = addThread(); - TraceThread thread2 = addThread("Thread2"); + TraceThread thread2 = addThread("Processes[1].Threads[2]"); addRegisterValues(thread1); activateThread(thread2); waitForSwing(); @@ -625,7 +626,8 @@ public class DebuggerTraceRegistersProviderTest extends AbstractDebuggerRegister TraceThread thread3; try (Transaction tx = ub.startTransaction()) { - thread3 = ub.trace.getThreadManager().createThread("Thread3", 0); + ub.createRootObject("Target"); // Different schema from first, because why not? + thread3 = ub.trace.getThreadManager().createThread("Threads[3]", 0); } traceManager.activateTrace(ub.trace); waitForDomainObject(ub.trace); @@ -701,6 +703,7 @@ public class DebuggerTraceRegistersProviderTest extends AbstractDebuggerRegister assertR0RowTypePopulated(); try (Transaction tx = tb.startTransaction()) { + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 2); TraceMemorySpace regVals = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, 1, true); regVals.putBytes(getPlatform(), 0, pc, tb.buf(0, 0, 0, 0, 0, 0x50, 0, 0)); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java index 54ae229f0d..829b265990 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java @@ -53,9 +53,9 @@ import ghidra.program.util.ProgramLocation; import ghidra.trace.model.DefaultTraceLocation; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.*; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.util.TraceRegisterUtils; import ghidra.util.Msg; import ghidra.util.task.TaskMonitor; @@ -79,7 +79,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt protected Register r0; protected Register r1; - protected TraceObjectThread thread; + protected TraceThread thread; @Before public void setUpWatchesProviderTest() throws Exception { @@ -100,7 +100,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); tb.createObjectsProcessAndThreads(); - thread = tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + thread = tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); } // TODO: This seems to hold up the task manager. @@ -117,7 +117,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt } } - private void setRegisterValues(TraceObjectThread thread) { + private void setRegisterValues(TraceThread thread) { try (Transaction tx = tb.startTransaction()) { tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); TraceMemorySpace regVals = @@ -318,7 +318,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); tb.createObjectsFramesAndRegs( - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class), + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class), Lifespan.nowOn(0), tb.host, 1); } waitForDomainObject(tb.trace); @@ -566,7 +566,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt tb.range(0x55550000, 0x5555ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); tb.createObjectsFramesAndRegs( - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class), + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class), Lifespan.nowOn(0), tb.host, 1); tb.obj("Processes[1].Threads[1].Stack[0].Registers[r1]").delete(); @@ -606,7 +606,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt runSwing(() -> row.setRawValueString("0x1234")); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r0", 0x1234); rmiCx.withdrawTarget(tool, tb.trace); @@ -661,7 +661,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt protected void setupUnmappedDataSection() throws Throwable { try (Transaction tx = tb.startTransaction()) { - TraceMemoryOperations mem = tb.trace.getMemoryManager(); + TraceMemoryManager mem = tb.trace.getMemoryManager(); mem.createRegion("Processes[1].Memory[bin:.data]", 0, tb.range(0x00600000, 0x0060ffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); } @@ -678,7 +678,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerInt intoProject(program); try (Transaction tx = tb.startTransaction()) { - TraceMemoryOperations mem = tb.trace.getMemoryManager(); + TraceMemoryManager mem = tb.trace.getMemoryManager(); mem.createRegion("Processes[1].Memory[bin:.data]", 0, tb.range(0x55750000, 0x5575ffff), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE); } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/AbstractDebuggerLogicalBreakpointServiceTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/AbstractDebuggerLogicalBreakpointServiceTest.java index 2b7a089529..cc993ecf7a 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/AbstractDebuggerLogicalBreakpointServiceTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/AbstractDebuggerLogicalBreakpointServiceTest.java @@ -44,6 +44,8 @@ import ghidra.trace.model.*; import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.trace.model.memory.TraceMemoryRegion; +import ghidra.trace.model.target.TraceObject.ConflictResolution; +import ghidra.trace.model.target.path.KeyPath; import ghidra.util.Msg; import ghidra.util.SystemUtilities; @@ -152,15 +154,14 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest protected abstract void terminateTarget(T t); - protected abstract TraceBreakpoint findLoc(long snap, Set locs, int index); + protected abstract TraceBreakpointLocation findLoc(long snap, Set locs, + int index); protected abstract void handleToggleBreakpointInvocation(T target, - TraceBreakpoint expectedBreakpoint, - boolean expectedEnabled) throws Throwable; + TraceBreakpointLocation expectedBreakpoint, boolean expectedEnabled) throws Throwable; protected abstract void handleDeleteBreakpointInvocation(T target, - TraceBreakpoint expectedBreakpoint) - throws Throwable; + TraceBreakpointLocation expectedBreakpoint) throws Throwable; @Before public void setUpBreakpointServiceTest() throws Throwable { @@ -293,7 +294,8 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertNull(enLb.getProgramLocation()); assertEquals(Set.of(TraceBreakpointKind.READ, TraceBreakpointKind.WRITE), enLb.getKinds()); - TraceBreakpoint bpt = Unique.assertOne(trace.getBreakpointManager().getAllBreakpoints()); + TraceBreakpointLocation bpt = + Unique.assertOne(trace.getBreakpointManager().getAllBreakpointLocations()); assertEquals(Set.of(trace), enLb.getMappedTraces()); assertEquals(addr(trace, 0x56550123), enLb.getTraceAddress(trace)); assertEquals(Set.of(bpt), enLb.getTraceBreakpoints(trace)); @@ -314,7 +316,8 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertNull(enLb.getProgramLocation()); assertEquals(Set.of(TraceBreakpointKind.SW_EXECUTE), enLb.getKinds()); - TraceBreakpoint bpt = Unique.assertOne(trace.getBreakpointManager().getAllBreakpoints()); + TraceBreakpointLocation bpt = + Unique.assertOne(trace.getBreakpointManager().getAllBreakpointLocations()); assertEquals(Set.of(trace), enLb.getMappedTraces()); assertEquals(addr(trace, offset), enLb.getTraceAddress(trace)); assertEquals(Set.of(bpt), enLb.getTraceBreakpoints(trace)); @@ -331,7 +334,8 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertEquals(State.ENABLED, enLb.computeStateForProgram(program)); assertEquals(Set.of(TraceBreakpointKind.SW_EXECUTE), enLb.getKinds()); - TraceBreakpoint bpt = Unique.assertOne(trace.getBreakpointManager().getAllBreakpoints()); + TraceBreakpointLocation bpt = + Unique.assertOne(trace.getBreakpointManager().getAllBreakpointLocations()); assertEquals(Set.of(trace), enLb.getMappedTraces()); assertEquals(addr(trace, 0x55550123), enLb.getTraceAddress(trace)); assertEquals(Set.of(bpt), enLb.getTraceBreakpoints(trace)); @@ -402,8 +406,10 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertEquals(addr(trace1, 0x55550123), enLb.getTraceAddress(trace1)); assertEquals(addr(trace2, 0x55551123), enLb.getTraceAddress(trace2)); - TraceBreakpoint bpt1 = Unique.assertOne(trace1.getBreakpointManager().getAllBreakpoints()); - TraceBreakpoint bpt2 = Unique.assertOne(trace2.getBreakpointManager().getAllBreakpoints()); + TraceBreakpointLocation bpt1 = + Unique.assertOne(trace1.getBreakpointManager().getAllBreakpointLocations()); + TraceBreakpointLocation bpt2 = + Unique.assertOne(trace2.getBreakpointManager().getAllBreakpointLocations()); assertEquals(Set.of(bpt1), enLb.getTraceBreakpoints(trace1)); assertEquals(Set.of(bpt2), enLb.getTraceBreakpoints(trace2)); assertNotEquals(Set.of(bpt2), enLb.getTraceBreakpoints(trace1)); // Sanity check @@ -441,7 +447,8 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertEquals(Set.of(trace), enLb.getMappedTraces()); assertEquals(addr(trace, 0x55550123), enLb.getTraceAddress(trace)); - TraceBreakpoint bpt = Unique.assertOne(trace.getBreakpointManager().getAllBreakpoints()); + TraceBreakpointLocation bpt = + Unique.assertOne(trace.getBreakpointManager().getAllBreakpointLocations()); assertEquals(Set.of(bpt), enLb.getTraceBreakpoints(trace)); assertEquals(Set.of(bpt), enLb.getTraceBreakpoints()); @@ -1339,12 +1346,11 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints()); - int id = Integer.parseInt( - ((TraceObjectBreakpointLocation) Unique.assertOne(lb.getTraceBreakpoints(trace))) - .getSpecification() - .getObject() - .getCanonicalPath() - .index()); + int id = Integer.parseInt(Unique.assertOne(lb.getTraceBreakpoints(trace)) + .getSpecification() + .getObject() + .getCanonicalPath() + .index()); // Simulate a step, which should also cause snap advance in target simulateTargetStep(target1); @@ -1414,11 +1420,11 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertEquals(2, lb.getTraceBreakpoints().size()); - Set locs = lb.getTraceBreakpoints(); + Set locs = lb.getTraceBreakpoints(); long snap = getSnap(target1); - TraceBreakpoint bpt0 = findLoc(snap, locs, 0); - TraceBreakpoint bpt1 = findLoc(snap, locs, 1); + TraceBreakpointLocation bpt0 = findLoc(snap, locs, 0); + TraceBreakpointLocation bpt1 = findLoc(snap, locs, 1); CompletableFuture disable = breakpointService.disableLocs(Set.of(bpt0)); handleToggleBreakpointInvocation(target1, bpt0, false); waitOn(disable); @@ -1517,6 +1523,12 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest intoProject(program); programManager.openProgram(program); + try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(SCHEMA_CTX); + tb.trace.getObjectManager() + .createObject(KeyPath.parse("Processes[1].Breakpoints")) + .insert(Lifespan.nowOn(0), ConflictResolution.DENY); + } addTextMappingDead(0, program, tb); addEnabledProgramBreakpointWithSleigh(program); @@ -1531,7 +1543,7 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest waitForDomainObject(program); waitOn(breakpointService.changesSettled()); - TraceBreakpoint bpt = Unique.assertOne( + TraceBreakpointLocation bpt = Unique.assertOne( tb.trace.getBreakpointManager().getBreakpointsAt(0, tb.addr(0x55550123))); assertEquals("r0=0xbeef;", bpt.getEmuSleigh(0)); } @@ -1552,6 +1564,12 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest assertEquals("r0=0xbeef;", lb.getEmuSleigh()); + try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(SCHEMA_CTX); + tb.trace.getObjectManager() + .createObject(KeyPath.parse("Processes[1].Breakpoints")) + .insert(Lifespan.nowOn(0), ConflictResolution.DENY); + } addTextMappingDead(0, program, tb); waitOn(mappingService.changesSettled()); waitOn(breakpointService.changesSettled()); @@ -1563,7 +1581,7 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest waitForDomainObject(program); waitOn(breakpointService.changesSettled()); - TraceBreakpoint bpt = Unique.assertOne( + TraceBreakpointLocation bpt = Unique.assertOne( tb.trace.getBreakpointManager().getBreakpointsAt(0, tb.addr(0x55550123))); assertEquals("r0=0xbeef;", bpt.getEmuSleigh(0)); } @@ -1585,8 +1603,9 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest programManager.openProgram(program); try (Transaction tid = tb.startTransaction()) { - TraceBreakpoint bpt = tb.trace.getBreakpointManager() - .addBreakpoint("Processes[1].Breakpoints[0]", Lifespan.nowOn(0), + tb.createRootObject(SCHEMA_CTX); + TraceBreakpointLocation bpt = tb.trace.getBreakpointManager() + .addBreakpoint("Processes[1].Breakpoints[0][0]", Lifespan.nowOn(0), tb.addr(0x55550123), Set.of(), Set.of(TraceBreakpointKind.SW_EXECUTE), false /* emuEnabled defaults to true */, ""); bpt.setEmuSleigh(0, "r0=0xbeef;"); @@ -1639,7 +1658,7 @@ public abstract class AbstractDebuggerLogicalBreakpointServiceTest programManager.openProgram(program); try (Transaction tid = tb.startTransaction()) { - TraceBreakpoint bpt = tb.trace.getBreakpointManager() + TraceBreakpointLocation bpt = tb.trace.getBreakpointManager() .addBreakpoint("Processes[1].Breakpoints[0]", Lifespan.nowOn(0), tb.addr(0x55550123), Set.of(), Set.of(TraceBreakpointKind.SW_EXECUTE), diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerRmiLogicalBreakpointServiceTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerRmiLogicalBreakpointServiceTest.java index ec61930e2c..baa65a74e3 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerRmiLogicalBreakpointServiceTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerRmiLogicalBreakpointServiceTest.java @@ -29,16 +29,17 @@ import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.trace.database.ToyDBTraceBuilder; import ghidra.trace.model.*; -import ghidra.trace.model.breakpoint.*; import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet; -import ghidra.trace.model.memory.TraceObjectMemoryRegion; +import ghidra.trace.model.breakpoint.TraceBreakpointLocation; +import ghidra.trace.model.breakpoint.TraceBreakpointSpec; +import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.modules.TraceStaticMapping; import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.time.TraceSnapshot; public class DebuggerRmiLogicalBreakpointServiceTest extends - AbstractDebuggerLogicalBreakpointServiceTest { + AbstractDebuggerLogicalBreakpointServiceTest { ToyDBTraceBuilder tb3; @@ -101,42 +102,42 @@ public class DebuggerRmiLogicalBreakpointServiceTest extends } @Override - protected TraceObjectMemoryRegion addTargetTextRegion(TraceRmiTarget target, long offset) + protected TraceMemoryRegion addTargetTextRegion(TraceRmiTarget target, long offset) throws Throwable { Trace trace = target.getTrace(); - TraceObjectMemoryRegion result; + TraceMemoryRegion result; try (Transaction tx = trace.openTransaction("Add .text")) { result = Objects.requireNonNull( addMemoryRegion(trace.getObjectManager(), Lifespan.nowOn(target.getSnap()), tb.range(offset, offset + 0x0fff), "bin:.text", "rx") - .queryInterface(TraceObjectMemoryRegion.class)); + .queryInterface(TraceMemoryRegion.class)); } waitForDomainObject(trace); return result; } @Override - protected TraceObjectMemoryRegion addTargetTextRegion(TraceRmiTarget target) throws Throwable { + protected TraceMemoryRegion addTargetTextRegion(TraceRmiTarget target) throws Throwable { return addTargetTextRegion(target, 0x55550000); } @Override - protected TraceObjectMemoryRegion addTargetDataRegion(TraceRmiTarget target) throws Throwable { + protected TraceMemoryRegion addTargetDataRegion(TraceRmiTarget target) throws Throwable { Trace trace = target.getTrace(); long offset = 0x56550000; - TraceObjectMemoryRegion result; + TraceMemoryRegion result; try (Transaction tx = trace.openTransaction("Add .data")) { result = Objects.requireNonNull( addMemoryRegion(trace.getObjectManager(), Lifespan.nowOn(target.getSnap()), tb.range(offset, offset + 0x0fff), "bin:.data", "rw") - .queryInterface(TraceObjectMemoryRegion.class)); + .queryInterface(TraceMemoryRegion.class)); } waitForDomainObject(trace); return result; } @Override - protected void addTextMapping(TraceRmiTarget target, TraceObjectMemoryRegion text, + protected void addTextMapping(TraceRmiTarget target, TraceMemoryRegion text, Program program) throws Throwable { Trace trace = target.getTrace(); long snap = getSnap(target); @@ -162,7 +163,7 @@ public class DebuggerRmiLogicalBreakpointServiceTest extends } @Override - protected void addTargetAccessBreakpoint(TraceRmiTarget target, TraceObjectMemoryRegion region) + protected void addTargetAccessBreakpoint(TraceRmiTarget target, TraceMemoryRegion region) throws Throwable { Address min = region.getMinAddress(getSnap(target)).add(0x0123); Trace trace = target.getTrace(); @@ -175,7 +176,7 @@ public class DebuggerRmiLogicalBreakpointServiceTest extends @Override protected void addTargetSoftwareBreakpoint(TraceRmiTarget target, - TraceObjectMemoryRegion region, int offset, Integer id) throws Throwable { + TraceMemoryRegion region, int offset, Integer id) throws Throwable { Address min = region.getMinAddress(getSnap(target)).add(offset); Trace trace = target.getTrace(); try (Transaction tx = trace.openTransaction("Add software breakpoint")) { @@ -190,20 +191,18 @@ public class DebuggerRmiLogicalBreakpointServiceTest extends Trace trace = target.getTrace(); long snap = target.getSnap(); Lifespan nowOn = Lifespan.nowOn(snap); - List locsToDel = trace.getBreakpointManager() - .getAllBreakpoints() + List locsToDel = trace.getBreakpointManager() + .getAllBreakpointLocations() .stream() - .filter(bp -> bp.getKinds(snap).equals(TraceBreakpointKindSet.SW_EXECUTE)) - .filter(bp -> bp instanceof TraceObjectBreakpointLocation) - .map(bp -> (TraceObjectBreakpointLocation) bp) + .filter(loc -> loc.getKinds(snap).equals(TraceBreakpointKindSet.SW_EXECUTE)) .toList(); - List specsToDel = + List specsToDel = locsToDel.stream().map(bp -> bp.getSpecification()).distinct().toList(); try (Transaction tx = trace.openTransaction("Delete software breakpoints")) { - for (TraceObjectBreakpointLocation loc : locsToDel) { + for (TraceBreakpointLocation loc : locsToDel) { loc.getObject().remove(nowOn); } - for (TraceObjectBreakpointSpec spec : specsToDel) { + for (TraceBreakpointSpec spec : specsToDel) { spec.getObject().remove(nowOn); } } @@ -216,7 +215,8 @@ public class DebuggerRmiLogicalBreakpointServiceTest extends } @Override - protected TraceBreakpoint findLoc(long snap, Set locs, int index) { + protected TraceBreakpointLocation findLoc(long snap, Set locs, + int index) { return locs.stream() .filter(b -> b.getName(snap).equals(Integer.toString(index + 1))) .findAny() @@ -225,34 +225,28 @@ public class DebuggerRmiLogicalBreakpointServiceTest extends @Override protected void handleToggleBreakpointInvocation(TraceRmiTarget target, - TraceBreakpoint expectedBreakpoint, boolean expectedEn) throws Throwable { - if (!(expectedBreakpoint instanceof TraceObjectBreakpointLocation loc)) { - throw new AssertionError("Unexpected trace breakpoint type: " + expectedBreakpoint); - } + TraceBreakpointLocation expectedLoc, boolean expectedEn) throws Throwable { Map args = rmiMethodToggleBreak.expect(); try (Transaction tx = tb.startTransaction()) { - loc.setEnabled(Lifespan.nowOn(target.getSnap()), expectedEn); + expectedLoc.setEnabled(Lifespan.nowOn(target.getSnap()), expectedEn); } waitForDomainObject(tb.trace); rmiMethodToggleBreak.result(null); assertEquals(Map.ofEntries( - Map.entry("breakpoint", loc.getSpecification().getObject()), + Map.entry("breakpoint", expectedLoc.getSpecification().getObject()), Map.entry("enabled", expectedEn)), args); } @Override protected void handleDeleteBreakpointInvocation(TraceRmiTarget target, - TraceBreakpoint expectedBreakpoint) throws Throwable { - if (!(expectedBreakpoint instanceof TraceObjectBreakpointLocation loc)) { - throw new AssertionError("Unexpected trace breakpoint type: " + expectedBreakpoint); - } + TraceBreakpointLocation expectedLoc) throws Throwable { Map args = rmiMethodDeleteBreak.expect(); try (Transaction tx = tb.startTransaction()) { - loc.getObject().removeTree(Lifespan.nowOn(target.getSnap())); + expectedLoc.getObject().removeTree(Lifespan.nowOn(target.getSnap())); } waitForDomainObject(tb.trace); rmiMethodDeleteBreak.result(null); assertEquals(Map.ofEntries( - Map.entry("breakpoint", loc.getSpecification().getObject())), args); + Map.entry("breakpoint", expectedLoc.getSpecification().getObject())), args); } } diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/control/DebuggerControlServiceTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/control/DebuggerControlServiceTest.java index 235896eb6b..dbc5c55014 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/control/DebuggerControlServiceTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/control/DebuggerControlServiceTest.java @@ -40,9 +40,8 @@ import ghidra.program.model.mem.MemoryAccessException; import ghidra.trace.model.Lifespan; import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.memory.TraceMemoryFlag; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule; @@ -173,7 +172,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte createAndOpenTrace(); controlService.setCurrentMode(tb.trace, ControlMode.RW_EMULATOR); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { // NB. TraceManager should automatically activate the first thread thread = tb.createObjectsProcessAndThreads(); @@ -203,7 +202,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte createAndOpenTrace(); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { // NB. TraceManager should automatically activate the first thread thread = tb.createObjectsProcessAndThreads(); @@ -243,7 +242,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte createAndOpenTrace(); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { // NB. TraceManager should automatically activate the first thread thread = tb.createObjectsProcessAndThreads(); @@ -286,7 +285,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte try (Transaction tx = tb.startTransaction()) { // NB. TraceManager should automatically activate the first thread - TraceObjectThread thread = tb.createObjectsProcessAndThreads(); + TraceThread thread = tb.createObjectsProcessAndThreads(); tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), getPlatform(), 1); } activateTrace(); @@ -314,7 +313,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte createAndOpenTrace(); controlService.setCurrentMode(tb.trace, ControlMode.RW_EMULATOR); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { // NB. TraceManager should automatically activate the first thread thread = tb.createObjectsProcessAndThreads(); @@ -385,7 +384,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte createAndOpenTrace(); controlService.setCurrentMode(tb.trace, ControlMode.RW_TRACE); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { // NB. TraceManager should automatically activate the first thread thread = tb.createObjectsProcessAndThreads(); @@ -417,8 +416,8 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte try (Transaction tx = tb.startTransaction()) { tb.createObjectsProcessAndThreads(); - TraceObjectThread thread = - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + TraceThread thread = + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), getPlatform(), 1); tb.trace.getMemoryManager() .addRegion("Processes[1].Memory[exe:.text]", Lifespan.nowOn(0), @@ -436,7 +435,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte TraceObject process = tb.obj("Processes[1]"); TraceThread thread = - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); activateTrace(); // platform traceManager.activateThread(thread); waitForSwing(); @@ -456,7 +455,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte addTarget(); TraceThread thread = - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); activateTrace(); // platform traceManager.activateThread(thread); waitForSwing(); @@ -466,7 +465,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte assertTrue(editor.isRegisterEditable(r0)); CompletableFuture future = editor.setRegister(rv1234); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r0", 1234); waitOn(future); } @@ -477,7 +476,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte addTarget(); TraceThread thread = - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); activateTrace(); // platform traceManager.activateThread(thread); waitForSwing(); @@ -487,14 +486,14 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte assertTrue(editor.isRegisterEditable(r0)); CompletableFuture future = editor.setRegister(rv1234); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r0", 1234); waitOn(future); assertTrue(editor.isRegisterEditable(r0h)); CompletableFuture future2 = editor.setRegister(rvHigh1234); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r0h", 1234); waitOn(future2); } @@ -505,7 +504,7 @@ public class DebuggerControlServiceTest extends AbstractGhidraHeadedDebuggerInte Target target = addTarget(); TraceThread thread = - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); activateTrace(); // platform traceManager.activateThread(thread); waitForSwing(); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/modules/DynamicStaticSynchronizationPluginTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/modules/DynamicStaticSynchronizationPluginTest.java index 49254531bb..80de5cc3c8 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/modules/DynamicStaticSynchronizationPluginTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/modules/DynamicStaticSynchronizationPluginTest.java @@ -46,6 +46,7 @@ import ghidra.program.model.lang.Register; import ghidra.program.model.lang.RegisterValue; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.model.*; import ghidra.trace.model.memory.TraceMemoryFlag; @@ -99,8 +100,10 @@ public class DynamicStaticSynchronizationPluginTest monitor, false); } try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceLocation from = new DefaultTraceLocation(tb.trace, null, Lifespan.nowOn(0), tb.addr(0x00400000)); @@ -158,15 +161,22 @@ public class DynamicStaticSynchronizationPluginTest } TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(), + "Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceLocation from = new DefaultTraceLocation(tb.trace, null, Lifespan.nowOn(0), tb.addr(0x00400000)); ProgramLocation to = new ProgramLocation(program, ss.getAddress(0x00600000)); DebuggerStaticMappingUtils.addMapping(from, to, 0x8000, false); - thread = tb.getOrAddThread("Thread1", 0); + thread = tb.getOrAddThread("Threads[1]", 0); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); Register pc = tb.trace.getBaseLanguage().getProgramCounter(); TraceMemorySpace regs = memory.getMemoryRegisterSpace(thread, true); regs.setValue(1, new RegisterValue(pc, BigInteger.valueOf(0x00401234))); @@ -344,8 +354,10 @@ public class DynamicStaticSynchronizationPluginTest monitor, false); } try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); DBTraceMemoryManager memory = tb.trace.getMemoryManager(); - memory.addRegion("exe:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0040ffff), + memory.addRegion("Memory[exe:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); TraceLocation from = new DefaultTraceLocation(tb.trace, null, Lifespan.nowOn(0), tb.addr(0x00400000)); @@ -432,13 +444,17 @@ public class DynamicStaticSynchronizationPluginTest createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.trace.getMemoryManager() - .addRegion("bash:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0041ffff), + .addRegion("Memory[bash:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0041ffff), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); TraceModule bin = tb.trace.getModuleManager() - .addLoadedModule("/bin/bash", "/bin/bash", tb.range(0x00400000, 0x0041ffff), 0); - bin.addSection(0, "bash[.text]", tb.range(0x00400000, 0x0040ffff)); + .addLoadedModule("Modules[/bin/bash]", "/bin/bash", + tb.range(0x00400000, 0x0041ffff), 0); + bin.addSection(0, "Modules[/bin/bash].Sections[.text]", + tb.range(0x00400000, 0x0040ffff)); } waitForDomainObject(tb.trace); traceManager.activateTrace(tb.trace); @@ -464,12 +480,15 @@ public class DynamicStaticSynchronizationPluginTest createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject("Target"); tb.trace.getMemoryManager() - .addRegion("bash:.text", Lifespan.nowOn(0), tb.range(0x00400000, 0x0041ffff), + .addRegion("Memory[bash:.text]", Lifespan.nowOn(0), + tb.range(0x00400000, 0x0041ffff), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); tb.trace.getModuleManager() - .addLoadedModule("/bin/bash", "/bin/bash", tb.range(0x00400000, 0x0041ffff), 0); + .addLoadedModule("Modules[/bin/bash]", "/bin/bash", + tb.range(0x00400000, 0x0041ffff), 0); } waitForDomainObject(tb.trace); traceManager.activateTrace(tb.trace); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java index e15eaf8e90..59f852ea0b 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java @@ -15,6 +15,7 @@ */ package ghidra.app.plugin.core.debug.service.tracemgr; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; import java.util.*; @@ -34,16 +35,11 @@ import ghidra.debug.api.target.Target; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.model.DomainFile; import ghidra.trace.database.target.DBTraceObjectManager; -import ghidra.trace.database.target.DBTraceObjectManagerTest; import ghidra.trace.model.Lifespan; import ghidra.trace.model.Trace; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.target.iface.TraceObjectEventScope; +import ghidra.trace.model.target.iface.TraceEventScope; import ghidra.trace.model.target.path.KeyPath; -import ghidra.trace.model.target.schema.SchemaContext; -import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; -import ghidra.trace.model.target.schema.XmlSchemaContext; -import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.trace.model.time.schedule.TraceSchedule.ScheduleForm; @@ -136,7 +132,8 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge TraceThread thread; try (Transaction tx = tb.startTransaction()) { - thread = tb.getOrAddThread("Thread 1", 0); + tb.createRootObject("Target"); + thread = tb.getOrAddThread("Threads[1]", 0); } waitForDomainObject(tb.trace); @@ -236,18 +233,16 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge assertEquals(null, traceManager.getCurrentObject()); - SchemaContext ctx = XmlSchemaContext.deserialize(DBTraceObjectManagerTest.XML_CTX); TraceObject objThread0; try (Transaction tx = tb.startTransaction()) { DBTraceObjectManager objectManager = tb.trace.getObjectManager(); - objectManager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild(); - objThread0 = - objectManager.createObject(KeyPath.parse("Targets[0].Threads[0]")); + tb.createRootObject(); + objThread0 = objectManager.createObject(KeyPath.parse("Targets[0].Threads[0]")); } // Manager listens for the root-created event to activate it. Wait for it to clear. waitForDomainObject(tb.trace); TraceThread thread = - Objects.requireNonNull(objThread0.queryInterface(TraceObjectThread.class)); + Objects.requireNonNull(objThread0.queryInterface(TraceThread.class)); traceManager.activateObject(objThread0); waitForSwing(); @@ -359,7 +354,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge public void testFollowPresent() throws Throwable { createRmiConnection(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); thread = tb.createObjectsProcessAndThreads(); @@ -407,7 +402,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge createRmiConnection(); addActivateMethods(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); thread = tb.createObjectsProcessAndThreads(); @@ -456,7 +451,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge createRmiConnection(); addActivateMethods(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); thread = tb.createObjectsProcessAndThreads(); @@ -502,7 +497,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge createRmiConnection(); addActivateWithTimeMethods(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); thread = tb.createObjectsProcessAndThreads(); @@ -530,7 +525,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge createRmiConnection(); addActivateMethods(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); thread = tb.createObjectsProcessAndThreads(); @@ -558,13 +553,13 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge assertNull(target.getSupportedTimeForm(thread, 0)); try (Transaction tx = tb.startTransaction()) { - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_ONLY.name()); } assertEquals(ScheduleForm.SNAP_ONLY, target.getSupportedTimeForm(thread, 0)); try (Transaction tx = tb.startTransaction()) { - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_ANY_STEPS_OPS.name()); } // Constrained by method parameter @@ -588,25 +583,25 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge assertNull(target.getSupportedTimeForm(thread, 0)); try (Transaction tx = tb.startTransaction()) { - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_ONLY.name()); } assertEquals(ScheduleForm.SNAP_ONLY, target.getSupportedTimeForm(thread, 0)); try (Transaction tx = tb.startTransaction()) { - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_EVT_STEPS.name()); } assertEquals(ScheduleForm.SNAP_EVT_STEPS, target.getSupportedTimeForm(thread, 0)); try (Transaction tx = tb.startTransaction()) { - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_ANY_STEPS.name()); } assertEquals(ScheduleForm.SNAP_ANY_STEPS, target.getSupportedTimeForm(thread, 0)); try (Transaction tx = tb.startTransaction()) { - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_ANY_STEPS_OPS.name()); } assertEquals(ScheduleForm.SNAP_ANY_STEPS_OPS, target.getSupportedTimeForm(thread, 0)); @@ -617,7 +612,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge createRmiConnection(); addActivateMethods(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); thread = tb.createObjectsProcessAndThreads(); @@ -652,12 +647,12 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge createRmiConnection(); addActivateWithTimeMethods(); createAndOpenTrace(); - TraceObjectThread thread; + TraceThread thread; TraceObject root; try (Transaction tx = tb.startTransaction()) { root = tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION).getChild(); thread = tb.createObjectsProcessAndThreads(); - root.setAttribute(Lifespan.nowOn(0), TraceObjectEventScope.KEY_TIME_SUPPORT, + root.setAttribute(Lifespan.nowOn(0), TraceEventScope.KEY_TIME_SUPPORT, ScheduleForm.SNAP_EVT_STEPS.name()); tb.trace.getTimeManager() .getSnapshot(0, true) diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java index 84daa0fb15..9e53b6ad3e 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java @@ -40,12 +40,13 @@ import ghidra.app.services.*; import ghidra.debug.api.control.ControlMode; import ghidra.program.model.address.Address; import ghidra.program.model.lang.*; +import ghidra.trace.database.ToyDBTraceBuilder.ToySchemaBuilder; import ghidra.trace.database.memory.DBTraceMemoryManager; import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.model.Lifespan; import ghidra.trace.model.breakpoint.TraceBreakpointKind; import ghidra.trace.model.memory.TraceMemoryFlag; -import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.thread.TraceThread; public abstract class AbstractFlatDebuggerAPITest @@ -79,6 +80,13 @@ public abstract class AbstractFlatDebuggerAPITest api.getState().setCurrentProgram(program); } + protected SchemaContext buildContext() { + return new ToySchemaBuilder() + .noRegisterGroups() + .useRegistersPerFrame() + .build(); + } + protected TraceThread createTraceWithThreadAndStack(boolean open) throws Throwable { if (open) { createAndOpenTrace(); @@ -88,9 +96,9 @@ public abstract class AbstractFlatDebuggerAPITest } TraceThread thread; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); thread = tb.getOrAddThread("Threads[0]", 0); - TraceStack stack = tb.trace.getStackManager().getStack(thread, 0, true); - stack.setDepth(0, 3, true); + tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 3); } waitForSwing(); return thread; @@ -100,6 +108,7 @@ public abstract class AbstractFlatDebuggerAPITest createAndOpenTrace(); try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); mm.createRegion("Memory[bin.text]", 0, tb.range(0x00400000, 0x0040ffff), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); @@ -128,6 +137,7 @@ public abstract class AbstractFlatDebuggerAPITest CompletableFuture changesSettled; try (Transaction tx = tb.startTransaction()) { + tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() .createRegion("Memory[bin.text]", 0, tb.range(0x00400000, 0x00400fff), Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java index a0397e6754..3cb1c63c9a 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java @@ -100,6 +100,7 @@ public class DeadFlatDebuggerAPITest extends AbstractFlatDebuggerAPITest { @@ -74,7 +73,7 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest step, Supplier method) throws Throwable { createTarget(); - TraceObjectThread thread = - tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + TraceThread thread = tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); traceManager.activateThread(thread); waitForSwing(); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/pcode/exec/TraceRmiPcodeExecTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/pcode/exec/TraceRmiPcodeExecTest.java index 372768610c..187a712a0d 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/pcode/exec/TraceRmiPcodeExecTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/pcode/exec/TraceRmiPcodeExecTest.java @@ -31,16 +31,16 @@ import ghidra.pcode.exec.PcodeArithmetic.Purpose; import ghidra.program.model.lang.RegisterValue; import ghidra.trace.model.Lifespan; import ghidra.trace.model.memory.TraceMemorySpace; -import ghidra.trace.model.stack.TraceObjectStackFrame; +import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.model.target.TraceObject; -import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.schedule.TraceSchedule; public class TraceRmiPcodeExecTest extends AbstractGhidraHeadedDebuggerIntegrationTest { Target target; - TraceObjectThread thread; + TraceThread thread; SleighLanguage language; protected void setupExecTest() throws Throwable { @@ -50,7 +50,7 @@ public class TraceRmiPcodeExecTest extends AbstractGhidraHeadedDebuggerIntegrati try (Transaction tx = tb.startTransaction()) { tb.trace.getObjectManager().createRootObject(SCHEMA_SESSION); tb.createObjectsProcessAndThreads(); - thread = tb.obj("Processes[1].Threads[1]").queryInterface(TraceObjectThread.class); + thread = tb.obj("Processes[1].Threads[1]").queryInterface(TraceThread.class); tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 1); } target = rmiCx.publishTarget(tool, tb.trace); @@ -149,7 +149,7 @@ public class TraceRmiPcodeExecTest extends AbstractGhidraHeadedDebuggerIntegrati }); handleWriteRegInvocation( - tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceObjectStackFrame.class), + tb.obj("Processes[1].Threads[1].Stack[0]").queryInterface(TraceStackFrame.class), "r2", 11); waitOn(futResult);