GP-5499: Add 'Time' column to Time table.

This commit is contained in:
Dan
2025-03-26 19:03:51 +00:00
parent f2e8afff9c
commit 9016ed28f1
12 changed files with 86 additions and 55 deletions

View File

@@ -13,32 +13,28 @@
<BODY lang="EN-US">
<H1><A name="plugin"></A>Debugger: Time Overview</H1>
<P>Patterned on the Program Overview, this plugin provides a pair of sidebars for the
Dynamic Listing that indicate the history of the current trace, similar to those in the
<A href="help/topics/DebuggerTimePlugin/DebuggerTimePlugin.html">Time</A>
and <A href="help/topics/DebuggerMemviewPlugin/DebuggerMemviewPlugin.html">Memview</A> plugins.
The Trace Overview bar gives a compressed view of various events
(thread creation/destruction, module loads/unloads, et cetera). Events are added in time
snap order <em>without</em> spaces between consecutive events, as in the Memview display. The Trace
Selection sidebar allows the user to click &amp; drag over a section of either sidebar and zooms
in on that time span. In the zoomed version, events are in snap order <em>with</em> intervening space
to indicate the actual time delays (although these are dictated, in part, by the numbering
schema for events).
</P>
<P>Patterned on the Program Overview, this plugin provides a pair of sidebars for the Dynamic
Listing that indicate the history of the current trace, similar to those in the <A href=
"help/topics/DebuggerTimePlugin/DebuggerTimePlugin.html">Time</A> and <A href=
"help/topics/DebuggerMemviewPlugin/DebuggerMemviewPlugin.html">Memview</A> plugins. The Trace
Overview bar gives a compressed view of various events (thread creation/destruction, module
loads/unloads, et cetera). Events are added in time snap order <EM>without</EM> spaces between
consecutive events, as in the Memview display. The Trace Selection sidebar allows the user to
click &amp; drag over a section of either sidebar and zooms in on that time span. In the zoomed
version, events are in snap order <EM>with</EM> intervening space to indicate the actual time
delays (although these are dictated, in part, by the numbering schema for events).</P>
<H2>Navigation</H2>
<H3><A name="zoom"></A><IMG alt="" src="icon.widget.imagepanel.zoom.in">Zoom</H3>
<P>Clicking and dragging over a region of the Trace Overview causes that
span to be displayed uncompressed in the Trace Selection. The same action can also
be applied to the Trace Selection itself, resulting in a more detailed zoom.</P>
<H3><A name="move"></A><IMG alt="" src="icon.widget.imagepanel.zoom.in">Move</H3>
<P>Shift click &amp; drag on the Trace Selection allows the user to move forward and
backward in the view without rescaling.
</P>
<P>Clicking and dragging over a region of the Trace Overview causes that span to be displayed
uncompressed in the Trace Selection. The same action can also be applied to the Trace Selection
itself, resulting in a more detailed zoom.</P>
<H3><A name="move"></A><IMG alt="" src="icon.widget.imagepanel.zoom.in">Move</H3>
<P>Shift click &amp; drag on the Trace Selection allows the user to move forward and backward
in the view without rescaling.</P>
</BODY>
</HTML>

View File

@@ -25,14 +25,18 @@
snapshot <EM>activates</EM> the selected point in time, i.e., the entire Debugger UI will
navigate to the selected snapshot. <B>NOTE:</B> Navigating through time is not permitted while
in <B>Control Target</B> <A href=
"help/topics/DebuggerControlPlugin/DebuggerControlPlugin.html#control_mode">mode</A>.</P>
"help/topics/DebuggerControlPlugin/DebuggerControlPlugin.html#control_mode">mode</A>, unless
the back end supports time travel.</P>
<H2>Table Columns</H2>
<P>The table has the following columns:</P>
<UL>
<LI>Snap - the 0-up index of the snapshot (event) recorded.</LI>
<LI>Snap - the 0-up index of the snapshot (event) recorded. <EM>(hidden by default)</EM></LI>
<LI>Time - the "time" coordinate for the snapshot. This is the same as the Snap column for
most snapshots. For <EM>scratch</EM> snapshots, this is the same as the Schedule column.</LI>
<LI>Timestamp - the "wall-clock" time of the event. If the debugger doesn't give an event
time, or the snapshot does not correspond to an event, then it is the snapshot creation
@@ -44,7 +48,8 @@
<LI>Schedule - if applicable, a source snap and the stepping schedule which produces this
snapshot. This always applies to <EM>scratch</EM> snapshots produced by emulation, but may
(rarely) apply to recorded events if the stepping schedule between them is somehow known. See
the <A href="#goto_time">Go To Time</A> action for a description of the notation.</LI>
the <A href="#goto_time">Go To Time</A> action for a description of the notation. <EM>(hidden
by default)</EM></LI>
<LI>Description - a user-modifiable description of the snapshot or event. This defaults to
the debugger's description of the event.</LI>
@@ -91,11 +96,10 @@
<H3><A name="hide_scratch"></A>Hide Scratch</H3>
<P>This toggle action is always available in the drop-down actions of the Time window. It is
enabled by default. The emulation service, which enables trace extrapolation and interpolation,
writes emulated state into the trace's <EM>scratch space</EM>, which comprises all negative
snaps. When this toggle is enabled, those snapshots are hidden. They can be displayed by
disabling this toggle. Note that navigating into scratch space may cause temporary undefined
behavior in some windows, and may prevent interaction with the target.</P>
<P>This toggle action is always available in the toolbar of the Time window. It is disabled by
default. The emulation service, which enables trace extrapolation and interpolation, writes
emulated state into the trace's <EM>scratch space</EM>, which comprises all negative snaps.
Some time-travel capable back ends may also write into scratch space. When this toggle is
enabled, those scratch snapshots are hidden.</P>
</BODY>
</HTML>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1726,8 +1726,7 @@ public interface DebuggerResources {
String ownerName = owner.getName();
return new ToggleActionBuilder(NAME, ownerName)
.description(DESCRIPTION)
.menuGroup(GROUP_GENERAL)
.menuPath(NAME)
.toolBarIcon(ICON_FILTER)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}

