mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
Minor refactor of table address retrieval and some options constants
This commit is contained in:
parent
7ddd8665b7
commit
5d58d61506
@ -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.
|
||||
@ -18,6 +18,7 @@ package ghidra;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import generic.theme.GColor;
|
||||
import ghidra.app.util.SearchConstants;
|
||||
import ghidra.framework.options.Options;
|
||||
|
||||
/**
|
||||
@ -82,13 +83,17 @@ public interface GhidraOptions {
|
||||
/**
|
||||
* Option for the max number of hits found in a search; the search
|
||||
* stops when it reaches this limit.
|
||||
* @deprecated use {@link SearchConstants#SEARCH_LIMIT_NAME}
|
||||
*/
|
||||
final String OPTION_SEARCH_LIMIT = "Search Limit";
|
||||
@Deprecated
|
||||
final String OPTION_SEARCH_LIMIT = SearchConstants.SEARCH_LIMIT_NAME;
|
||||
|
||||
/**
|
||||
* Options title the search category
|
||||
* @deprecated use {@link SearchConstants#SEARCH_OPTION_NAME}
|
||||
*/
|
||||
final String OPTION_SEARCH_TITLE = "Search";
|
||||
@Deprecated(since = "11.3", forRemoval = true)
|
||||
final String OPTION_SEARCH_TITLE = SearchConstants.SEARCH_OPTION_NAME;
|
||||
|
||||
/**
|
||||
* Category name for the "Auto Analysis" options.
|
||||
|
@ -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.
|
||||
@ -39,8 +39,10 @@ import ghidra.util.task.TaskMonitor;
|
||||
*/
|
||||
public class AddressRangeTableModel extends GhidraProgramTableModel<AddressRangeInfo> {
|
||||
|
||||
private ProgramSelection selection;
|
||||
private static final int MIN_ADDRESS_COLUMN_INDEX = 0;
|
||||
private static final int MAX_ADDRESS_COLUMN_INDEX = 1;
|
||||
|
||||
private ProgramSelection selection;
|
||||
private int resultsLimit;
|
||||
private long minLength;
|
||||
|
||||
@ -52,24 +54,6 @@ public class AddressRangeTableModel extends GhidraProgramTableModel<AddressRange
|
||||
this.minLength = minLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation(int modelRow, int modelColumn) {
|
||||
AddressRangeInfo rangeInfo = getRowObject(modelRow);
|
||||
if (modelColumn == MAX_ADDRESS_COLUMN_INDEX) {
|
||||
return new ProgramLocation(program, rangeInfo.max());
|
||||
}
|
||||
return new ProgramLocation(program, rangeInfo.min());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramSelection getProgramSelection(int[] modelRows) {
|
||||
AddressSet ranges = new AddressSet();
|
||||
for (AddressRangeInfo rangeInfo : getRowObjects(modelRows)) {
|
||||
ranges.addRange(program, rangeInfo.min(), rangeInfo.max());
|
||||
}
|
||||
return new ProgramSelection(program.getAddressFactory(), ranges);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoad(Accumulator<AddressRangeInfo> accumulator, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
@ -140,6 +124,42 @@ public class AddressRangeTableModel extends GhidraProgramTableModel<AddressRange
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation(int modelRow, int modelColumn) {
|
||||
AddressRangeInfo rangeInfo = getRowObject(modelRow);
|
||||
if (modelColumn == MAX_ADDRESS_COLUMN_INDEX) {
|
||||
return new ProgramLocation(program, rangeInfo.max());
|
||||
}
|
||||
return new ProgramLocation(program, rangeInfo.min());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramSelection getProgramSelection(int[] modelRows) {
|
||||
AddressSet ranges = new AddressSet();
|
||||
for (AddressRangeInfo rangeInfo : getRowObjects(modelRows)) {
|
||||
ranges.addRange(program, rangeInfo.min(), rangeInfo.max());
|
||||
}
|
||||
return new ProgramSelection(ranges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress(int modelRow) {
|
||||
AddressRangeInfo rangeInfo = getRowObject(modelRow);
|
||||
return rangeInfo.min();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress(int modelRow, int modelColumn) {
|
||||
AddressRangeInfo rangeInfo = getRowObject(modelRow);
|
||||
if (modelColumn == MIN_ADDRESS_COLUMN_INDEX) {
|
||||
return rangeInfo.min();
|
||||
}
|
||||
else if (modelColumn == MAX_ADDRESS_COLUMN_INDEX) {
|
||||
return rangeInfo.max();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class MinAddressTableColumn
|
||||
extends AbstractDynamicTableColumn<AddressRangeInfo, Address, Object> {
|
||||
|
||||
@ -235,20 +255,19 @@ public class AddressRangeTableModel extends GhidraProgramTableModel<AddressRange
|
||||
}
|
||||
}
|
||||
|
||||
private class NumRefsFromTableColumn
|
||||
extends AbstractDynamicTableColumn<AddressRangeInfo, Integer, Object> {
|
||||
private class NumRefsFromTableColumn
|
||||
extends AbstractDynamicTableColumn<AddressRangeInfo, Integer, Object> {
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "From References";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue(AddressRangeInfo rangeInfo, Settings settings, Object data,
|
||||
ServiceProvider services) throws IllegalArgumentException {
|
||||
return rangeInfo.numRefsFrom();
|
||||
}
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "From References";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue(AddressRangeInfo rangeInfo, Settings settings, Object data,
|
||||
ServiceProvider services) throws IllegalArgumentException {
|
||||
return rangeInfo.numRefsFrom();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
@ -17,7 +17,6 @@ package ghidra.app.plugin.core.gotoquery;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.events.*;
|
||||
import ghidra.app.nav.*;
|
||||
@ -67,7 +66,7 @@ public final class GoToServicePlugin extends ProgramPlugin {
|
||||
Options opt = tool.getOptions(SearchConstants.SEARCH_OPTION_NAME);
|
||||
|
||||
// we register this option here, since the other search plugins all depend on this service
|
||||
opt.registerOption(GhidraOptions.OPTION_SEARCH_LIMIT,
|
||||
opt.registerOption(SearchConstants.SEARCH_LIMIT_NAME,
|
||||
SearchConstants.DEFAULT_SEARCH_LIMIT, null,
|
||||
"The maximum number of search results.");
|
||||
|
||||
@ -90,7 +89,7 @@ public final class GoToServicePlugin extends ProgramPlugin {
|
||||
int getMaxHits() {
|
||||
Options opt = tool.getOptions(SearchConstants.SEARCH_OPTION_NAME);
|
||||
int maxSearchHits =
|
||||
opt.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
opt.getInt(SearchConstants.SEARCH_LIMIT_NAME, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
|
||||
return maxSearchHits;
|
||||
}
|
||||
|
@ -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.
|
||||
@ -23,6 +23,7 @@ import ghidra.GhidraOptions;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.ListingHighlightProvider;
|
||||
import ghidra.app.util.SearchConstants;
|
||||
import ghidra.app.util.viewer.field.ListingField;
|
||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||
import ghidra.framework.options.OptionsChangeListener;
|
||||
@ -39,7 +40,7 @@ class LocationReferencesHighlighter {
|
||||
private static final String MARKER_SET_DESCRIPTION = "Shows the location of references " +
|
||||
"currently displayed in the Location References window.";
|
||||
|
||||
private static final String OPTIONS_TITLE = GhidraOptions.OPTION_SEARCH_TITLE;
|
||||
private static final String OPTIONS_TITLE = SearchConstants.SEARCH_OPTION_NAME;
|
||||
private static final String HIGHLIGHT_COLOR_KEY =
|
||||
"Reference Search" + GhidraOptions.DELIMITER + "Highlight Match Color";
|
||||
private static final String HIGHLIGHT_COLOR_DESCRIPTION =
|
||||
|
@ -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.
|
||||
@ -200,14 +200,28 @@ public class FunctionReachabilityTableModel
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation(int row, int column) {
|
||||
FunctionReachabilityResult result = getRowObject(row);
|
||||
if (column == FROM_FUNCTION_COLUMN) {
|
||||
public Address getAddress(int modelRow, int modelColumn) {
|
||||
FunctionReachabilityResult result = getRowObject(modelColumn);
|
||||
if (modelColumn == FROM_FUNCTION_COLUMN) {
|
||||
Function function = result.getFromFunction();
|
||||
return function.getEntryPoint();
|
||||
}
|
||||
else if (modelColumn == TO_FUNCTION_COLUMN) {
|
||||
Function function = result.getToFunction();
|
||||
return function.getEntryPoint();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation(int modelRow, int modelColumn) {
|
||||
FunctionReachabilityResult result = getRowObject(modelRow);
|
||||
if (modelColumn == FROM_FUNCTION_COLUMN) {
|
||||
Function function = result.getFromFunction();
|
||||
Address address = function.getEntryPoint();
|
||||
return new ProgramLocation(getProgram(), address);
|
||||
}
|
||||
else if (column == TO_FUNCTION_COLUMN) {
|
||||
else if (modelColumn == TO_FUNCTION_COLUMN) {
|
||||
Function function = result.getToFunction();
|
||||
Address address = function.getEntryPoint();
|
||||
return new ProgramLocation(getProgram(), address);
|
||||
|
@ -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.
|
||||
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.searchtext;
|
||||
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.plugin.core.searchtext.Searcher.TextSearchResult;
|
||||
import ghidra.app.util.SearchConstants;
|
||||
import ghidra.app.util.query.ProgramLocationPreviewTableModel;
|
||||
@ -51,7 +50,7 @@ public abstract class AbstractSearchTableModel extends ProgramLocationPreviewTab
|
||||
this.options = options;
|
||||
Options opt = tool.getOptions(SearchConstants.SEARCH_OPTION_NAME);
|
||||
searchLimit =
|
||||
opt.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
opt.getInt(SearchConstants.SEARCH_LIMIT_NAME, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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.
|
||||
@ -31,7 +31,6 @@ import docking.tool.ToolConstants;
|
||||
import docking.widgets.fieldpanel.support.Highlight;
|
||||
import docking.widgets.table.threaded.*;
|
||||
import generic.theme.GIcon;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.*;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
@ -423,7 +422,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
||||
@Override
|
||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||
Object newValue) {
|
||||
if (optionName.equals(GhidraOptions.OPTION_SEARCH_LIMIT)) {
|
||||
if (optionName.equals(SearchConstants.SEARCH_LIMIT_NAME)) {
|
||||
int newSearchLimit = ((Integer) newValue).intValue();
|
||||
if (newSearchLimit <= 0) {
|
||||
throw new OptionsVetoException("Search limit must be greater than 0");
|
||||
@ -450,7 +449,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
||||
"The search result highlight color for the currently selected match");
|
||||
|
||||
searchLimit =
|
||||
opt.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
opt.getInt(SearchConstants.SEARCH_LIMIT_NAME, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
|
||||
doHighlight = opt.getBoolean(SearchConstants.SEARCH_HIGHLIGHT_NAME, true);
|
||||
|
||||
|
@ -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.
|
||||
@ -32,6 +32,12 @@ public interface SearchConstants {
|
||||
*/
|
||||
public static final String SEARCH_OPTION_NAME = "Search";
|
||||
|
||||
/**
|
||||
* Option for the max number of hits found in a search; the search
|
||||
* stops when it reaches this limit.
|
||||
*/
|
||||
public static final String SEARCH_LIMIT_NAME = "Search Limit";
|
||||
|
||||
/**
|
||||
* Option name for whether to highlight search results.
|
||||
*/
|
||||
|
@ -19,7 +19,6 @@ import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.plugin.core.gotoquery.GoToQueryResultsTableModel;
|
||||
import ghidra.app.plugin.core.navigation.NavigationOptions;
|
||||
@ -75,7 +74,7 @@ public class GoToQuery {
|
||||
|
||||
Options options = plugin.getTool().getOptions(SearchConstants.SEARCH_OPTION_NAME);
|
||||
this.maxHits =
|
||||
options.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
options.getInt(SearchConstants.SEARCH_LIMIT_NAME, SearchConstants.DEFAULT_SEARCH_LIMIT);
|
||||
this.fromAddress = fromAddr;
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package ghidra.features.base.memsearch.gui;
|
||||
|
||||
import static ghidra.GhidraOptions.*;
|
||||
import static ghidra.app.util.SearchConstants.*;
|
||||
|
||||
import ghidra.GhidraOptions;
|
||||
@ -113,7 +112,7 @@ public class MemorySearchOptions {
|
||||
private void searchOptionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||
Object newValue) {
|
||||
|
||||
if (optionName.equals(OPTION_SEARCH_LIMIT)) {
|
||||
if (optionName.equals(SEARCH_LIMIT_NAME)) {
|
||||
int limit = (int) newValue;
|
||||
if (limit <= 0) {
|
||||
throw new OptionsVetoException("Search limit must be greater than 0");
|
||||
@ -125,7 +124,7 @@ public class MemorySearchOptions {
|
||||
}
|
||||
|
||||
private void loadSearchOptions(ToolOptions options) {
|
||||
searchLimit = options.getInt(OPTION_SEARCH_LIMIT, DEFAULT_SEARCH_LIMIT);
|
||||
searchLimit = options.getInt(SEARCH_LIMIT_NAME, DEFAULT_SEARCH_LIMIT);
|
||||
highlightMatches = options.getBoolean(SEARCH_HIGHLIGHT_NAME, true);
|
||||
autoRestrictSelection = options.getBoolean(AUTO_RESTRICT_SELECTION, true);
|
||||
prepopulateSearch = options.getBoolean(PRE_POPULATE_MEM_SEARCH, true);
|
||||
|
@ -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.
|
||||
@ -15,17 +15,15 @@
|
||||
*/
|
||||
package ghidra.util.table;
|
||||
|
||||
import docking.widgets.table.*;
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.util.table.field.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* This class is now just a shell left in place to not break external clients.
|
||||
*
|
||||
* @param <ROW_TYPE> the row type
|
||||
*/
|
||||
public abstract class AddressBasedTableModel<ROW_TYPE> extends GhidraProgramTableModel<ROW_TYPE> {
|
||||
|
||||
public AddressBasedTableModel(String title, ServiceProvider serviceProvider, Program program,
|
||||
@ -37,100 +35,4 @@ public abstract class AddressBasedTableModel<ROW_TYPE> extends GhidraProgramTabl
|
||||
TaskMonitor monitor, boolean loadIncrementally) {
|
||||
super(title, serviceProvider, program, monitor, loadIncrementally);
|
||||
}
|
||||
|
||||
public abstract Address getAddress(int row);
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
// We create an untyped column descriptor. However, we are assigning it to a typed variable,
|
||||
// which guarantees that we only put homogeneous objects into the descriptor.
|
||||
@Override
|
||||
protected TableColumnDescriptor<ROW_TYPE> createTableColumnDescriptor() {
|
||||
TableColumnDescriptor<ROW_TYPE> descriptor = new TableColumnDescriptor();
|
||||
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn()), 1, true);
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new LabelTableColumn()));
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new CodeUnitTableColumn()));
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation(int row, int column) {
|
||||
if (row < 0 || row >= filteredData.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ROW_TYPE rowObject = filteredData.get(row);
|
||||
DynamicTableColumn<ROW_TYPE, ?, ?> tableColumn = getColumn(column);
|
||||
if (tableColumn instanceof ProgramLocationTableColumn<?, ?>) {
|
||||
|
||||
@SuppressWarnings("unchecked") // we checked
|
||||
ProgramLocationTableColumn<ROW_TYPE, ?> programField =
|
||||
(ProgramLocationTableColumn<ROW_TYPE, ?>) tableColumn;
|
||||
ProgramLocation loc = programField.getProgramLocation(rowObject,
|
||||
getColumnSettings(column), getProgram(), serviceProvider);
|
||||
if (loc != null) {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
|
||||
Address address = getAddress(row, column);
|
||||
if (address != null) {
|
||||
return new ProgramLocation(getProgram(), address);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Address getAddress(int row, int column) {
|
||||
DynamicTableColumn<ROW_TYPE, ?, ?> tableColumn = getColumn(column);
|
||||
|
||||
if (tableColumn instanceof ProgramLocationTableColumn<?, ?>) {
|
||||
@SuppressWarnings("unchecked")
|
||||
// we checked
|
||||
ProgramLocationTableColumn<ROW_TYPE, ?> programLocationColumn =
|
||||
(ProgramLocationTableColumn<ROW_TYPE, ?>) tableColumn;
|
||||
Settings settings = getColumnSettings(column);
|
||||
ROW_TYPE rowObject = filteredData.get(row);
|
||||
Object value =
|
||||
programLocationColumn.getValue(rowObject, settings, getProgram(), serviceProvider);
|
||||
if (value instanceof Address) {
|
||||
return (Address) value;
|
||||
}
|
||||
|
||||
if (value instanceof ProgramLocation) {
|
||||
ProgramLocation programLocation = (ProgramLocation) value;
|
||||
return programLocation.getByteAddress();
|
||||
}
|
||||
|
||||
ProgramLocation location = programLocationColumn.getProgramLocation(rowObject, settings,
|
||||
getProgram(), serviceProvider);
|
||||
if (location != null) {
|
||||
return location.getByteAddress();
|
||||
}
|
||||
}
|
||||
|
||||
ROW_TYPE storageValue = filteredData.get(row);
|
||||
Object columnValueForRow = getColumnValueForRow(storageValue, column);
|
||||
if (columnValueForRow instanceof Address) {
|
||||
return (Address) columnValueForRow;
|
||||
}
|
||||
return getAddress(row); // TODO Perhaps this should return null?
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramSelection getProgramSelection(int[] rows) {
|
||||
AddressSet addressSet = new AddressSet();
|
||||
for (int element : rows) {
|
||||
Address addr = getAddress(element);
|
||||
if (addr.isMemoryAddress()) {
|
||||
addressSet.addRange(addr, addr);
|
||||
}
|
||||
}
|
||||
return new ProgramSelection(addressSet);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
@ -15,10 +15,16 @@
|
||||
*/
|
||||
package ghidra.util.table;
|
||||
|
||||
import docking.widgets.table.*;
|
||||
import docking.widgets.table.threaded.ThreadedTableModel;
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.util.table.field.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public abstract class GhidraProgramTableModel<ROW_TYPE>
|
||||
@ -37,6 +43,23 @@ public abstract class GhidraProgramTableModel<ROW_TYPE>
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
// We create an untyped column descriptor. However, we are assigning it to a typed variable,
|
||||
// which guarantees that we only put homogeneous objects into the descriptor.
|
||||
@Override
|
||||
protected TableColumnDescriptor<ROW_TYPE> createTableColumnDescriptor() {
|
||||
TableColumnDescriptor<ROW_TYPE> descriptor = new TableColumnDescriptor();
|
||||
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn()), 1, true);
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new LabelTableColumn()));
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new CodeUnitTableColumn()));
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public void setProgram(Program program) {
|
||||
Program originalProgram = this.program;
|
||||
this.program = program;
|
||||
@ -66,14 +89,155 @@ public abstract class GhidraProgramTableModel<ROW_TYPE>
|
||||
return getProgram();
|
||||
}
|
||||
|
||||
// most subclasses will override this to return an address
|
||||
public Address getAddress(int row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
program = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an address for the given row and column.
|
||||
* @param modelRow the model row
|
||||
* @param modelColumn the column row
|
||||
* @return the address
|
||||
*/
|
||||
public Address getAddress(int modelRow, int modelColumn) {
|
||||
|
||||
//
|
||||
// Try to find an address for the given cell.
|
||||
//
|
||||
// 1) Prefer columns that have a ProgramLocation, as they are already used for navigation.
|
||||
//
|
||||
ROW_TYPE rowObject = filteredData.get(modelRow);
|
||||
DynamicTableColumn<ROW_TYPE, ?, ?> tableColumn = getColumn(modelColumn);
|
||||
if (tableColumn instanceof ProgramLocationTableColumn<?, ?>) {
|
||||
@SuppressWarnings("unchecked")
|
||||
// we checked
|
||||
ProgramLocationTableColumn<ROW_TYPE, ?> programLocationColumn =
|
||||
(ProgramLocationTableColumn<ROW_TYPE, ?>) tableColumn;
|
||||
Settings settings = getColumnSettings(modelColumn);
|
||||
Object value =
|
||||
programLocationColumn.getValue(rowObject, settings, getProgram(), serviceProvider);
|
||||
if (value instanceof Address) {
|
||||
return (Address) value;
|
||||
}
|
||||
|
||||
if (value instanceof ProgramLocation) {
|
||||
ProgramLocation programLocation = (ProgramLocation) value;
|
||||
return programLocation.getByteAddress();
|
||||
}
|
||||
|
||||
ProgramLocation location = programLocationColumn.getProgramLocation(rowObject, settings,
|
||||
getProgram(), serviceProvider);
|
||||
if (location != null) {
|
||||
return location.getByteAddress();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 2) See if the given cell value is an Address
|
||||
//
|
||||
Object columnValue = getColumnValueForRow(rowObject, modelColumn);
|
||||
if (columnValue instanceof Address) {
|
||||
return (Address) columnValue;
|
||||
}
|
||||
|
||||
//
|
||||
// 3) Check to see if we can get an Address directly from my row object
|
||||
//
|
||||
Address address = getAddress(modelRow);
|
||||
if (address != null) {
|
||||
return address;
|
||||
}
|
||||
|
||||
//
|
||||
// 4) Check for the case where we are using a mapped column that converted the current row
|
||||
// object into an Address row object.
|
||||
//
|
||||
Object mappedRowObject = getMappedRowObject(tableColumn, rowObject, modelColumn);
|
||||
if (mappedRowObject instanceof Address) {
|
||||
return (Address) mappedRowObject;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the best Address for the given row.
|
||||
* <P>
|
||||
* Implementation Note: this class will only return an Address if this model's row type is
|
||||
* Address. Clients that know how to get an Address for a given row should override this
|
||||
* method.
|
||||
* @param modelRow the row
|
||||
* @return the Address or null
|
||||
*/
|
||||
public Address getAddress(int modelRow) {
|
||||
ROW_TYPE rowObject = filteredData.get(modelRow);
|
||||
if (rowObject instanceof Address) {
|
||||
return (Address) rowObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given column supports row mapping, then use that column to get the mapped row. In
|
||||
* this case, our table may have a row object, like Function, that the column maps to another
|
||||
* type that it needs, like Address.
|
||||
*
|
||||
* @param tableColumn the table column
|
||||
* @param currentRowObject the table's actual non-mapped row value
|
||||
* @param columnIndex the column index
|
||||
* @return the mapped row value or null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object getMappedRowObject(DynamicTableColumn<ROW_TYPE, ?, ?> tableColumn,
|
||||
ROW_TYPE currentRowObject, int columnIndex) {
|
||||
|
||||
if (tableColumn instanceof MappedTableColumn) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
MappedTableColumn mappedColumn = (MappedTableColumn) tableColumn;
|
||||
return mappedColumn.map(currentRowObject, getProgram(), serviceProvider);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation(int modelRow, int modelColumn) {
|
||||
if (modelRow < 0 || modelRow >= filteredData.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ROW_TYPE rowObject = filteredData.get(modelRow);
|
||||
DynamicTableColumn<ROW_TYPE, ?, ?> tableColumn = getColumn(modelColumn);
|
||||
if (tableColumn instanceof ProgramLocationTableColumn<?, ?>) {
|
||||
|
||||
@SuppressWarnings("unchecked") // we checked
|
||||
ProgramLocationTableColumn<ROW_TYPE, ?> programField =
|
||||
(ProgramLocationTableColumn<ROW_TYPE, ?>) tableColumn;
|
||||
ProgramLocation loc = programField.getProgramLocation(rowObject,
|
||||
getColumnSettings(modelColumn), getProgram(), serviceProvider);
|
||||
if (loc != null) {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
|
||||
Address address = getAddress(modelRow, modelColumn);
|
||||
if (address != null) {
|
||||
return new ProgramLocation(getProgram(), address);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramSelection getProgramSelection(int[] modelRows) {
|
||||
AddressSet addressSet = new AddressSet();
|
||||
for (int element : modelRows) {
|
||||
Address addr = getAddress(element);
|
||||
if (addr.isMemoryAddress()) {
|
||||
addressSet.addRange(addr, addr);
|
||||
}
|
||||
}
|
||||
return new ProgramSelection(addressSet);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import docking.widgets.combobox.GhidraComboBox;
|
||||
import docking.widgets.table.GTable;
|
||||
import docking.widgets.table.threaded.GThreadedTablePanel;
|
||||
import generic.test.TestUtils;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.cmd.data.CreateDataCmd;
|
||||
import ghidra.app.cmd.label.AddLabelCmd;
|
||||
import ghidra.app.cmd.label.CreateNamespacesCmd;
|
||||
@ -570,7 +569,7 @@ public class GoToAddressLabelPluginTest extends AbstractGhidraHeadedIntegrationT
|
||||
public void testQueryResultsMaxHitsDynamicFound() throws Exception {
|
||||
loadProgram("x86");
|
||||
Options opt = plugin.getTool().getOptions(SearchConstants.SEARCH_OPTION_NAME);
|
||||
opt.setInt(GhidraOptions.OPTION_SEARCH_LIMIT, 20);
|
||||
opt.setInt(SearchConstants.SEARCH_LIMIT_NAME, 20);
|
||||
|
||||
setText("L*");
|
||||
performOkCallback();
|
||||
@ -582,7 +581,7 @@ public class GoToAddressLabelPluginTest extends AbstractGhidraHeadedIntegrationT
|
||||
public void testQueryResultsMaxHitsDefinedFound() throws Exception {
|
||||
loadProgram("x86");
|
||||
Options opt = plugin.getTool().getOptions(SearchConstants.SEARCH_OPTION_NAME);
|
||||
opt.setInt(GhidraOptions.OPTION_SEARCH_LIMIT, 5);
|
||||
opt.setInt(SearchConstants.SEARCH_LIMIT_NAME, 5);
|
||||
|
||||
createLabel("1006960", "abc1");
|
||||
createLabel("1006961", "abc2");
|
||||
|
@ -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.
|
||||
@ -124,16 +124,16 @@ public class MappedTableColumn<ROW_TYPE, EXPECTED_ROW_TYPE, COLUMN_TYPE, DATA_SO
|
||||
public COLUMN_TYPE getValue(ROW_TYPE rowObject, Settings settings, DATA_SOURCE data,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
|
||||
if (rowObject == null) {
|
||||
// can happen when the model is cleared out from under Swing
|
||||
return null;
|
||||
}
|
||||
EXPECTED_ROW_TYPE mappedRowObject = map(rowObject, data, serviceProvider);
|
||||
return tableColumn.getValue(mappedRowObject, settings, data, serviceProvider);
|
||||
}
|
||||
|
||||
EXPECTED_ROW_TYPE mappedObject = mapper.map(rowObject, data, serviceProvider);
|
||||
if (mappedObject == null) {
|
||||
return null; // some mappers have null data
|
||||
public EXPECTED_ROW_TYPE map(ROW_TYPE rowObject, DATA_SOURCE data,
|
||||
ServiceProvider serviceProvider) {
|
||||
if (rowObject == null) {
|
||||
return null;// can happen when the model is cleared out from under Swing
|
||||
}
|
||||
return tableColumn.getValue(mappedObject, settings, data, serviceProvider);
|
||||
return mapper.map(rowObject, data, serviceProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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.
|
||||
@ -27,10 +27,10 @@ import docking.ComponentProvider;
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.widgets.combobox.GhidraComboBox;
|
||||
import docking.widgets.table.threaded.ThreadedTableModel;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.plugin.core.searchtext.SearchTextPlugin;
|
||||
import ghidra.app.plugin.core.string.StringTableProvider;
|
||||
import ghidra.app.plugin.core.table.TableComponentProvider;
|
||||
import ghidra.app.util.SearchConstants;
|
||||
|
||||
/**
|
||||
* Captures screenshots associated with Memory Search.
|
||||
@ -160,7 +160,7 @@ public class SearchScreenShots extends AbstractSearchScreenShots {
|
||||
// custom program we've loaded. Also, we are NOT changing the option so that dialog
|
||||
// that is shown will have the default value
|
||||
searchPlugin = env.getPlugin(SearchTextPlugin.class);
|
||||
searchPlugin.optionsChanged(null, GhidraOptions.OPTION_SEARCH_LIMIT, null, 10);
|
||||
searchPlugin.optionsChanged(null, SearchConstants.SEARCH_LIMIT_NAME, null, 10);
|
||||
|
||||
performAction("Search Text", "SearchTextPlugin", false);
|
||||
waitForSwing();
|
||||
|
Loading…
Reference in New Issue
Block a user