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 2e39041d0b..8ff385ab6d 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 @@ -73,7 +73,14 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat return null; } long snap = coordinates.getSnap(); - TraceStack stack = trace.getStackManager().getLatestStack(thread, snap); + TraceStack stack; + try { + stack = trace.getStackManager().getLatestStack(thread, snap); + } + catch (IllegalStateException e) { + // Schema does not specify a stack + return null; + } if (stack == null) { return null; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/AbstractQueryTablePanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/AbstractQueryTablePanel.java index 90d60d5bae..e2c5f95d99 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/AbstractQueryTablePanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/model/AbstractQueryTablePanel.java @@ -18,18 +18,17 @@ package ghidra.app.plugin.core.debug.gui.model; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.*; -import java.util.*; +import java.util.Collection; +import java.util.List; import java.util.stream.Collectors; import javax.swing.*; import javax.swing.event.ListSelectionListener; -import docking.widgets.table.DynamicTableColumn; import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener; import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.framework.plugintool.Plugin; import ghidra.trace.model.Lifespan; -import ghidra.trace.model.Trace; import ghidra.trace.model.target.TraceObject; import ghidra.util.datastruct.ListenerSet; import ghidra.util.table.GhidraTable; @@ -209,24 +208,6 @@ public abstract class AbstractQueryTablePanel Map.Entry> getColumnByNameAndType( - String name, Class type) { - int count = tableModel.getColumnCount(); - for (int i = 0; i < count; i++) { - DynamicTableColumn column = tableModel.getColumn(i); - if (!name.equals(column.getColumnName())) { - continue; - } - if (column.getColumnClass() != type) { - continue; - } - return Map.entry(table.convertColumnIndexToView(i), - (DynamicTableColumn) column); - } - return null; - } - public void setDiffColor(Color diffColor) { tableModel.setDiffColor(diffColor); } 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 a65e1ab017..ae6da77f96 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 @@ -84,6 +84,9 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel getProperty(ValueRow row) { - DebuggerCoordinates coords = provider.current.object(row.currentObject()); + TraceObject obj = row.getValue().getChild(); + DebuggerCoordinates coords = provider.current.object(obj); return new ValueAddressProperty(row) { @Override public Address getValue() { 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 9cd70a5a9e..1733745649 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 @@ -39,9 +39,9 @@ import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper; import ghidra.dbg.target.TargetMemoryRegion; import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; +import ghidra.dbg.target.schema.XmlSchemaContext; import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry; import ghidra.debug.api.tracemgr.DebuggerCoordinates; -import ghidra.dbg.target.schema.XmlSchemaContext; import ghidra.program.model.address.*; import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryBlock; @@ -151,20 +151,29 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes protected void assertRow(int position, Object object, String name, Address start, Address end, long length, String flags) { ValueRow row = provider.panel.getAllItems().get(position); - DynamicTableColumn nameCol = - provider.panel.getColumnByNameAndType("Name", ValueRow.class).getValue(); - DynamicTableColumn startCol = - provider.panel.getColumnByNameAndType("Start", ValueProperty.class).getValue(); - DynamicTableColumn endCol = - provider.panel.getColumnByNameAndType("End", ValueProperty.class).getValue(); - DynamicTableColumn lengthCol = - provider.panel.getColumnByNameAndType("Length", ValueProperty.class).getValue(); - DynamicTableColumn readCol = - provider.panel.getColumnByNameAndType("Read", ValueProperty.class).getValue(); - DynamicTableColumn writeCol = - provider.panel.getColumnByNameAndType("Write", ValueProperty.class).getValue(); - DynamicTableColumn executeCol = - provider.panel.getColumnByNameAndType("Execute", ValueProperty.class).getValue(); + var tableModel = QueryPanelTestHelper.getTableModel(provider.panel); + GhidraTable table = QueryPanelTestHelper.getTable(provider.panel); + DynamicTableColumn nameCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Name", ValueRow.class) + .column(); + DynamicTableColumn startCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Start", ValueProperty.class) + .column(); + DynamicTableColumn endCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "End", ValueProperty.class) + .column(); + DynamicTableColumn lengthCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Length", ValueProperty.class) + .column(); + DynamicTableColumn readCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Read", ValueProperty.class) + .column(); + DynamicTableColumn writeCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Write", ValueProperty.class) + .column(); + DynamicTableColumn executeCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Execute", ValueProperty.class) + .column(); assertSame(object, row.getValue().getValue()); assertEquals(name, rowColDisplay(row, nameCol)); @@ -349,10 +358,14 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes }); waitForPass(() -> assertFalse(tb.trace.getProgramView().getMemory().isEmpty())); - int startColIdx = - provider.panel.getColumnByNameAndType("Start", ValueProperty.class).getKey(); - int endColIdx = provider.panel.getColumnByNameAndType("End", ValueProperty.class).getKey(); + var tableModel = QueryPanelTestHelper.getTableModel(provider.panel); GhidraTable table = QueryPanelTestHelper.getTable(provider.panel); + int startColIdx = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Start", ValueProperty.class) + .viewIndex(); + int endColIdx = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "End", ValueProperty.class) + .viewIndex(); clickTableCell(table, 0, startColIdx, 2); waitForPass(() -> assertEquals(tb.addr(0x00400000), listing.getLocation().getAddress())); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/QueryPanelTestHelper.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/QueryPanelTestHelper.java index 6634b30945..e20bf78952 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/QueryPanelTestHelper.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/model/QueryPanelTestHelper.java @@ -16,14 +16,37 @@ package ghidra.app.plugin.core.debug.gui.model; import docking.widgets.table.*; -import ghidra.app.plugin.core.debug.gui.thread.DebuggerThreadsPanel; +import ghidra.trace.model.Trace; import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.column.GColumnRenderer; public class QueryPanelTestHelper { - public static ObjectTableModel getTableModel(DebuggerThreadsPanel panel) { + public record ColumnAndIndex(DynamicTableColumn column, int modelIndex, + int viewIndex) { + } + + @SuppressWarnings("unchecked") + public static ColumnAndIndex getColumnByNameAndType( + AbstractQueryTableModel tableModel, GhidraTable table, String name, Class type) { + int count = tableModel.getColumnCount(); + for (int i = 0; i < count; i++) { + DynamicTableColumn column = tableModel.getColumn(i); + if (!name.equals(column.getColumnName())) { + continue; + } + if (column.getColumnClass() != type) { + continue; + } + return new ColumnAndIndex<>((DynamicTableColumn) column, + i, table.convertColumnIndexToView(i)); + } + return null; + } + + public static AbstractQueryTableModel getTableModel( + AbstractQueryTablePanel panel) { return panel.tableModel; } 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 3397a4ec61..7754328a67 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 @@ -232,14 +232,20 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes protected void assertModuleRow(int pos, Object object, String name, Address start, Address end, long length) { ValueRow row = provider.modulesPanel.getAllItems().get(pos); - DynamicTableColumn nameCol = - provider.modulesPanel.getColumnByNameAndType("Name", ValueProperty.class).getValue(); - DynamicTableColumn baseCol = - provider.modulesPanel.getColumnByNameAndType("Base", ValueProperty.class).getValue(); - DynamicTableColumn maxCol = - provider.modulesPanel.getColumnByNameAndType("Max", ValueProperty.class).getValue(); - DynamicTableColumn lengthCol = - provider.modulesPanel.getColumnByNameAndType("Length", ValueProperty.class).getValue(); + var tableModel = QueryPanelTestHelper.getTableModel(provider.modulesPanel); + GhidraTable table = QueryPanelTestHelper.getTable(provider.modulesPanel); + DynamicTableColumn nameCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Name", ValueProperty.class) + .column(); + DynamicTableColumn baseCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Base", ValueProperty.class) + .column(); + DynamicTableColumn maxCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Max", ValueProperty.class) + .column(); + DynamicTableColumn lengthCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Length", ValueProperty.class) + .column(); assertSame(object, row.getValue().getValue()); assertEquals(name, rowColVal(row, nameCol)); @@ -251,17 +257,23 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes protected void assertSectionRow(int pos, Object object, String moduleName, String name, Address start, Address end, long length) { ValueRow row = provider.sectionsPanel.getAllItems().get(pos); - DynamicTableColumn moduleNameCol = - provider.sectionsPanel.getColumnByNameAndType("Module Name", ValueProperty.class) - .getValue(); - DynamicTableColumn nameCol = - provider.sectionsPanel.getColumnByNameAndType("Name", String.class).getValue(); - DynamicTableColumn startCol = - provider.sectionsPanel.getColumnByNameAndType("Start", ValueProperty.class).getValue(); - DynamicTableColumn endCol = - provider.sectionsPanel.getColumnByNameAndType("End", ValueProperty.class).getValue(); - DynamicTableColumn lengthCol = - provider.sectionsPanel.getColumnByNameAndType("Length", ValueProperty.class).getValue(); + var tableModel = QueryPanelTestHelper.getTableModel(provider.sectionsPanel); + GhidraTable table = QueryPanelTestHelper.getTable(provider.sectionsPanel); + DynamicTableColumn moduleNameCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Module Name", ValueProperty.class) + .column(); + DynamicTableColumn nameCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Name", String.class) + .column(); + DynamicTableColumn startCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Start", ValueProperty.class) + .column(); + DynamicTableColumn endCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "End", ValueProperty.class) + .column(); + DynamicTableColumn lengthCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Length", ValueProperty.class) + .column(); assertSame(object, row.getValue().getValue()); assertEquals(moduleName, rowColVal(row, moduleNameCol)); 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 87ec82984d..800fed28a8 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 @@ -15,7 +15,8 @@ */ package ghidra.app.plugin.core.debug.gui.stack; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.List; @@ -52,6 +53,7 @@ import ghidra.trace.model.stack.TraceObjectStack; import ghidra.trace.model.target.*; import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.thread.TraceObjectThread; +import ghidra.util.table.GhidraTable; import ghidra.util.task.TaskMonitor; /** @@ -215,13 +217,18 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest protected void assertRow(int level, Address pcVal, Function func) { ValueRow row = stackProvider.panel.getAllItems().get(level); + var tableModel = QueryPanelTestHelper.getTableModel(stackProvider.panel); + GhidraTable table = QueryPanelTestHelper.getTable(stackProvider.panel); - DynamicTableColumn levelCol = - stackProvider.panel.getColumnByNameAndType("Level", String.class).getValue(); - DynamicTableColumn pcCol = - stackProvider.panel.getColumnByNameAndType("PC", ValueProperty.class).getValue(); - DynamicTableColumn funcCol = - stackProvider.panel.getColumnByNameAndType("Function", Function.class).getValue(); + DynamicTableColumn levelCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Level", String.class) + .column(); + DynamicTableColumn pcCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "PC", ValueProperty.class) + .column(); + DynamicTableColumn funcCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Function", Function.class) + .column(); assertEquals(PathUtils.makeKey(PathUtils.makeIndex(level)), rowColVal(row, levelCol)); assertEquals(pcVal, rowColVal(row, pcCol)); @@ -308,8 +315,6 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest /** * Because keys are strings, we need to ensure they get sorted numerically - * - * @throws Exception */ @Test public void testTableSortedCorrectly() throws Exception { 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 a1d186abd7..f655fcb87f 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 @@ -29,7 +29,6 @@ import db.Transaction; import docking.widgets.table.*; import generic.test.category.NightlyCategory; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest; -import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel; import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*; import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper; import ghidra.dbg.target.TargetExecutionStateful; @@ -154,25 +153,24 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes assertThreadsTableSize(0); } - protected void assertThreadRow(int position, Object object, String name, Long created, - Long destroyed, TargetExecutionState state, String comment) { + protected void assertThreadRow(int position, Object object, String name, + TargetExecutionState state, String comment) { // NB. Not testing plot, since that's unmodified from generic ObjectTable ValueRow row = provider.panel.getAllItems().get(position); - DynamicTableColumn nameCol = - provider.panel.getColumnByNameAndType("Name", ValueRow.class).getValue(); - DynamicTableColumn createdCol = - provider.panel.getColumnByNameAndType("Created", ValueProperty.class).getValue(); - DynamicTableColumn destroyedCol = - provider.panel.getColumnByNameAndType("Destroyed", ValueProperty.class).getValue(); - DynamicTableColumn stateCol = - provider.panel.getColumnByNameAndType("State", ValueProperty.class).getValue(); - DynamicTableColumn commentCol = - provider.panel.getColumnByNameAndType("Comment", ValueProperty.class).getValue(); + var tableModel = QueryPanelTestHelper.getTableModel(provider.panel); + GhidraTable table = QueryPanelTestHelper.getTable(provider.panel); + DynamicTableColumn nameCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Name", ValueRow.class) + .column(); + DynamicTableColumn stateCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "State", ValueProperty.class) + .column(); + DynamicTableColumn commentCol = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Comment", ValueProperty.class) + .column(); assertSame(object, row.getValue().getValue()); assertEquals(name, rowColDisplay(row, nameCol)); - assertEquals(created, rowColVal(row, createdCol)); - assertEquals(destroyed, rowColVal(row, destroyedCol)); assertEquals(state.name(), rowColVal(row, stateCol)); assertEquals(comment, rowColVal(row, commentCol)); } @@ -180,9 +178,9 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes protected void assertThreadsPopulated() { assertThreadsTableSize(2); - assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]", 0L, null, + assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]", TargetExecutionState.STOPPED, "A comment"); - assertThreadRow(1, thread2.getObject(), "Processes[1].Threads[2]", 0L, 10L, + assertThreadRow(1, thread2.getObject(), "Processes[1].Threads[2]", TargetExecutionState.STOPPED, "Another comment"); } @@ -399,7 +397,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes waitForTasks(); waitForPass(() -> { - assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]", 0L, 15L, + assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]", TargetExecutionState.STOPPED, "A comment"); }); // NOTE: Destruction will not be visible in plot unless snapshot 15 is created @@ -429,11 +427,12 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes traceManager.activateTrace(tb.trace); waitForTasks(); - int commentViewIdx = - provider.panel.getColumnByNameAndType("Comment", ValueProperty.class).getKey(); - ObjectTableModel tableModel = QueryPanelTestHelper.getTableModel(provider.panel); + var tableModel = QueryPanelTestHelper.getTableModel(provider.panel); GhidraTable table = QueryPanelTestHelper.getTable(provider.panel); - int commentModelIdx = table.convertColumnIndexToModel(commentViewIdx); + int commentModelIdx = QueryPanelTestHelper + .getColumnByNameAndType(tableModel, table, "Comment", ValueProperty.class) + .modelIndex(); + assertNotEquals(-1, commentModelIdx); runSwing(() -> { tableModel.setValueAt(new ValueFixedProperty<>("A different comment"), 0,