GP-2474: Add "Map Manually" button to "Modules" window

This commit is contained in:
Dan 2022-08-23 10:30:27 -04:00
parent 1eb2e71734
commit 87c4a0f442
7 changed files with 215 additions and 156 deletions

View file

@ -1429,159 +1429,36 @@ public interface DebuggerResources {
}
}
interface MapIdenticallyAction {
String NAME = "Map Identically";
String DESCRIPTION =
"Map the current trace to the current program using identical addresses";
Icon ICON = ICON_MAP_IDENTICALLY;
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_identically";
String NAME_MAP_IDENTICALLY = "Map Identically";
String DESCRIPTION_MAP_IDENTICALLY =
"Map the current trace to the current program using identical addresses";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
.toolBarIcon(ICON)
.toolBarGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
String NAME_MAP_MANUALLY = "Map Manually";
String DESCRIPTION_MAP_MANUALLY = "Map the current trace to various programs manually";
interface MapModulesAction {
String NAME = "Map Modules";
String DESCRIPTION = "Map selected modules to program images";
Icon ICON = ICON_MAP_MODULES; // TODO: Probably no icon
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_modules";
String NAME_MAP_MODULES = "Map Modules";
String DESCRIPTION_MAP_MODULES = "Map selected modules to program images";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
//.toolBarIcon(ICON)
//.toolBarGroup(GROUP)
//.popupMenuIcon(ICON)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
String NAME_PREFIX_MAP_MODULE_TO = "Map Module to ";
String DESCRIPTION_MAP_MODULE_TO = "Map the selected module to the current program";
interface MapModuleToAction {
String NAME_PREFIX = "Map Module to ";
String DESCRIPTION = "Map the selected module to the current program";
Icon ICON = ICON_MAP_MODULES; // TODO: Probably no icon
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_module_to";
String NAME_MAP_SECTIONS = "Map Sections";
String DESCRIPTION_MAP_SECTIONS = "Map selected sections to program memory blocks";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
String NAME_PREFIX_MAP_SECTION_TO = "Map Section to ";
String DESCRIPTION_MAP_SECTION_TO = "Map the selected section to the current program";
interface MapSectionsAction {
String NAME = "Map Sections";
String DESCRIPTION = "Map selected sections to program memory blocks";
Icon ICON = ICON_MAP_SECTIONS; // TODO: Probably no icon
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_sections";
String NAME_PREFIX_MAP_SECTIONS_TO = "Map Sections to ";
String DESCRIPTION_MAP_SECTIONS_TO = "Map the selected module sections to the current program";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
//.toolBarIcon(ICON)
//.toolBarGroup(GROUP)
//.popupMenuIcon(ICON)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
String NAME_MAP_REGIONS = "Map Regions";
String DESCRIPTION_MAP_REGIONS = "Map selected regions to program memory blocks";
interface MapSectionToAction {
String NAME_PREFIX = "Map Section to ";
String DESCRIPTION = "Map the selected section to the current program";
Icon ICON = ICON_MAP_SECTIONS; // TODO: Probably no icon
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_section_to";
String NAME_PREFIX_MAP_REGION_TO = "Map Region to ";
String DESCRIPTION_MAP_REGION_TO = "Map the selected region to the current program";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapSectionsToAction {
String NAME_PREFIX = "Map Sections to ";
String DESCRIPTION = "Map the selected module sections to the current program";
Icon ICON = ICON_MAP_SECTIONS;
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_sections_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapRegionsAction {
String NAME = "Map Regions";
String DESCRIPTION = "Map selected regions to program memory blocks";
Icon ICON = ICON_MAP_REGIONS; // TODO: Probably no icon
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_regions";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
//.toolBarIcon(ICON)
//.toolBarGroup(GROUP)
//.popupMenuIcon(ICON)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapRegionToAction {
String NAME_PREFIX = "Map Region to ";
String DESCRIPTION = "Map the selected region to the current program";
Icon ICON = ICON_MAP_SECTIONS; // TODO: Probably no icon
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_region_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapRegionsToAction {
String NAME_PREFIX = "Map Regions to ";
String DESCRIPTION = "Map the selected (module) regions to the current program";
Icon ICON = ICON_MAP_SECTIONS;
String GROUP = GROUP_MAPPING;
String HELP_ANCHOR = "map_regions_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
String NAME_PREFIX_MAP_REGIONS_TO = "Map Regions to ";
String DESCRIPTION_MAP_REGIONS_TO = "Map the selected (module) regions to the current program";
/*interface SelectAddressesAction { // TODO: Finish this conversion
String NAME = "Select Addresses";

View file

@ -27,7 +27,6 @@ import docking.widgets.table.*;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerMapProposalDialog;
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.MapRegionsAction;
import ghidra.app.services.RegionMapProposal.RegionMapEntry;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
@ -115,7 +114,7 @@ public class DebuggerRegionMapProposalDialog
private final DebuggerRegionsProvider provider;
public DebuggerRegionMapProposalDialog(DebuggerRegionsProvider provider) {
super(provider.getTool(), MapRegionsAction.NAME);
super(provider.getTool(), DebuggerResources.NAME_MAP_REGIONS);
this.provider = provider;
}

View file

@ -32,6 +32,7 @@ import com.google.common.collect.Range;
import docking.ActionContext;
import docking.WindowPosition;
import docking.action.*;
import docking.action.builder.ActionBuilder;
import docking.widgets.table.CustomToStringCellRenderer;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
@ -56,6 +57,7 @@ import ghidra.trace.model.Trace.TraceMemoryRegionChangeType;
import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.memory.TraceMemoryManager;
import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.database.ObjectKey;
import ghidra.util.table.GhidraTable;
@ -63,6 +65,52 @@ import ghidra.util.table.GhidraTableFilterPanel;
public class DebuggerRegionsProvider extends ComponentProviderAdapter {
interface MapRegionsAction {
String NAME = DebuggerResources.NAME_MAP_REGIONS;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_REGIONS;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_regions";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapRegionToAction {
String NAME_PREFIX = DebuggerResources.NAME_PREFIX_MAP_REGION_TO;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_REGION_TO;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_region_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapRegionsToAction {
String NAME_PREFIX = DebuggerResources.NAME_PREFIX_MAP_REGIONS_TO;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_REGIONS_TO;
Icon ICON = DebuggerResources.ICON_MAP_SECTIONS;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_regions_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
protected enum RegionTableColumns
implements EnumeratedTableColumn<RegionTableColumns, RegionRow> {
NAME("Name", String.class, RegionRow::getName, RegionRow::setName),

View file

@ -26,7 +26,6 @@ import docking.widgets.table.*;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerMapProposalDialog;
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.MapModulesAction;
import ghidra.app.services.ModuleMapProposal.ModuleMapEntry;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.PluginTool;
@ -114,7 +113,7 @@ public class DebuggerModuleMapProposalDialog
private final DebuggerModulesProvider provider;
protected DebuggerModuleMapProposalDialog(DebuggerModulesProvider provider) {
super(provider.getTool(), MapModulesAction.NAME);
super(provider.getTool(), DebuggerResources.NAME_MAP_MODULES);
this.provider = provider;
}

View file

@ -30,9 +30,9 @@ import javax.swing.table.TableColumnModel;
import com.google.common.collect.Range;
import docking.ActionContext;
import docking.WindowPosition;
import docking.*;
import docking.action.*;
import docking.action.builder.ActionBuilder;
import docking.widgets.filechooser.GhidraFileChooser;
import docking.widgets.table.CustomToStringCellRenderer;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
@ -55,6 +55,7 @@ import ghidra.framework.main.DataTreeDialog;
import ghidra.framework.model.*;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.framework.plugintool.util.PluginException;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
@ -73,6 +74,114 @@ import ghidra.util.table.GhidraTable;
import ghidra.util.table.GhidraTableFilterPanel;
public class DebuggerModulesProvider extends ComponentProviderAdapter {
interface MapIdenticallyAction {
String NAME = DebuggerResources.NAME_MAP_IDENTICALLY;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_IDENTICALLY;
Icon ICON = DebuggerResources.ICON_MAP_IDENTICALLY;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_identically";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
.toolBarIcon(ICON)
.toolBarGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapManuallyAction {
String NAME = DebuggerResources.NAME_MAP_MANUALLY;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_MANUALLY;
Icon ICON = DebuggerResources.ICON_MAPPINGS;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_manually";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
.toolBarIcon(ICON)
.toolBarGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapModulesAction {
String NAME = "Map Modules";
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_MODULES;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_modules";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapModuleToAction {
String NAME_PREFIX = DebuggerResources.NAME_PREFIX_MAP_MODULE_TO;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_MODULE_TO;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_module_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapSectionsAction {
String NAME = DebuggerResources.NAME_MAP_SECTIONS;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_SECTIONS;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_sections";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME)
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapSectionToAction {
String NAME_PREFIX = DebuggerResources.NAME_PREFIX_MAP_SECTION_TO;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_SECTION_TO;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_section_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
interface MapSectionsToAction {
String NAME_PREFIX = DebuggerResources.NAME_PREFIX_MAP_SECTIONS_TO;
String DESCRIPTION = DebuggerResources.DESCRIPTION_MAP_SECTIONS_TO;
String GROUP = DebuggerResources.GROUP_MAPPING;
String HELP_ANCHOR = "map_sections_to";
static ActionBuilder builder(Plugin owner) {
String ownerName = owner.getName();
return new ActionBuilder(NAME_PREFIX, ownerName).description(DESCRIPTION)
.popupMenuPath(NAME_PREFIX + "...")
.popupMenuGroup(GROUP)
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
}
}
protected enum ModuleTableColumns
implements EnumeratedTableColumn<ModuleTableColumns, ModuleRow> {
BASE("Base Address", Address.class, ModuleRow::getBase),
@ -578,6 +687,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
private ProgramLocation currentLocation;
DockingAction actionMapIdentically;
DockingAction actionMapManually;
DockingAction actionMapModules;
DockingAction actionMapModuleTo;
DockingAction actionMapSections;
@ -795,6 +905,10 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
.enabledWhen(ctx -> currentProgram != null && currentTrace != null)
.onAction(this::activatedMapIdentically)
.buildAndInstallLocal(this);
actionMapManually = MapManuallyAction.builder(plugin)
.enabled(true)
.onAction(this::activatedMapManually)
.buildAndInstallLocal(this);
actionMapModules = MapModulesAction.builder(plugin)
.enabledWhen(this::isContextNonEmpty)
.popupWhen(this::isContextNonEmpty)
@ -878,6 +992,26 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
Range.atLeast(traceManager.getCurrentSnap()), true);
}
private void activatedMapManually(ActionContext ignored) {
ComponentProvider provider =
tool.getComponentProvider(DebuggerResources.TITLE_PROVIDER_MAPPINGS);
if (provider != null) {
tool.showComponentProvider(provider, true);
return;
}
try {
tool.addPlugin(DebuggerStaticMappingPlugin.class.getName());
}
catch (PluginException e) {
Msg.showError(this, mainPanel, MapManuallyAction.NAME,
"DebuggerStaticMappingPlugin could not be enabled", e);
return;
}
provider = tool.getComponentProvider(DebuggerResources.TITLE_PROVIDER_MAPPINGS);
assert provider != null;
tool.showComponentProvider(provider, true);
}
private void activatedMapModules(ActionContext ignored) {
Set<TraceModule> sel = getSelectedModules(myActionContext);
if (sel == null || sel.isEmpty()) {

View file

@ -27,7 +27,6 @@ import docking.widgets.table.*;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerMapProposalDialog;
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.MapSectionsAction;
import ghidra.app.services.SectionMapProposal.SectionMapEntry;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
@ -116,7 +115,7 @@ public class DebuggerSectionMapProposalDialog
private final DebuggerModulesProvider provider;
public DebuggerSectionMapProposalDialog(DebuggerModulesProvider provider) {
super(provider.getTool(), MapSectionsAction.NAME);
super(provider.getTool(), DebuggerResources.NAME_MAP_SECTIONS);
this.provider = provider;
}

View file

@ -29,13 +29,15 @@ import com.google.common.collect.Range;
import docking.widgets.filechooser.GhidraFileChooser;
import generic.Unique;
import generic.test.category.NightlyCategory;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog;
import ghidra.app.plugin.core.debug.gui.*;
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog.MemoryBlockRow;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractImportFromFileSystemAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModuleMapProposalDialog.ModuleMapTableColumns;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProvider.MapModulesAction;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProvider.MapSectionsAction;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerSectionMapProposalDialog.SectionMapTableColumns;
import ghidra.app.services.DebuggerListingService;
import ghidra.app.services.ModuleMapProposal.ModuleMapEntry;
@ -715,7 +717,8 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
}
protected static final Set<String> POPUP_ACTIONS = Set.of(AbstractSelectAddressesAction.NAME,
MapModulesAction.NAME, MapSectionsAction.NAME, AbstractImportFromFileSystemAction.NAME);
DebuggerResources.NAME_MAP_MODULES, DebuggerResources.NAME_MAP_SECTIONS,
AbstractImportFromFileSystemAction.NAME);
@Test
public void testPopupActionsOnModuleSelections() throws Exception {