Merge remote-tracking branch 'origin/GP-6026_Dan_addBreakLocExpressionColumn--SQUASHED' into patch

This commit is contained in:
Ryan Kurtz
2026-01-16 13:17:20 -05:00
13 changed files with 64 additions and 31 deletions
@@ -149,8 +149,11 @@
<LI>Threads - (hidden by default) if the breakpoint applies to a limited set of threads,
gives the list of threads.</LI>
<LI>Comment - gives a user comment &mdash; the specification's expression by default. This
field is user modifiable.</LI>
<LI>Comment - gives a user comment. This field is user modifiable.</LI>
<LI>Expression - the expression given by the user when placing the breakpoint. This ought to
echo back what was typed into the CLI, if applicable. When placed via a Listing, this often
refers to the dynamic address.</LI>
<LI>Sleigh - indicates whether or not the location has a customized Sleigh configuration.
This is only relevant for emulation.</LI>
@@ -319,7 +322,7 @@ emu_exec_decoded();
Alternatively, suppose the example instruction is <CODE>JZ 0x00401234</CODE>. Then, the
injection can jump straight to the target:
<PRE>
goto [0x00401234];
goto 0x00401234;
</PRE>
</LI>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

@@ -25,6 +25,7 @@ import ghidra.pcode.exec.SleighUtils;
import ghidra.program.model.address.Address;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
import ghidra.trace.model.breakpoint.TraceBreakpointSpec;
public class BreakpointLocationRow {
private final DebuggerBreakpointsProvider provider;
@@ -113,6 +114,15 @@ public class BreakpointLocationRow {
}
}
public String getExpression() {
TraceBreakpointSpec spec = loc.getSpecification();
if (spec == null) {
// Shouldn't happen, but may in the interim
return "";
}
return spec.getExpression(getSnap());
}
public boolean hasSleigh() {
return !SleighUtils.UNCONDITIONAL_BREAK.equals(loc.getEmuSleigh(getSnap()));
}
@@ -70,8 +70,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
protected enum LogicalBreakpointTableColumns
implements EnumeratedTableColumn<LogicalBreakpointTableColumns, LogicalBreakpointRow> {
STATE("State", State.class, LogicalBreakpointRow::getState, LogicalBreakpointRow::setState, true),
NAME("Name", String.class, LogicalBreakpointRow::getName, LogicalBreakpointRow::setName, //
STATE("State", State.class, LogicalBreakpointRow::getState, LogicalBreakpointRow::setState,
true),
NAME("Name", String.class, LogicalBreakpointRow::getName, LogicalBreakpointRow::setName,
LogicalBreakpointRow::isNamable, true),
ADDRESS("Address", Address.class, LogicalBreakpointRow::getAddress, true),
IMAGE("Image", String.class, LogicalBreakpointRow::getImageName, true),
@@ -142,8 +143,8 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
}
}
protected static class LogicalBreakpointTableModel extends RowWrappedEnumeratedColumnTableModel< //
LogicalBreakpointTableColumns, LogicalBreakpoint, LogicalBreakpointRow, LogicalBreakpoint> {
protected static class LogicalBreakpointTableModel extends RowWrappedEnumeratedColumnTableModel<
LogicalBreakpointTableColumns, LogicalBreakpoint, LogicalBreakpointRow, LogicalBreakpoint> {
public LogicalBreakpointTableModel(DebuggerBreakpointsProvider provider) {
super(provider.getTool(), "Breakpoints", LogicalBreakpointTableColumns.class, lb -> lb,
@@ -160,12 +161,16 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
protected enum BreakpointLocationTableColumns
implements EnumeratedTableColumn<BreakpointLocationTableColumns, BreakpointLocationRow> {
STATE("State", State.class, BreakpointLocationRow::getState, BreakpointLocationRow::setState, true, true),
NAME("Name", String.class, BreakpointLocationRow::getName, BreakpointLocationRow::setName, true, true),
STATE("State", State.class, BreakpointLocationRow::getState,
BreakpointLocationRow::setState, true, true),
NAME("Name", String.class, BreakpointLocationRow::getName, BreakpointLocationRow::setName,
true, true),
ADDRESS("Address", Address.class, BreakpointLocationRow::getAddress, true, true),
TRACE("Trace", String.class, BreakpointLocationRow::getTraceName, true, true),
THREADS("Threads", String.class, BreakpointLocationRow::getThreads, true, false),
COMMENT("Comment", String.class, BreakpointLocationRow::getComment, BreakpointLocationRow::setComment, true, true),
COMMENT("Comment", String.class, BreakpointLocationRow::getComment,
BreakpointLocationRow::setComment, true, true),
EXPRESSION("Expression", String.class, BreakpointLocationRow::getExpression, true, true),
SLEIGH("Sleigh", Boolean.class, BreakpointLocationRow::hasSleigh, true, true);
private final String header;
@@ -229,9 +234,8 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
}
protected static class BreakpointLocationTableModel
extends RowWrappedEnumeratedColumnTableModel< //
BreakpointLocationTableColumns, ObjectKey, BreakpointLocationRow, //
TraceBreakpointLocation> {
extends RowWrappedEnumeratedColumnTableModel<BreakpointLocationTableColumns, ObjectKey,
BreakpointLocationRow, TraceBreakpointLocation> {
public BreakpointLocationTableModel(DebuggerBreakpointsProvider provider) {
super(provider.getTool(), "Locations", BreakpointLocationTableColumns.class,
@@ -44,7 +44,7 @@ import ghidra.test.ToyProgramBuilder;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.database.breakpoint.DBTraceBreakpointManager;
import ghidra.trace.model.*;
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
import ghidra.trace.model.breakpoint.*;
import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
import help.screenshot.GhidraScreenShotGenerator;
@@ -151,11 +151,20 @@ public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenera
long snap = tb1.trace.getTimeManager().createSnapshot("First").getKey();
DBTraceBreakpointManager bm = tb1.trace.getBreakpointManager();
bm.placeBreakpoint("Breakpoints[1]", snap, tb1.addr(0x00401234), List.of(),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "ram:00401234");
bm.placeBreakpoint("Breakpoints[2]", snap, tb1.range(0x00604321, 0x00604324),
List.of(),
Set.of(TraceBreakpointKind.WRITE), true, "ram:00604321");
TraceBreakpointLocation locCx =
bm.placeBreakpoint("Breakpoints[1]", snap, tb1.addr(0x00401234), List.of(),
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "");
locCx.getSpecification()
.getObject()
.setAttribute(Lifespan.nowOn(snap), TraceBreakpointSpec.KEY_EXPRESSION,
"*0x00401234");
TraceBreakpointLocation locWr =
bm.placeBreakpoint("Breakpoints[2]", snap, tb1.range(0x00604321, 0x00604324),
List.of(), Set.of(TraceBreakpointKind.WRITE), true, "");
locWr.getSpecification()
.getObject()
.setAttribute(Lifespan.nowOn(snap), TraceBreakpointSpec.KEY_EXPRESSION,
"version");
}
try (Transaction tx = tb2.startTransaction()) {
@@ -164,8 +173,13 @@ public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenera
long snap = tb2.trace.getTimeManager().createSnapshot("First").getKey();
DBTraceBreakpointManager bm = tb2.trace.getBreakpointManager();
bm.placeBreakpoint("Breakpoints[1]", snap, tb2.addr(0x7fac1234), List.of(),
Set.of(TraceBreakpointKind.SW_EXECUTE), false, "ram:7fac1234");
TraceBreakpointLocation locCx =
bm.placeBreakpoint("Breakpoints[1]", snap, tb2.addr(0x7fac1234), List.of(),
Set.of(TraceBreakpointKind.SW_EXECUTE), false, "");
locCx.getSpecification()
.getObject()
.setAttribute(Lifespan.nowOn(snap), TraceBreakpointSpec.KEY_EXPRESSION,
"*0x7fac1234");
}
programManager.openProgram(program);
@@ -260,6 +260,7 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
@Test
public void testGettingStarted_ToolWSpecimen() {
tool.getActiveWindow().requestFocus();
captureToolWindow(1920, 1080);
}
@@ -309,7 +310,7 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
public void testGettingStarted_DisassemblyAfterLaunch() throws Throwable {
launchProgramInGdb();
Thread.sleep(7000);
tool.getActiveWindow().requestFocus();
captureToolWindow(1920, 1080);
}
@@ -382,9 +383,9 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
Program prog = null;
long snap = flatDbg.getCurrentSnap();
try (LoadResults<Program> result = ProgramLoader.builder()
.source(new File(module.getName(snap)))
.project(env.getProject())
.monitor(monitor)
.source(new File(module.getName(snap)))
.project(env.getProject())
.monitor(monitor)
.load()) {
result.save(monitor);
@@ -442,6 +443,7 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
// Just to be sure.
goTo(tool, progLibC, flatDbg.translateDynamicToStatic(dynAddr));
tool.getActiveWindow().requestFocus();
captureToolWindow(1920, 1080);
}
@@ -261,9 +261,9 @@ back-end.</li>
<li>The <strong>Trace</strong> column indicates which target contains
the location. The text here should match one of the tabs from the
Dynamic Listing panel.</li>
<li>The <strong>Comment</strong> column is a user-defined comment. Its
default value is the specification that generated it, e.g.,
<code>srand</code>.</li>
<li>The <strong>Comment</strong> column is a user-defined comment.</li>
<li>The <strong>Expression</strong> column is the expression given when
specifying the breakpoint, e.g., <code>srand</code>.</li>
</ul>
</section>
<section id="toggling-the-breakpoints" class="level3">
@@ -422,7 +422,7 @@ course.</p>
</section>
<section id="exercise-diagram-the-mines" class="level3">
<h3>Exercise: Diagram the Mines</h3>
<p>You goal is to capture the location of all the mines. You will
<p>Your goal is to capture the location of all the mines. You will
probably want to disable the breakpoints on <code>rand</code> and
<code>srand</code> for now. Devise a strategy using breakpoints and the
control buttons (Step, Resume, etc.) so that you can observe the
@@ -88,7 +88,7 @@ The State, Address, and Sleigh columns are the same as the top, but for the indi
* The **Trace** column indicates which target contains the location.
The text here should match one of the tabs from the Dynamic Listing panel.
* The **Comment** column is a user-defined comment.
Its default value is the specification that generated it, e.g., `srand`.
* The **Expression** column is the expression given when specifying the breakpoint, e.g., `srand`.
### Toggling the Breakpoints
@@ -195,7 +195,7 @@ The advantages of a dynamic session along side static analysis should become mor
### Exercise: Diagram the Mines
You goal is to capture the location of all the mines.
Your goal is to capture the location of all the mines.
You will probably want to disable the breakpoints on `rand` and `srand` for now.
Devise a strategy using breakpoints and the control buttons (Step, Resume, etc.) so that you can observe the location of each mine.
Use pen and paper to draw a diagram of the board, and mark the location of each mine as you observe the algorithm placing it.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 130 KiB