View File

@@ -35,6 +35,7 @@ import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.time.TraceSnapshot;
import ghidra.trace.model.time.TraceTimeManager;
import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.trace.util.TraceEvents;
import ghidra.util.table.GhidraTableFilterPanel;
import ghidra.util.table.column.AbstractGColumnRenderer;
@@ -43,28 +44,32 @@ public class DebuggerSnapshotTablePanel extends JPanel {
protected enum SnapshotTableColumns
implements EnumeratedTableColumn<SnapshotTableColumns, SnapshotRow> {
SNAP("Snap", Long.class, SnapshotRow::getSnap),
TIMESTAMP("Timestamp", String.class, SnapshotRow::getTimeStamp), // TODO: Use Date type here
EVENT_THREAD("Event Thread", String.class, SnapshotRow::getEventThreadName),
SCHEDULE("Schedule", String.class, SnapshotRow::getSchedule),
DESCRIPTION("Description", String.class, SnapshotRow::getDescription, SnapshotRow::setDescription);
SNAP("Snap", Long.class, SnapshotRow::getSnap, false),
TIME("Time", TraceSchedule.class, SnapshotRow::getTime, true),
TIMESTAMP("Timestamp", String.class, SnapshotRow::getTimeStamp, true), // TODO: Use Date type here
EVENT_THREAD("Event Thread", String.class, SnapshotRow::getEventThreadName, true),
SCHEDULE("Schedule", String.class, SnapshotRow::getSchedule, false),
DESCRIPTION("Description", String.class, SnapshotRow::getDescription, SnapshotRow::setDescription, true);
private final String header;
private final Function<SnapshotRow, ?> getter;
private final BiConsumer<SnapshotRow, Object> setter;
private final Class<?> cls;
private final boolean visible;
<T> SnapshotTableColumns(String header, Class<T> cls, Function<SnapshotRow, T> getter) {
this(header, cls, getter, null);
<T> SnapshotTableColumns(String header, Class<T> cls, Function<SnapshotRow, T> getter,
boolean visible) {
this(header, cls, getter, null, visible);
}
@SuppressWarnings("unchecked")
<T> SnapshotTableColumns(String header, Class<T> cls, Function<SnapshotRow, T> getter,
BiConsumer<SnapshotRow, T> setter) {
BiConsumer<SnapshotRow, T> setter, boolean visible) {
this.header = header;
this.cls = cls;
this.getter = getter;
this.setter = (BiConsumer<SnapshotRow, Object>) setter;
this.visible = visible;
}
@Override
@@ -87,12 +92,29 @@ public class DebuggerSnapshotTablePanel extends JPanel {
return setter != null;
}
@Override
public boolean isVisible() {
return visible;
}
@Override
public void setValueOf(SnapshotRow row, Object value) {
setter.accept(row, value);
}
}
protected static class SnapshotTableModel
extends DefaultEnumeratedColumnTableModel<SnapshotTableColumns, SnapshotRow> {
public SnapshotTableModel(PluginTool tool) {
super(tool, "Snapshots", SnapshotTableColumns.class);
}
@Override
public List<SnapshotTableColumns> defaultSortOrder() {
return List.of(SnapshotTableColumns.TIME);
}
}
private class SnapshotListener extends TraceDomainObjectListener {
public SnapshotListener() {
listenForUntyped(DomainObjectEvent.RESTORED, e -> objectRestored());
@@ -153,7 +175,7 @@ public class DebuggerSnapshotTablePanel extends JPanel {
}
};
protected final EnumeratedColumnTableModel<SnapshotRow> snapshotTableModel;
protected final SnapshotTableModel snapshotTableModel;
protected final GTable snapshotTable;
protected final GhidraTableFilterPanel<SnapshotRow> snapshotFilterPanel;
protected boolean hideScratch = true;
@@ -165,8 +187,7 @@ public class DebuggerSnapshotTablePanel extends JPanel {
public DebuggerSnapshotTablePanel(PluginTool tool) {
super(new BorderLayout());
snapshotTableModel =
new DefaultEnumeratedColumnTableModel<>(tool, "Snapshots", SnapshotTableColumns.class);
snapshotTableModel = new SnapshotTableModel(tool);
snapshotTable = new GTable(snapshotTableModel);
snapshotTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
add(new JScrollPane(snapshotTable));
@@ -178,9 +199,12 @@ public class DebuggerSnapshotTablePanel extends JPanel {
TableColumn snapCol = columnModel.getColumn(SnapshotTableColumns.SNAP.ordinal());
snapCol.setPreferredWidth(40);
snapCol.setCellRenderer(styleCurrentRenderer);
TableColumn timeCol = columnModel.getColumn(SnapshotTableColumns.TIMESTAMP.ordinal());
timeCol.setPreferredWidth(200);
TableColumn timeCol = columnModel.getColumn(SnapshotTableColumns.TIME.ordinal());
timeCol.setPreferredWidth(40);
timeCol.setCellRenderer(styleCurrentRenderer);
TableColumn timeStampCol = columnModel.getColumn(SnapshotTableColumns.TIMESTAMP.ordinal());
timeStampCol.setPreferredWidth(200);
timeStampCol.setCellRenderer(styleCurrentRenderer);
TableColumn etCol = columnModel.getColumn(SnapshotTableColumns.EVENT_THREAD.ordinal());
etCol.setPreferredWidth(40);
etCol.setCellRenderer(styleCurrentRenderer);

View File

@@ -82,7 +82,7 @@ public class DebuggerTimeProvider extends ComponentProviderAdapter {
private DebuggerSnapActionContext myActionContext;
@AutoConfigStateField
/*testing*/ boolean hideScratch = true;
/*testing*/ boolean hideScratch = false;
public DebuggerTimeProvider(DebuggerTimePlugin plugin) {
super(plugin.getTool(), TITLE_PROVIDER_TIME, plugin.getName());

View File

@@ -21,6 +21,7 @@ import db.Transaction;
import ghidra.trace.model.Trace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.model.time.TraceSnapshot;
import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.DateUtils;
public class SnapshotRow {
@@ -38,6 +39,14 @@ public class SnapshotRow {
return snapshot;
}
public TraceSchedule getTime() {
long snap = snapshot.getKey();
if (snap < 0) {
return snapshot.getSchedule();
}
return TraceSchedule.snap(snap);
}
public long getSnap() {
return snapshot.getKey();
}

View File

@@ -663,6 +663,7 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
DebuggerTimeSelectionDialog timeDialog =
waitForDialogComponent(DebuggerTimeSelectionDialog.class);
timeDialog.setScheduleText(TraceSchedule.snap(snapA).toString());
timeDialog.getComponent().requestFocus();
captureDialog(timeDialog);
}

View File

@@ -230,16 +230,15 @@ alt="Time window" />
general, every pause generates a snapshot. By default, the most recent
snapshot is at the bottom. The columns are:</p>
<ul>
<li>The <strong>Snap</strong> column numbers each snapshot. Other
windows that indicate life spans refer to these numbers.</li>
<li>The <strong>Time</strong> column numbers each snapshot. Other
windows that indicate life spans refer to these numbers. If emulating
(covered later in this course), this column may display the
schedule.</li>
<li>The <strong>Timestamp</strong> column gives the time when the
snapshot was created, i.e., the time when the event occurred.</li>
<li>The <strong>Event Thread</strong> column indicates which thread
caused the target to break. This only applies to snapshots that were
created because of an event, which is most.</li>
<li>The <strong>Schedule</strong> column describes the snapshot in
relation to another. It typically only applies to emulator / scratch
snapshots, which are covered later in this course.</li>
<li>The <strong>Description</strong> column describes the event that
generated the snapshot. This can be edited in the table, or by pressing
<strong><code>CTRL</code>-<code>SHIFT</code>-<code>N</code></strong> to

View File

@@ -122,13 +122,12 @@ In general, every pause generates a snapshot.
By default, the most recent snapshot is at the bottom.
The columns are:
* The **Snap** column numbers each snapshot.
* The **Time** column numbers each snapshot.
Other windows that indicate life spans refer to these numbers.
If emulating (covered later in this course), this column may display the schedule.
* The **Timestamp** column gives the time when the snapshot was created, i.e., the time when the event occurred.
* The **Event Thread** column indicates which thread caused the target to break.
This only applies to snapshots that were created because of an event, which is most.
* The **Schedule** column describes the snapshot in relation to another.
It typically only applies to emulator / scratch snapshots, which are covered later in this course.
* The **Description** column describes the event that generated the snapshot.
This can be edited in the table, or by pressing **`CTRL`-`SHIFT`-`N`** to mark interesting snapshots.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 25 KiB