mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-08 21:47:59 -05:00
Merge remote-tracking branch 'origin/GP-1-dragonmacher-strings-table-jumping'
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -28,14 +28,14 @@ import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.util.table.GhidraTable;
|
||||
|
||||
public class ViewStringsContext extends DefaultActionContext implements DataLocationListContext {
|
||||
public class DefinedStringsContext extends DefaultActionContext implements DataLocationListContext {
|
||||
|
||||
private final ViewStringsProvider viewStringsProvider;
|
||||
private final DefinedStringsProvider viewStringsProvider;
|
||||
private final GhidraTable table;
|
||||
private final ViewStringsTableModel tableModel;
|
||||
private final DefinedStringsTableModel tableModel;
|
||||
|
||||
ViewStringsContext(ViewStringsProvider provider, GhidraTable table,
|
||||
ViewStringsTableModel tableModel) {
|
||||
DefinedStringsContext(DefinedStringsProvider provider, GhidraTable table,
|
||||
DefinedStringsTableModel tableModel) {
|
||||
super(provider, table);
|
||||
this.viewStringsProvider = provider;
|
||||
this.table = table;
|
||||
@@ -58,7 +58,7 @@ import resources.ResourceManager;
|
||||
servicesRequired = { GoToService.class }
|
||||
)
|
||||
//@formatter:on
|
||||
public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectListener {
|
||||
public class DefinedStringsPlugin extends ProgramPlugin implements DomainObjectListener {
|
||||
|
||||
private static Icon REFRESH_ICON = Icons.REFRESH_ICON;
|
||||
private static Icon REFRESH_NOT_NEEDED_ICON =
|
||||
@@ -66,10 +66,10 @@ public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectList
|
||||
|
||||
private DockingAction refreshAction;
|
||||
private SelectionNavigationAction linkNavigationAction;
|
||||
private ViewStringsProvider provider;
|
||||
private DefinedStringsProvider provider;
|
||||
private SwingUpdateManager reloadUpdateMgr;
|
||||
|
||||
public ViewStringsPlugin(PluginTool tool) {
|
||||
public DefinedStringsPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectList
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
provider = new ViewStringsProvider(this);
|
||||
provider = new DefinedStringsProvider(this);
|
||||
reloadUpdateMgr = new SwingUpdateManager(100, 60000, this::doReload);
|
||||
createActions();
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectList
|
||||
tool.addLocalAction(provider, linkNavigationAction);
|
||||
|
||||
new ActionBuilder("Data Settings", getName()) // create pop-up menu item "Settings..."
|
||||
.withContext(ViewStringsContext.class)
|
||||
.withContext(DefinedStringsContext.class)
|
||||
.popupMenuPath("Settings...")
|
||||
.popupMenuGroup("R")
|
||||
.helpLocation(new HelpLocation("DataPlugin", "Data_Settings"))
|
||||
@@ -128,7 +128,7 @@ public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectList
|
||||
.buildAndInstallLocal(provider);
|
||||
|
||||
new ActionBuilder("Default Settings", getName()) // create pop-up menu item "Default Settings..."
|
||||
.withContext(ViewStringsContext.class)
|
||||
.withContext(DefinedStringsContext.class)
|
||||
.popupMenuPath("Default Settings...")
|
||||
.popupMenuGroup("R")
|
||||
.helpLocation(new HelpLocation("DataPlugin", "Default_Settings"))
|
||||
@@ -211,7 +211,6 @@ public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectList
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//Msg.info(this, "Unhandled event type: " + doRecord.getEventType());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -38,20 +38,20 @@ import ghidra.util.table.*;
|
||||
/**
|
||||
* Provider for the defined strings table.
|
||||
*/
|
||||
public class ViewStringsProvider extends ComponentProviderAdapter {
|
||||
public class DefinedStringsProvider extends ComponentProviderAdapter {
|
||||
|
||||
public static final Icon ICON = new GIcon("icon.plugin.viewstrings.provider");
|
||||
|
||||
private GhidraThreadedTablePanel<ProgramLocation> threadedTablePanel;
|
||||
private GhidraTableFilterPanel<ProgramLocation> filterPanel;
|
||||
private GhidraTable table;
|
||||
private ViewStringsTableModel stringModel;
|
||||
private DefinedStringsTableModel stringModel;
|
||||
private JComponent mainPanel;
|
||||
private Program currentProgram;
|
||||
private HelpLocation helpLocation;
|
||||
private AtomicReference<ProgramLocation> delayedShowProgramLocation = new AtomicReference<>();
|
||||
|
||||
ViewStringsProvider(ViewStringsPlugin plugin) {
|
||||
DefinedStringsProvider(DefinedStringsPlugin plugin) {
|
||||
super(plugin.getTool(), "Defined Strings", plugin.getName());
|
||||
mainPanel = createWorkPanel();
|
||||
setIcon(ICON);
|
||||
@@ -70,8 +70,8 @@ public class ViewStringsProvider extends ComponentProviderAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewStringsContext getActionContext(MouseEvent event) {
|
||||
return new ViewStringsContext(this, table, stringModel);
|
||||
public DefinedStringsContext getActionContext(MouseEvent event) {
|
||||
return new DefinedStringsContext(this, table, stringModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,9 +79,6 @@ public class ViewStringsProvider extends ComponentProviderAdapter {
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.docking.HelpTopic#getHelpLocation()
|
||||
*/
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return helpLocation;
|
||||
@@ -107,12 +104,16 @@ public class ViewStringsProvider extends ComponentProviderAdapter {
|
||||
|
||||
private JComponent createWorkPanel() {
|
||||
|
||||
stringModel = new ViewStringsTableModel(tool);
|
||||
stringModel = new DefinedStringsTableModel(tool);
|
||||
|
||||
threadedTablePanel = new GhidraThreadedTablePanel<>(stringModel, 1000);
|
||||
table = threadedTablePanel.getTable();
|
||||
table.setPreferredScrollableViewportSize(new Dimension(350, 150));
|
||||
table.getSelectionModel().addListSelectionListener(e -> notifyContextChanged());
|
||||
table.getSelectionModel().addListSelectionListener(e -> {
|
||||
if (!e.getValueIsAdjusting()) {
|
||||
notifyContextChanged();
|
||||
}
|
||||
});
|
||||
|
||||
stringModel.addTableModelListener(e -> {
|
||||
int rowCount = stringModel.getRowCount();
|
||||
@@ -148,7 +149,7 @@ public class ViewStringsProvider extends ComponentProviderAdapter {
|
||||
}
|
||||
});
|
||||
TableColumn stringRepCol = table.getColumnModel()
|
||||
.getColumn(ViewStringsTableModel.COLUMNS.STRING_REP_COL.ordinal());
|
||||
.getColumn(DefinedStringsTableModel.COLUMNS.STRING_REP_COL.ordinal());
|
||||
|
||||
stringRepCol.setCellEditor(new StringRepCellEditor());
|
||||
|
||||
@@ -201,23 +202,23 @@ public class ViewStringsProvider extends ComponentProviderAdapter {
|
||||
return table;
|
||||
}
|
||||
|
||||
public ViewStringsTableModel getModel() {
|
||||
public DefinedStringsTableModel getModel() {
|
||||
return stringModel;
|
||||
}
|
||||
|
||||
private void doShowProgramLocation(ProgramLocation loc) {
|
||||
ProgramLocation realLoc = stringModel.findEquivProgramLocation(loc);
|
||||
if (realLoc != null) {
|
||||
int rowIndex = stringModel.getViewIndex(realLoc);
|
||||
if (rowIndex >= 0) {
|
||||
table.selectRow(rowIndex);
|
||||
table.scrollToSelectedRow();
|
||||
}
|
||||
else {
|
||||
getTool().setStatusInfo(
|
||||
"String at " + realLoc.getAddress() + " is filtered out of table view", false);
|
||||
}
|
||||
private void doShowProgramLocation(ProgramLocation pl) {
|
||||
ProgramLocation modelLocation = stringModel.findEquivProgramLocation(pl);
|
||||
if (modelLocation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newRow = stringModel.getViewIndex(modelLocation);
|
||||
if (newRow < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
table.selectRow(newRow);
|
||||
table.scrollToSelectedRow();
|
||||
}
|
||||
|
||||
public void showProgramLocation(ProgramLocation loc) {
|
||||
@@ -47,7 +47,7 @@ import ghidra.util.task.TaskMonitor;
|
||||
* This implementation keeps a local index of Address to row object (which are ProgramLocations)
|
||||
* so that DomainObjectChangedEvent events can be efficiently handled.
|
||||
*/
|
||||
class ViewStringsTableModel extends AddressBasedTableModel<ProgramLocation> {
|
||||
class DefinedStringsTableModel extends AddressBasedTableModel<ProgramLocation> {
|
||||
|
||||
private Map<Address, ProgramLocation> rowsIndexedByAddress = new HashMap<>();
|
||||
|
||||
@@ -66,7 +66,7 @@ class ViewStringsTableModel extends AddressBasedTableModel<ProgramLocation> {
|
||||
TRANSLATED_VALUE
|
||||
}
|
||||
|
||||
ViewStringsTableModel(PluginTool tool) {
|
||||
DefinedStringsTableModel(PluginTool tool) {
|
||||
super("Defined String Table", tool, null, null);
|
||||
}
|
||||
|
||||
@@ -136,9 +136,9 @@ class ViewStringsTableModel extends AddressBasedTableModel<ProgramLocation> {
|
||||
}
|
||||
|
||||
public void removeDataInstanceAt(Address addr) {
|
||||
ProgramLocation progLoc = rowsIndexedByAddress.get(addr);
|
||||
if (progLoc != null) {
|
||||
removeObject(progLoc);
|
||||
ProgramLocation pl = rowsIndexedByAddress.get(addr);
|
||||
if (pl != null) {
|
||||
removeObject(pl);
|
||||
rowsIndexedByAddress.remove(addr);
|
||||
}
|
||||
}
|
||||
@@ -149,17 +149,18 @@ class ViewStringsTableModel extends AddressBasedTableModel<ProgramLocation> {
|
||||
|
||||
public void addDataInstance(Program localProgram, Data data) {
|
||||
for (Data stringInstance : DefinedStringIterator.forDataInstance(data)) {
|
||||
addObject(createIndexedStringInstanceLocation(localProgram, stringInstance));
|
||||
ProgramLocation pl = createIndexedStringInstanceLocation(localProgram, stringInstance);
|
||||
addObject(pl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramSelection getProgramSelection(int[] rows) {
|
||||
AddressSet set = new AddressSet();
|
||||
for (int element : rows) {
|
||||
ProgramLocation progLoc = filteredData.get(element);
|
||||
Data data = getProgram().getListing().getDataContaining(progLoc.getAddress());
|
||||
data = data.getComponent(progLoc.getComponentPath());
|
||||
for (int row : rows) {
|
||||
ProgramLocation pl = filteredData.get(row);
|
||||
Data data = getProgram().getListing().getDataContaining(pl.getAddress());
|
||||
data = data.getComponent(pl.getComponentPath());
|
||||
set.addRange(data.getMinAddress(), data.getMaxAddress());
|
||||
}
|
||||
return new ProgramSelection(set);
|
||||
@@ -1011,6 +1011,10 @@ public class GTable extends JTable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls the selected row into the view center. This call will not scroll if the selected row
|
||||
* is already in the view.
|
||||
*/
|
||||
public void scrollToSelectedRow() {
|
||||
Container parent = getParent();
|
||||
if (!(parent instanceof JViewport viewport)) {
|
||||
@@ -1027,6 +1031,10 @@ public class GTable extends JTable {
|
||||
int row = selectedRows[0];
|
||||
Rectangle cellRect = getCellRect(row, 0, true);
|
||||
Rectangle visibleRect = getVisibleRect();
|
||||
if (visibleRect.contains(cellRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cellRect.x = visibleRect.x; // use the view x to prevent side scrolling
|
||||
cellRect.width = visibleRect.width;
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -22,15 +22,15 @@ import javax.swing.table.TableColumn;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.app.plugin.core.strings.ViewStringsProvider;
|
||||
import ghidra.app.plugin.core.strings.DefinedStringsProvider;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
|
||||
public class ViewStringsPluginScreenShots extends GhidraScreenShotGenerator {
|
||||
public class DefinedStringsPluginScreenShots extends GhidraScreenShotGenerator {
|
||||
|
||||
public ViewStringsPluginScreenShots() {
|
||||
public DefinedStringsPluginScreenShots() {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -82,14 +82,14 @@ public class ViewStringsPluginScreenShots extends GhidraScreenShotGenerator {
|
||||
|
||||
@Test
|
||||
public void testDefined_String_Table() {
|
||||
ViewStringsProvider provider = showProvider(ViewStringsProvider.class);
|
||||
DefinedStringsProvider provider = showProvider(DefinedStringsProvider.class);
|
||||
TableColumn addrCol = provider.getTable().getColumnModel().getColumn(0);
|
||||
addrCol.setMaxWidth(200);
|
||||
|
||||
TableColumn dataTypeCol = provider.getTable().getColumnModel().getColumn(3);
|
||||
dataTypeCol.setMaxWidth(200);
|
||||
|
||||
captureIsolatedProvider(ViewStringsProvider.class, 600, 300);
|
||||
captureIsolatedProvider(DefinedStringsProvider.class, 600, 300);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user