mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-787: Refactored Regions,Modules/Sections,Mappings,Threads to use RowWrapped...
This commit is contained in:
parent
84c77bb90c
commit
085daeb39b
17 changed files with 159 additions and 149 deletions
|
@ -18,7 +18,8 @@ package ghidra.app.plugin.core.debug.gui;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -1560,11 +1561,11 @@ public interface DebuggerResources {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static <V, R> void setSelectedRows(Set<V> sel, Map<V, R> rowMap, GTable table,
|
static <V, R> void setSelectedRows(Set<V> sel, Function<V, R> rowMapper, GTable table,
|
||||||
RowObjectTableModel<R> model, GTableFilterPanel<R> filterPanel) {
|
RowObjectTableModel<R> model, GTableFilterPanel<R> filterPanel) {
|
||||||
table.clearSelection();
|
table.clearSelection();
|
||||||
for (V v : sel) {
|
for (V v : sel) {
|
||||||
R row = rowMap.get(v);
|
R row = rowMapper.apply(v);
|
||||||
if (row == null) {
|
if (row == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -971,14 +971,12 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedBreakpoints(Set<LogicalBreakpoint> sel) {
|
public void setSelectedBreakpoints(Set<LogicalBreakpoint> sel) {
|
||||||
DebuggerResources.setSelectedRows(sel, breakpointTableModel.getMap(), breakpointTable,
|
DebuggerResources.setSelectedRows(sel, breakpointTableModel::getRow, breakpointTable,
|
||||||
breakpointTableModel, breakpointFilterPanel);
|
breakpointTableModel, breakpointFilterPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedLocations(Set<TraceBreakpoint> sel) {
|
public void setSelectedLocations(Set<TraceBreakpoint> sel) {
|
||||||
DebuggerResources.setSelectedRows(
|
DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable,
|
||||||
sel.stream().map(b -> b.getObjectKey()).collect(Collectors.toSet()),
|
|
||||||
locationTableModel.getMap(), locationTable,
|
|
||||||
locationTableModel, locationFilterPanel);
|
locationTableModel, locationFilterPanel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,9 @@ import com.google.common.collect.Range;
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.WindowPosition;
|
import docking.WindowPosition;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.CustomToStringCellRenderer;
|
||||||
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
|
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
|
||||||
|
import docking.widgets.table.RowWrappedEnumeratedColumnTableModel;
|
||||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
|
||||||
|
@ -51,6 +52,7 @@ import ghidra.trace.model.Trace.TraceMemoryRegionChangeType;
|
||||||
import ghidra.trace.model.TraceDomainObjectListener;
|
import ghidra.trace.model.TraceDomainObjectListener;
|
||||||
import ghidra.trace.model.memory.TraceMemoryManager;
|
import ghidra.trace.model.memory.TraceMemoryManager;
|
||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||||
|
import ghidra.util.database.ObjectKey;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
import ghidra.util.table.GhidraTableFilterPanel;
|
import ghidra.util.table.GhidraTableFilterPanel;
|
||||||
|
|
||||||
|
@ -112,6 +114,16 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class RegionTableModel
|
||||||
|
extends RowWrappedEnumeratedColumnTableModel< //
|
||||||
|
RegionTableColumns, ObjectKey, RegionRow, TraceMemoryRegion> {
|
||||||
|
|
||||||
|
public RegionTableModel() {
|
||||||
|
super("Regions", RegionTableColumns.class, TraceMemoryRegion::getObjectKey,
|
||||||
|
RegionRow::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected static RegionRow getSelectedRegionRow(ActionContext context) {
|
protected static RegionRow getSelectedRegionRow(ActionContext context) {
|
||||||
if (!(context instanceof DebuggerRegionActionContext)) {
|
if (!(context instanceof DebuggerRegionActionContext)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -150,26 +162,15 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void regionAdded(TraceMemoryRegion region) {
|
private void regionAdded(TraceMemoryRegion region) {
|
||||||
regionMap.computeIfAbsent(region, r -> {
|
regionTableModel.addItem(region);
|
||||||
RegionRow rr = new RegionRow(r);
|
|
||||||
regionTableModel.add(rr);
|
|
||||||
return rr;
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* NOTE: No need to add sections here. A TraceModule is created empty, so when each
|
|
||||||
* section is added, we'll get the call.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void regionChanged(TraceMemoryRegion region) {
|
private void regionChanged(TraceMemoryRegion region) {
|
||||||
regionTableModel.notifyUpdated(regionMap.get(region));
|
regionTableModel.updateItem(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void regionDeleted(TraceMemoryRegion region) {
|
private void regionDeleted(TraceMemoryRegion region) {
|
||||||
RegionRow rr = regionMap.remove(region);
|
regionTableModel.deleteItem(region);
|
||||||
if (rr != null) {
|
|
||||||
regionTableModel.delete(rr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,9 +223,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
private final RegionsListener regionsListener = new RegionsListener();
|
private final RegionsListener regionsListener = new RegionsListener();
|
||||||
|
|
||||||
protected final Map<TraceMemoryRegion, RegionRow> regionMap = new HashMap<>();
|
protected final RegionTableModel regionTableModel = new RegionTableModel();
|
||||||
protected final EnumeratedColumnTableModel<RegionRow> regionTableModel =
|
|
||||||
new DefaultEnumeratedColumnTableModel<>("Regions", RegionTableColumns.class);
|
|
||||||
protected GhidraTable regionTable;
|
protected GhidraTable regionTable;
|
||||||
private GhidraTableFilterPanel<RegionRow> regionFilterPanel;
|
private GhidraTableFilterPanel<RegionRow> regionFilterPanel;
|
||||||
|
|
||||||
|
@ -262,16 +261,13 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadRegions() {
|
private void loadRegions() {
|
||||||
regionMap.clear();
|
|
||||||
regionTableModel.clear();
|
regionTableModel.clear();
|
||||||
|
|
||||||
if (currentTrace == null) {
|
if (currentTrace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TraceMemoryManager memoryManager = currentTrace.getMemoryManager();
|
TraceMemoryManager memoryManager = currentTrace.getMemoryManager();
|
||||||
for (TraceMemoryRegion region : memoryManager.getAllRegions()) {
|
regionTableModel.addAllItems(memoryManager.getAllRegions());
|
||||||
regionTableModel.add(regionMap.computeIfAbsent(region, RegionRow::new));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildMainPanel() {
|
protected void buildMainPanel() {
|
||||||
|
@ -376,8 +372,8 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedRegions(Set<TraceMemoryRegion> sel) {
|
public void setSelectedRegions(Set<TraceMemoryRegion> sel) {
|
||||||
DebuggerResources.setSelectedRows(sel, regionMap, regionTable, regionTableModel,
|
DebuggerResources.setSelectedRows(sel, regionTableModel::getRow, regionTable,
|
||||||
regionFilterPanel);
|
regionTableModel, regionFilterPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<RegionRow> getSelectedRows() {
|
public Collection<RegionRow> getSelectedRows() {
|
||||||
|
|
|
@ -64,6 +64,7 @@ import ghidra.trace.model.TraceDomainObjectListener;
|
||||||
import ghidra.trace.model.modules.*;
|
import ghidra.trace.model.modules.*;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.database.ObjectKey;
|
||||||
import ghidra.util.datastruct.CollectionChangeListener;
|
import ghidra.util.datastruct.CollectionChangeListener;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
import ghidra.util.table.GhidraTableFilterPanel;
|
import ghidra.util.table.GhidraTableFilterPanel;
|
||||||
|
@ -198,6 +199,25 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
return sections.iterator().next();
|
return sections.iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class ModuleTableModel
|
||||||
|
extends RowWrappedEnumeratedColumnTableModel< //
|
||||||
|
ModuleTableColumns, ObjectKey, ModuleRow, TraceModule> {
|
||||||
|
|
||||||
|
public ModuleTableModel() {
|
||||||
|
super("Modules", ModuleTableColumns.class, TraceModule::getObjectKey, ModuleRow::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class SectionTableModel
|
||||||
|
extends RowWrappedEnumeratedColumnTableModel< //
|
||||||
|
SectionTableColumns, ObjectKey, SectionRow, TraceSection> {
|
||||||
|
|
||||||
|
public SectionTableModel() {
|
||||||
|
super("Sections", SectionTableColumns.class, TraceSection::getObjectKey,
|
||||||
|
SectionRow::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected static Set<TraceModule> getSelectedModules(ActionContext context) {
|
protected static Set<TraceModule> getSelectedModules(ActionContext context) {
|
||||||
if (context instanceof DebuggerModuleActionContext) {
|
if (context instanceof DebuggerModuleActionContext) {
|
||||||
DebuggerModuleActionContext ctx = (DebuggerModuleActionContext) context;
|
DebuggerModuleActionContext ctx = (DebuggerModuleActionContext) context;
|
||||||
|
@ -253,54 +273,39 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moduleAdded(TraceModule module) {
|
private void moduleAdded(TraceModule module) {
|
||||||
moduleMap.computeIfAbsent(module, m -> {
|
moduleTableModel.addItem(module);
|
||||||
ModuleRow mr = new ModuleRow(m);
|
/**
|
||||||
moduleTableModel.add(mr);
|
* NOTE: No need to add sections here. A TraceModule is created empty, so when each
|
||||||
return mr;
|
* section is added, we'll get the call.
|
||||||
});/**
|
*/
|
||||||
* NOTE: No need to add sections here. A TraceModule is created empty, so when each
|
|
||||||
* section is added, we'll get the call.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moduleChanged(TraceModule module) {
|
private void moduleChanged(TraceModule module) {
|
||||||
moduleTableModel.notifyUpdated(moduleMap.get(module));
|
moduleTableModel.updateItem(module);
|
||||||
sectionTableModel.fireTableDataChanged(); // Because module name in section row
|
sectionTableModel.fireTableDataChanged(); // Because module name in section row
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moduleDeleted(TraceModule module) {
|
private void moduleDeleted(TraceModule module) {
|
||||||
ModuleRow mr = moduleMap.remove(module);
|
moduleTableModel.deleteItem(module);
|
||||||
if (mr != null) {
|
|
||||||
moduleTableModel.delete(mr);
|
|
||||||
}
|
|
||||||
// NOTE: module.getSections() will be empty, now
|
// NOTE: module.getSections() will be empty, now
|
||||||
for (Iterator<Entry<TraceSection, SectionRow>> it = sectionMap.entrySet().iterator(); it
|
sectionTableModel.deleteAllItems(sectionTableModel.getMap()
|
||||||
.hasNext();) {
|
.values()
|
||||||
Entry<TraceSection, SectionRow> ent = it.next();
|
.stream()
|
||||||
if (ent.getKey().getModule() == module) {
|
.filter(r -> r.getModule() == module)
|
||||||
it.remove();
|
.map(r -> r.getSection())
|
||||||
sectionTableModel.delete(ent.getValue());
|
.collect(Collectors.toList()));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sectionAdded(TraceSection section) {
|
private void sectionAdded(TraceSection section) {
|
||||||
sectionMap.computeIfAbsent(section, s -> {
|
sectionTableModel.addItem(section);
|
||||||
SectionRow sr = new SectionRow(s);
|
|
||||||
sectionTableModel.add(sr);
|
|
||||||
return sr;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sectionChanged(TraceSection section) {
|
private void sectionChanged(TraceSection section) {
|
||||||
sectionTableModel.notifyUpdated(sectionMap.get(section));
|
sectionTableModel.updateItem(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sectionDeleted(TraceSection section) {
|
private void sectionDeleted(TraceSection section) {
|
||||||
SectionRow sr = sectionMap.remove(section);
|
sectionTableModel.deleteItem(section);
|
||||||
if (sr != null) {
|
|
||||||
sectionTableModel.delete(sr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,15 +521,11 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
private final RecordersChangedListener recordersChangedListener =
|
private final RecordersChangedListener recordersChangedListener =
|
||||||
new RecordersChangedListener();
|
new RecordersChangedListener();
|
||||||
|
|
||||||
protected final Map<TraceModule, ModuleRow> moduleMap = new HashMap<>();
|
protected final ModuleTableModel moduleTableModel = new ModuleTableModel();
|
||||||
protected final EnumeratedColumnTableModel<ModuleRow> moduleTableModel =
|
|
||||||
new DefaultEnumeratedColumnTableModel<>("Modules", ModuleTableColumns.class);
|
|
||||||
protected GhidraTable moduleTable;
|
protected GhidraTable moduleTable;
|
||||||
private GhidraTableFilterPanel<ModuleRow> moduleFilterPanel;
|
private GhidraTableFilterPanel<ModuleRow> moduleFilterPanel;
|
||||||
|
|
||||||
protected final Map<TraceSection, SectionRow> sectionMap = new HashMap<>();
|
protected final SectionTableModel sectionTableModel = new SectionTableModel();
|
||||||
protected final EnumeratedColumnTableModel<SectionRow> sectionTableModel =
|
|
||||||
new DefaultEnumeratedColumnTableModel<>("Sections", SectionTableColumns.class);
|
|
||||||
protected GhidraTable sectionTable;
|
protected GhidraTable sectionTable;
|
||||||
protected GhidraTableFilterPanel<SectionRow> sectionFilterPanel;
|
protected GhidraTableFilterPanel<SectionRow> sectionFilterPanel;
|
||||||
private final SectionsBySelectedModulesTableFilter filterSectionsBySelectedModules =
|
private final SectionsBySelectedModulesTableFilter filterSectionsBySelectedModules =
|
||||||
|
@ -598,22 +599,16 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadModules() {
|
private void loadModules() {
|
||||||
moduleMap.clear();
|
|
||||||
moduleTableModel.clear();
|
moduleTableModel.clear();
|
||||||
|
|
||||||
sectionMap.clear();
|
|
||||||
sectionTableModel.clear();
|
sectionTableModel.clear();
|
||||||
|
|
||||||
if (currentTrace == null) {
|
if (currentTrace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceModuleManager moduleManager = currentTrace.getModuleManager();
|
TraceModuleManager moduleManager = currentTrace.getModuleManager();
|
||||||
for (TraceModule module : moduleManager.getAllModules()) {
|
moduleTableModel.addAllItems(moduleManager.getAllModules());
|
||||||
moduleTableModel.add(moduleMap.computeIfAbsent(module, ModuleRow::new));
|
sectionTableModel.addAllItems(moduleManager.getAllSections());
|
||||||
for (TraceSection section : module.getSections()) {
|
|
||||||
sectionTableModel.add(sectionMap.computeIfAbsent(section, SectionRow::new));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildMainPanel() {
|
protected void buildMainPanel() {
|
||||||
|
@ -1092,13 +1087,13 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedModules(Set<TraceModule> sel) {
|
public void setSelectedModules(Set<TraceModule> sel) {
|
||||||
DebuggerResources.setSelectedRows(sel, moduleMap, moduleTable, moduleTableModel,
|
DebuggerResources.setSelectedRows(sel, moduleTableModel::getRow, moduleTable,
|
||||||
moduleFilterPanel);
|
moduleTableModel, moduleFilterPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedSections(Set<TraceSection> sel) {
|
public void setSelectedSections(Set<TraceSection> sel) {
|
||||||
DebuggerResources.setSelectedRows(sel, sectionMap, sectionTable, sectionTableModel,
|
DebuggerResources.setSelectedRows(sel, sectionTableModel::getRow, sectionTable,
|
||||||
sectionFilterPanel);
|
sectionTableModel, sectionFilterPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataTreeDialog getProgramChooserDialog() {
|
private DataTreeDialog getProgramChooserDialog() {
|
||||||
|
|
|
@ -19,7 +19,8 @@ import java.awt.BorderLayout;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -54,6 +55,7 @@ import ghidra.trace.model.modules.TraceStaticMappingManager;
|
||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.util.MathUtilities;
|
import ghidra.util.MathUtilities;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.database.ObjectKey;
|
||||||
import ghidra.util.database.UndoableTransaction;
|
import ghidra.util.database.UndoableTransaction;
|
||||||
import ghidra.util.table.GhidraTableFilterPanel;
|
import ghidra.util.table.GhidraTableFilterPanel;
|
||||||
|
|
||||||
|
@ -95,6 +97,16 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class MappingTableModel
|
||||||
|
extends RowWrappedEnumeratedColumnTableModel< //
|
||||||
|
StaticMappingTableColumns, ObjectKey, StaticMappingRow, TraceStaticMapping> {
|
||||||
|
|
||||||
|
public MappingTableModel() {
|
||||||
|
super("Mappings", StaticMappingTableColumns.class, TraceStaticMapping::getObjectKey,
|
||||||
|
StaticMappingRow::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected class ListenerForStaticMappingDisplay extends TraceDomainObjectListener {
|
protected class ListenerForStaticMappingDisplay extends TraceDomainObjectListener {
|
||||||
public ListenerForStaticMappingDisplay() {
|
public ListenerForStaticMappingDisplay() {
|
||||||
listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored());
|
listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored());
|
||||||
|
@ -107,11 +119,11 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
private void staticMappingAdded(TraceStaticMapping mapping) {
|
private void staticMappingAdded(TraceStaticMapping mapping) {
|
||||||
addMapping(mapping);
|
mappingTableModel.addItem(mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void staticMappingDeleted(TraceStaticMapping mapping) {
|
private void staticMappingDeleted(TraceStaticMapping mapping) {
|
||||||
mappingTableModel.deleteWith(rec -> rec.getMapping() == mapping);
|
mappingTableModel.deleteItem(mapping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +147,7 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
|
||||||
|
|
||||||
private ListenerForStaticMappingDisplay listener = new ListenerForStaticMappingDisplay();
|
private ListenerForStaticMappingDisplay listener = new ListenerForStaticMappingDisplay();
|
||||||
|
|
||||||
protected final EnumeratedColumnTableModel<StaticMappingRow> mappingTableModel =
|
protected final MappingTableModel mappingTableModel = new MappingTableModel();
|
||||||
new DefaultEnumeratedColumnTableModel<>("Mappings", StaticMappingTableColumns.class);
|
|
||||||
|
|
||||||
private JPanel mainPanel = new JPanel(new BorderLayout());
|
private JPanel mainPanel = new JPanel(new BorderLayout());
|
||||||
protected GTable mappingTable;
|
protected GTable mappingTable;
|
||||||
|
@ -187,23 +198,13 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
|
||||||
return myActionContext;
|
return myActionContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMapping(TraceStaticMapping mapping) {
|
|
||||||
mappingTableModel.add(new StaticMappingRow(mapping));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addMappings(Collection<? extends TraceStaticMapping> entries) {
|
|
||||||
for (TraceStaticMapping ent : entries) {
|
|
||||||
addMapping(ent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadMappings() {
|
private void loadMappings() {
|
||||||
mappingTableModel.clear();
|
mappingTableModel.clear();
|
||||||
if (currentTrace == null) {
|
if (currentTrace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TraceStaticMappingManager manager = currentTrace.getStaticMappingManager();
|
TraceStaticMappingManager manager = currentTrace.getStaticMappingManager();
|
||||||
addMappings(manager.getAllEntries());
|
mappingTableModel.addAllItems(manager.getAllEntries());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildMainPanel() {
|
protected void buildMainPanel() {
|
||||||
|
|
|
@ -214,11 +214,6 @@ public class ObjectEnumeratedColumnTableModel<C extends ObjectsEnumeratedTableCo
|
||||||
fireTableRowsInserted(startIndex, endIndex);
|
fireTableRowsInserted(startIndex, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RowIterator<R> rowIterator() {
|
|
||||||
return new TableRowIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyUpdated(R row) {
|
public void notifyUpdated(R row) {
|
||||||
int rowIndex = modelData.indexOf(row);
|
int rowIndex = modelData.indexOf(row);
|
||||||
|
|
|
@ -30,7 +30,8 @@ import docking.action.*;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
import docking.widgets.HorizontalTabPanel;
|
import docking.widgets.HorizontalTabPanel;
|
||||||
import docking.widgets.HorizontalTabPanel.TabListCellRenderer;
|
import docking.widgets.HorizontalTabPanel.TabListCellRenderer;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.GTable;
|
||||||
|
import docking.widgets.table.RowWrappedEnumeratedColumnTableModel;
|
||||||
import docking.widgets.timeline.TimelineListener;
|
import docking.widgets.timeline.TimelineListener;
|
||||||
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
|
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
|
||||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||||
|
@ -55,6 +56,7 @@ import ghidra.trace.model.thread.TraceThreadManager;
|
||||||
import ghidra.trace.model.time.TraceSchedule;
|
import ghidra.trace.model.time.TraceSchedule;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
|
import ghidra.util.database.ObjectKey;
|
||||||
import ghidra.util.datastruct.CollectionChangeListener;
|
import ghidra.util.datastruct.CollectionChangeListener;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
import ghidra.util.table.GhidraTableFilterPanel;
|
import ghidra.util.table.GhidraTableFilterPanel;
|
||||||
|
@ -249,6 +251,16 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class ThreadTableModel
|
||||||
|
extends RowWrappedEnumeratedColumnTableModel< //
|
||||||
|
ThreadTableColumns, ObjectKey, ThreadRow, TraceThread> {
|
||||||
|
|
||||||
|
public ThreadTableModel(DebuggerThreadsProvider provider) {
|
||||||
|
super("Threads", ThreadTableColumns.class, TraceThread::getObjectKey,
|
||||||
|
t -> new ThreadRow(provider.modelService, t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ThreadsListener extends TraceDomainObjectListener {
|
private class ThreadsListener extends TraceDomainObjectListener {
|
||||||
public ThreadsListener() {
|
public ThreadsListener() {
|
||||||
listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored());
|
listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored());
|
||||||
|
@ -267,23 +279,15 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void threadAdded(TraceThread thread) {
|
private void threadAdded(TraceThread thread) {
|
||||||
threadMap.computeIfAbsent(thread, t -> {
|
threadTableModel.addItem(thread);
|
||||||
ThreadRow tr = new ThreadRow(modelService, t);
|
|
||||||
threadTableModel.add(tr);
|
|
||||||
doSetThread(thread);
|
|
||||||
return tr;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void threadChanged(TraceThread thread) {
|
private void threadChanged(TraceThread thread) {
|
||||||
threadTableModel.notifyUpdatedWith(row -> row.getThread() == thread);
|
threadTableModel.updateItem(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void threadDeleted(TraceThread thread) {
|
private void threadDeleted(TraceThread thread) {
|
||||||
ThreadRow tr = threadMap.remove(thread);
|
threadTableModel.deleteItem(thread);
|
||||||
if (tr != null) {
|
|
||||||
threadTableModel.delete(tr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void snapAdded(TraceSnapshot snapshot) {
|
private void snapAdded(TraceSnapshot snapshot) {
|
||||||
|
@ -333,9 +337,7 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||||
private final CollectionChangeListener<TraceRecorder> recordersListener =
|
private final CollectionChangeListener<TraceRecorder> recordersListener =
|
||||||
new RecordersChangeListener();
|
new RecordersChangeListener();
|
||||||
|
|
||||||
protected final Map<TraceThread, ThreadRow> threadMap = new HashMap<>();
|
protected final ThreadTableModel threadTableModel = new ThreadTableModel(this);
|
||||||
protected final EnumeratedColumnTableModel<ThreadRow> threadTableModel =
|
|
||||||
new DefaultEnumeratedColumnTableModel<>("Threads", ThreadTableColumns.class);
|
|
||||||
|
|
||||||
private JPanel mainPanel;
|
private JPanel mainPanel;
|
||||||
private JSplitPane splitPane;
|
private JSplitPane splitPane;
|
||||||
|
@ -453,7 +455,7 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
try (Suppression supp = cbCoordinateActivation.suppress(null)) {
|
try (Suppression supp = cbCoordinateActivation.suppress(null)) {
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
threadFilterPanel.setSelectedItem(threadMap.get(thread));
|
threadFilterPanel.setSelectedItem(threadTableModel.getRow(thread));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
threadTable.clearSelection();
|
threadTable.clearSelection();
|
||||||
|
@ -495,20 +497,13 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadThreads() {
|
protected void loadThreads() {
|
||||||
threadMap.clear();
|
|
||||||
threadTableModel.clear();
|
threadTableModel.clear();
|
||||||
Trace curTrace = current.getTrace();
|
Trace curTrace = current.getTrace();
|
||||||
if (curTrace == null) {
|
if (curTrace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TraceThreadManager manager = curTrace.getThreadManager();
|
TraceThreadManager manager = curTrace.getThreadManager();
|
||||||
for (TraceThread thread : manager.getAllThreads()) {
|
threadTableModel.addAllItems(manager.getAllThreads());
|
||||||
threadMap.computeIfAbsent(thread, t -> {
|
|
||||||
ThreadRow tr = new ThreadRow(modelService, t);
|
|
||||||
threadTableModel.add(tr);
|
|
||||||
return tr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
updateTimelineMax();
|
updateTimelineMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* ###
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import ghidra.util.database.ObjectKey;
|
||||||
|
|
||||||
|
public interface TraceObject {
|
||||||
|
/**
|
||||||
|
* Get an opaque unique id for this object, whose hash is immutable
|
||||||
|
*
|
||||||
|
* @return the opaque object id
|
||||||
|
*/
|
||||||
|
ObjectKey getObjectKey();
|
||||||
|
}
|
|
@ -23,29 +23,22 @@ import com.google.common.collect.Range;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceObject;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.util.database.ObjectKey;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A breakpoint in a trace
|
* A breakpoint in a trace
|
||||||
*/
|
*/
|
||||||
public interface TraceBreakpoint {
|
public interface TraceBreakpoint extends TraceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the trace containning this breakpoint
|
* Get the trace containing this breakpoint
|
||||||
*
|
*
|
||||||
* @return the trace
|
* @return the trace
|
||||||
*/
|
*/
|
||||||
Trace getTrace();
|
Trace getTrace();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an opaque unique id for this object, whose hash is immutable
|
|
||||||
*
|
|
||||||
* @return the opaque object id
|
|
||||||
*/
|
|
||||||
ObjectKey getObjectKey();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "full name" of this breakpoint
|
* Get the "full name" of this breakpoint
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,12 +21,13 @@ import com.google.common.collect.Range;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceObject;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A region of mapped target memory in a trace
|
* A region of mapped target memory in a trace
|
||||||
*/
|
*/
|
||||||
public interface TraceMemoryRegion {
|
public interface TraceMemoryRegion extends TraceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the trace containing this region
|
* Get the trace containing this region
|
||||||
|
@ -105,7 +106,8 @@ public interface TraceMemoryRegion {
|
||||||
/**
|
/**
|
||||||
* @see #setLifespan(Range)
|
* @see #setLifespan(Range)
|
||||||
*
|
*
|
||||||
* @param destructionSnap the destruction snap, or {@link Long#MAX_VALUE} for "to the end of time"
|
* @param destructionSnap the destruction snap, or {@link Long#MAX_VALUE} for "to the end of
|
||||||
|
* time"
|
||||||
*/
|
*/
|
||||||
void setDestructionSnap(long destructionSnap)
|
void setDestructionSnap(long destructionSnap)
|
||||||
throws DuplicateNameException, TraceOverlappedRegionException;
|
throws DuplicateNameException, TraceOverlappedRegionException;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.google.common.collect.Range;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceObject;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +30,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
* <p>
|
* <p>
|
||||||
* This also serves as a namespace for storing the module's sections.
|
* This also serves as a namespace for storing the module's sections.
|
||||||
*/
|
*/
|
||||||
public interface TraceModule {
|
public interface TraceModule extends TraceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the trace containing this module
|
* Get the trace containing this module
|
||||||
|
|
|
@ -18,12 +18,13 @@ package ghidra.trace.model.modules;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceObject;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A section of a module in a trace
|
* A section of a module in a trace
|
||||||
*/
|
*/
|
||||||
public interface TraceSection {
|
public interface TraceSection extends TraceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the trace containing this section
|
* Get the trace containing this section
|
||||||
|
|
|
@ -23,11 +23,12 @@ import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapped range from this trace to a Ghidra {@link Program}
|
* A mapped range from this trace to a Ghidra {@link Program}
|
||||||
*/
|
*/
|
||||||
public interface TraceStaticMapping {
|
public interface TraceStaticMapping extends TraceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "from" trace, i.e., the trace containing this mapping
|
* Get the "from" trace, i.e., the trace containing this mapping
|
||||||
|
|
|
@ -21,12 +21,13 @@ import com.google.common.collect.Range;
|
||||||
|
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceObject;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread in a trace
|
* A thread in a trace
|
||||||
*/
|
*/
|
||||||
public interface TraceThread {
|
public interface TraceThread extends TraceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the trace containing this thread
|
* Get the trace containing this thread
|
||||||
|
|
|
@ -213,11 +213,6 @@ public class DefaultEnumeratedColumnTableModel<C extends Enum<C> & EnumeratedTab
|
||||||
fireTableRowsInserted(startIndex, endIndex);
|
fireTableRowsInserted(startIndex, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RowIterator<R> rowIterator() {
|
|
||||||
return new TableRowIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyUpdated(R row) {
|
public void notifyUpdated(R row) {
|
||||||
int rowIndex = modelData.indexOf(row);
|
int rowIndex = modelData.indexOf(row);
|
||||||
|
|
|
@ -27,8 +27,6 @@ public interface EnumeratedColumnTableModel<R> extends RowObjectTableModel<R> {
|
||||||
|
|
||||||
void addAll(Collection<R> c);
|
void addAll(Collection<R> c);
|
||||||
|
|
||||||
ListIterator<R> rowIterator();
|
|
||||||
|
|
||||||
void notifyUpdated(R row);
|
void notifyUpdated(R row);
|
||||||
|
|
||||||
List<R> notifyUpdatedWith(Predicate<R> predicate);
|
List<R> notifyUpdatedWith(Predicate<R> predicate);
|
||||||
|
|
|
@ -55,6 +55,10 @@ public class RowWrappedEnumeratedColumnTableModel<C extends Enum<C> & Enumerated
|
||||||
return c.stream().map(this::rowFor).collect(Collectors.toList());
|
return c.stream().map(this::rowFor).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized R getRow(T t) {
|
||||||
|
return map.get(keyFunc.apply(t));
|
||||||
|
}
|
||||||
|
|
||||||
public void addItem(T t) {
|
public void addItem(T t) {
|
||||||
add(rowFor(t));
|
add(rowFor(t));
|
||||||
}
|
}
|
||||||
|
@ -83,4 +87,10 @@ public class RowWrappedEnumeratedColumnTableModel<C extends Enum<C> & Enumerated
|
||||||
public synchronized Map<K, R> getMap() {
|
public synchronized Map<K, R> getMap() {
|
||||||
return Map.copyOf(map);
|
return Map.copyOf(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void clear() {
|
||||||
|
map.clear();
|
||||||
|
super.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue