mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-5694 - Data Types - Updated the DataTypeQueryService to add more
useful method
This commit is contained in:
parent
d0c327973c
commit
6396a1a1e0
15 changed files with 251 additions and 66 deletions
|
@ -25,6 +25,7 @@ import ghidra.app.plugin.core.datamgr.archive.DefaultDataTypeArchiveService;
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
// FIXME!! TESTING
|
// FIXME!! TESTING
|
||||||
public class DefaultDataTypeManagerService extends DefaultDataTypeArchiveService
|
public class DefaultDataTypeManagerService extends DefaultDataTypeArchiveService
|
||||||
|
@ -64,6 +65,26 @@ public class DefaultDataTypeManagerService extends DefaultDataTypeArchiveService
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> getDataTypesByPath(DataTypePath path) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType getProgramDataTypeByPath(DataTypePath path) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType promptForDataType(String filterText) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> findDataTypes(String name, TaskMonitor monitor) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getDataType(TreePath selectedTreeNode) {
|
public DataType getDataType(TreePath selectedTreeNode) {
|
||||||
if (selectedTreeNode == null) {
|
if (selectedTreeNode == null) {
|
||||||
|
|
|
@ -84,7 +84,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
description = "Provides the window for managing and categorizing dataTypes. " +
|
description = "Provides the window for managing and categorizing dataTypes. " +
|
||||||
"The datatype display shows all built-in datatypes, datatypes in the " +
|
"The datatype display shows all built-in datatypes, datatypes in the " +
|
||||||
"current program, and datatypes in all open archives.",
|
"current program, and datatypes in all open archives.",
|
||||||
servicesProvided = { DataTypeManagerService.class, DataTypeArchiveService.class }
|
servicesProvided = { DataTypeManagerService.class, DataTypeQueryService.class, DataTypeArchiveService.class }
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class DataTypeManagerPlugin extends ProgramPlugin
|
public class DataTypeManagerPlugin extends ProgramPlugin
|
||||||
|
@ -519,6 +519,59 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getDataType(String filterText) {
|
public DataType getDataType(String filterText) {
|
||||||
|
return promptForDataType(filterText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> findDataTypes(String dtName, TaskMonitor monitor) {
|
||||||
|
List<DataType> results = new ArrayList<>();
|
||||||
|
DataTypeManager[] managers = getDataTypeManagers();
|
||||||
|
|
||||||
|
// we put the program's data types at the front of the list so clients can tell if the
|
||||||
|
// types we have found already exist in the program
|
||||||
|
DataTypeManager pdtm = getProgramDataTypeManager();
|
||||||
|
pdtm.findDataTypes(dtName, results);
|
||||||
|
for (DataTypeManager manager : managers) {
|
||||||
|
if (!(manager instanceof ProgramDataTypeManager)) {
|
||||||
|
manager.findDataTypes(dtName, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> getDataTypesByPath(DataTypePath path) {
|
||||||
|
List<DataType> results = new ArrayList<>();
|
||||||
|
DataTypeManager[] managers = getDataTypeManagers();
|
||||||
|
for (DataTypeManager manager : managers) {
|
||||||
|
DataType dt = manager.getDataType(path);
|
||||||
|
if (dt == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager instanceof ProgramDataTypeManager) {
|
||||||
|
// we put the program's data type at the front of the list so clients can tell if
|
||||||
|
// the types we have found already exist in the program
|
||||||
|
results.add(0, dt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
results.add(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType getProgramDataTypeByPath(DataTypePath path) {
|
||||||
|
DataTypeManager pdtm = getProgramDataTypeManager();
|
||||||
|
if (pdtm == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return pdtm.getDataType(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType promptForDataType(String filterText) {
|
||||||
DataTypeChooserDialog dialog = new DataTypeChooserDialog(this);
|
DataTypeChooserDialog dialog = new DataTypeChooserDialog(this);
|
||||||
if (!StringUtils.isBlank(filterText)) {
|
if (!StringUtils.isBlank(filterText)) {
|
||||||
dialog.showPrepopulatedDialog(tool, filterText);
|
dialog.showPrepopulatedDialog(tool, filterText);
|
||||||
|
|
|
@ -31,8 +31,7 @@ import ghidra.util.exception.VersionException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service that manages a set of data type archives, allowing re-use of already open
|
* A service that manages a set of data type archives, allowing re-use of already open archives.
|
||||||
* archives.
|
|
||||||
*/
|
*/
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@ServiceInfo(
|
@ServiceInfo(
|
||||||
|
@ -95,12 +94,12 @@ public interface DataTypeArchiveService {
|
||||||
* Opens the specified project-located data type archive.
|
* Opens the specified project-located data type archive.
|
||||||
*
|
*
|
||||||
* @param domainFile archive file located in the current project
|
* @param domainFile archive file located in the current project
|
||||||
* @param monitor {@link TaskMonitor} to display progess during the opening
|
* @param monitor {@link TaskMonitor} to display progress during the opening
|
||||||
* @return the data type archive
|
* @return the data type archive
|
||||||
* @throws IOException if an i/o error occurs opening the data type archive
|
* @throws IOException if an i/o error occurs opening the data type archive
|
||||||
* @throws DuplicateIdException if another archive with the same ID is already open
|
* @throws DuplicateIdException if another archive with the same ID is already open
|
||||||
* @throws VersionException
|
* @throws VersionException if there is a version exception
|
||||||
* @throws CancelledException
|
* @throws CancelledException if the user cancels
|
||||||
*/
|
*/
|
||||||
public DataTypeManager openArchive(DomainFile domainFile, TaskMonitor monitor)
|
public DataTypeManager openArchive(DomainFile domainFile, TaskMonitor monitor)
|
||||||
throws VersionException, CancelledException, IOException, DuplicateIdException;
|
throws VersionException, CancelledException, IOException, DuplicateIdException;
|
||||||
|
@ -128,5 +127,4 @@ public interface DataTypeArchiveService {
|
||||||
public Archive openArchive(File file, boolean acquireWriteLock)
|
public Archive openArchive(File file, boolean acquireWriteLock)
|
||||||
throws IOException, DuplicateIdException;
|
throws IOException, DuplicateIdException;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,16 @@ package ghidra.app.services;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.program.database.data.DataTypeUtilities;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplified datatype service interface to provide query capabilities
|
* Simplified datatype service interface to provide query capabilities to a set of open datatype
|
||||||
* to a set of open datatype managers
|
* managers.
|
||||||
|
*
|
||||||
|
* @see DataTypeUtilities
|
||||||
|
* @see DataTypeManagerService
|
||||||
*/
|
*/
|
||||||
public interface DataTypeQueryService {
|
public interface DataTypeQueryService {
|
||||||
|
|
||||||
|
@ -36,16 +41,59 @@ public interface DataTypeQueryService {
|
||||||
public List<DataType> getSortedDataTypeList();
|
public List<DataType> getSortedDataTypeList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain the preferred datatype which corresponds to the specified
|
* This method simply calls {@link #promptForDataType(String)}
|
||||||
* datatype specified by filterText. A tool-based service provider
|
* @deprecated use {@link #promptForDataType(String)}
|
||||||
* may prompt the user to select a datatype if more than one possibility
|
*/
|
||||||
* exists.
|
@SuppressWarnings("javadoc")
|
||||||
|
@Deprecated(since = "11.5", forRemoval = true)
|
||||||
|
public DataType getDataType(String filterText);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts the user for a data type. The optional filter text will be used to filter the tree
|
||||||
|
* of available types.
|
||||||
*
|
*
|
||||||
* @param filterText If not null, this text filters the visible data types to only show those
|
* @param filterText If not null, this text filters the visible data types to only show those
|
||||||
* that start with the given text
|
* that start with the given text
|
||||||
* @return the preferred data type (e.g., chosen by the user) or null if no match found
|
* @return the preferred data type (e.g., chosen by the user) or null if no match found
|
||||||
* or selection was cancelled by user.
|
* or selection was cancelled by user.
|
||||||
*/
|
*/
|
||||||
public DataType getDataType(String filterText);
|
public DataType promptForDataType(String filterText);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all data types matching the given name. This method will search all open data type
|
||||||
|
* archives.
|
||||||
|
* <p>
|
||||||
|
* Unlike {@link DataTypeManagerService#findDataTypes(String, TaskMonitor)}, this method will
|
||||||
|
* not return {@code .conflict} data types. If you need those types, then you must call each
|
||||||
|
* data type manager directly.
|
||||||
|
* <p>
|
||||||
|
* In the list of types returned, the program data type manager's types will be in the list
|
||||||
|
* before types from other archives.
|
||||||
|
*
|
||||||
|
* @param name the data type name to find
|
||||||
|
* @param monitor the task monitor
|
||||||
|
* @return the data types
|
||||||
|
* @see DataTypeManagerService#getDataTypeManagers()
|
||||||
|
*/
|
||||||
|
public List<DataType> findDataTypes(String name, TaskMonitor monitor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data type for the given data type path.
|
||||||
|
* <p>
|
||||||
|
* This method will check each open data type manager for a data type that matches the path.
|
||||||
|
* <p>
|
||||||
|
* If a type is in the program data type manager, then it will be first in the returned list.
|
||||||
|
*
|
||||||
|
* @param path the path
|
||||||
|
* @return the data type
|
||||||
|
*/
|
||||||
|
public List<DataType> getDataTypesByPath(DataTypePath path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data type for the given data type path from the program's data type manager.
|
||||||
|
* @param path the path
|
||||||
|
* @return the data type; null if the type does not exist
|
||||||
|
*/
|
||||||
|
public DataType getProgramDataTypeByPath(DataTypePath path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,17 +379,13 @@ public class DemangledDataType extends DemangledType {
|
||||||
static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace,
|
static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace,
|
||||||
String dtName) {
|
String dtName) {
|
||||||
|
|
||||||
// TODO: add support for use of Program.getPreferredRootNamespaceCategoryPath when
|
|
||||||
// searching for datatypes
|
|
||||||
|
|
||||||
List<DataType> list = new ArrayList<>();
|
List<DataType> list = new ArrayList<>();
|
||||||
dataTypeManager.findDataTypes(dtName, list);
|
dataTypeManager.findDataTypes(dtName, list);
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//use the datatype that exists in the root category,
|
// use the datatype that exists in the root category, otherwise just pick the first one
|
||||||
//otherwise just pick the first one...
|
|
||||||
DataType anyDt = null;
|
DataType anyDt = null;
|
||||||
DataType preferredDataType = null;
|
DataType preferredDataType = null;
|
||||||
for (DataType existingDT : list) {
|
for (DataType existingDT : list) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import ghidra.program.model.listing.FunctionSignature;
|
||||||
import ghidra.util.data.DataTypeParser;
|
import ghidra.util.data.DataTypeParser;
|
||||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for parsing function signatures. This class attempts to be much more
|
* Class for parsing function signatures. This class attempts to be much more
|
||||||
|
@ -353,9 +354,14 @@ public class FunctionSignatureParser {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getDataType(String filterText) {
|
public DataType getDataType(String filterText) {
|
||||||
|
return promptForDataType(filterText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType promptForDataType(String filterText) {
|
||||||
DataType dt = dtCache.get(filterText);
|
DataType dt = dtCache.get(filterText);
|
||||||
if (dt == null) {
|
if (dt == null) {
|
||||||
dt = service.getDataType(filterText);
|
dt = service.promptForDataType(filterText);
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
dtCache.put(filterText, dt);
|
dtCache.put(filterText, dt);
|
||||||
}
|
}
|
||||||
|
@ -363,5 +369,19 @@ public class FunctionSignatureParser {
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> getDataTypesByPath(DataTypePath path) {
|
||||||
|
return service.getDataTypesByPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType getProgramDataTypeByPath(DataTypePath path) {
|
||||||
|
return service.getProgramDataTypeByPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> findDataTypes(String name, TaskMonitor monitor) {
|
||||||
|
return service.findDataTypes(name, monitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,7 +379,6 @@ public class DataTypeParser {
|
||||||
|
|
||||||
// give up and ask the user
|
// give up and ask the user
|
||||||
return proptUserForType(baseName);
|
return proptUserForType(baseName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataType proptUserForType(String baseName) throws CancelledException {
|
private DataType proptUserForType(String baseName) throws CancelledException {
|
||||||
|
@ -388,7 +387,7 @@ public class DataTypeParser {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType dt = dataTypeManagerService.getDataType(baseName);
|
DataType dt = dataTypeManagerService.promptForDataType(baseName);
|
||||||
if (dt == null) {
|
if (dt == null) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
@ -483,7 +482,8 @@ public class DataTypeParser {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char n = nextIndex + 1 < dataTypeString.length() ? dataTypeString.charAt(nextIndex + 1) : '\0';
|
char n = nextIndex + 1 < dataTypeString.length() ? dataTypeString.charAt(nextIndex + 1)
|
||||||
|
: '\0';
|
||||||
if (c == ':' && n == ':') {
|
if (c == ':' && n == ':') {
|
||||||
nextIndex += 2;
|
nextIndex += 2;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -181,8 +181,8 @@ public class FavoritesAndMiscTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
List<DataType> dts = changeListener.getFavoriteDts();
|
List<DataType> dts = changeListener.getFavoriteDts();
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (int i = 0; i < dts.size(); i++) {
|
for (DataType dt : dts) {
|
||||||
if (dts.get(i).getName().equals("PascalUnicode")) {
|
if (dt.getName().equals("PascalUnicode")) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -198,8 +198,8 @@ public class FavoritesAndMiscTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
dts = changeListener.getFavoriteDts();
|
dts = changeListener.getFavoriteDts();
|
||||||
for (int i = 0; i < dts.size(); i++) {
|
for (DataType dt : dts) {
|
||||||
if (dts.get(i).getName().equals("MBCString")) {
|
if (dt.getName().equals("MBCString")) {
|
||||||
Assert.fail("Should not have found MBCString as a favorite!");
|
Assert.fail("Should not have found MBCString as a favorite!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +338,7 @@ public class FavoritesAndMiscTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
runSwing(() -> plugin.getDataType("ArrayStruct"), false);
|
runSwing(() -> plugin.promptForDataType("ArrayStruct"), false);
|
||||||
|
|
||||||
DataTypeChooserDialog d = waitForDialogComponent(DataTypeChooserDialog.class);
|
DataTypeChooserDialog d = waitForDialogComponent(DataTypeChooserDialog.class);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,11 @@ public class FunctionSignatureParserTest extends AbstractGhidraHeadedIntegration
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getDataType(String filterText) {
|
public DataType getDataType(String filterText) {
|
||||||
|
return promptForDataType(filterText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType promptForDataType(String filterText) {
|
||||||
// method only called if no results or multiple results were found.
|
// method only called if no results or multiple results were found.
|
||||||
// Tool based implementation will prompt user, test will pick last one
|
// Tool based implementation will prompt user, test will pick last one
|
||||||
ArrayList<DataType> list = new ArrayList<>();
|
ArrayList<DataType> list = new ArrayList<>();
|
||||||
|
|
|
@ -26,6 +26,7 @@ import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class DataManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
public class DataManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
@ -98,11 +99,17 @@ public class DataManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
dataMgr.resolve(new EnumDataType(s3.getCategoryPath(), "Enum", 2), null);
|
dataMgr.resolve(new EnumDataType(s3.getCategoryPath(), "Enum", 2), null);
|
||||||
dataMgr.resolve(new EnumDataType(s3.getCategoryPath(), "Enum", 2), null);
|
dataMgr.resolve(new EnumDataType(s3.getCategoryPath(), "Enum", 2), null);
|
||||||
|
|
||||||
ArrayList<DataType> list = new ArrayList<DataType>();
|
dataMgr.resolve(new EnumDataType(s3.getCategoryPath(), "zEnum", 2), null);
|
||||||
dataMgr.findDataTypes("Enum", list);
|
dataMgr.resolve(new EnumDataType(s3.getCategoryPath(), "zEnum2", 2), null);
|
||||||
|
|
||||||
|
List<DataType> list = new ArrayList<DataType>();
|
||||||
|
dataMgr.findDataTypes("Enum", list);
|
||||||
assertEquals(3, list.size());
|
assertEquals(3, list.size());
|
||||||
|
|
||||||
|
list.clear();
|
||||||
|
dataMgr.findDataTypes("Enum1", list);
|
||||||
|
Msg.debug(this, "dts: " + list);
|
||||||
|
|
||||||
Category c1 = root.createCategory("c1");
|
Category c1 = root.createCategory("c1");
|
||||||
dataMgr.resolve(new EnumDataType(c1.getCategoryPath(), "Enum", 2), null);
|
dataMgr.resolve(new EnumDataType(c1.getCategoryPath(), "Enum", 2), null);
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,26 @@ public class TestDoubleDataTypeManagerService implements DataTypeManagerService
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType promptForDataType(String filterText) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> getDataTypesByPath(DataTypePath path) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType getProgramDataTypeByPath(DataTypePath path) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DataType> findDataTypes(String name, TaskMonitor monitor) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataTypeManager getBuiltInDataTypesManager() {
|
public DataTypeManager getBuiltInDataTypesManager() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,11 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.framework.plugintool;
|
package ghidra.framework.plugintool;
|
||||||
|
|
||||||
|
import generic.json.Json;
|
||||||
|
|
||||||
public class ServiceInterfaceImplementationPair {
|
public class ServiceInterfaceImplementationPair {
|
||||||
public Class<?> interfaceClass;
|
public Class<?> interfaceClass;
|
||||||
public Object provider;
|
public Object provider;
|
||||||
|
|
||||||
public ServiceInterfaceImplementationPair(Class<?> interfaceClass, Object provider) {
|
public ServiceInterfaceImplementationPair(Class<?> interfaceClass, Object provider) {
|
||||||
this.interfaceClass = interfaceClass;
|
this.interfaceClass = interfaceClass;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Json.toString(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.help.UnsupportedOperationException;
|
import javax.help.UnsupportedOperationException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import db.*;
|
import db.*;
|
||||||
import db.util.ErrorHandler;
|
import db.util.ErrorHandler;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
|
@ -2098,32 +2100,37 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void findDataTypes(String name, List<DataType> list) {
|
public void findDataTypes(String name, List<DataType> list) {
|
||||||
if (name == null || name.length() == 0) {
|
if (StringUtils.isBlank(name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (name.equals(DataType.DEFAULT.getName())) {
|
if (name.equals(DataType.DEFAULT.getName())) {
|
||||||
list.add(DataType.DEFAULT);
|
list.add(DataType.DEFAULT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore .conflict in both name and result matches
|
// ignore .conflict in both name and result matches
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
try {
|
try {
|
||||||
buildSortedDataTypeList();
|
buildSortedDataTypeList();
|
||||||
// Use exemplar datatype in root category without .conflict to position at start
|
// Use exemplar datatype in root category without .conflict to position at start
|
||||||
// of possible matches
|
// of possible matches
|
||||||
name = DataTypeUtilities.getNameWithoutConflict(name);
|
String baseName = DataTypeUtilities.getNameWithoutConflict(name);
|
||||||
DataType compareDataType =
|
DataType compareDataType =
|
||||||
new TypedefDataType(CategoryPath.ROOT, name, DataType.DEFAULT, this);
|
new TypedefDataType(CategoryPath.ROOT, baseName, DataType.DEFAULT, this);
|
||||||
int index = Collections.binarySearch(sortedDataTypes, compareDataType, nameComparator);
|
int index = Collections.binarySearch(sortedDataTypes, compareDataType, nameComparator);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
// this allows us to find foo.conflict types
|
||||||
index = -index - 1;
|
index = -index - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add all matches to list
|
// add all matches to list
|
||||||
while (index < sortedDataTypes.size()) {
|
while (index < sortedDataTypes.size()) {
|
||||||
DataType dt = sortedDataTypes.get(index);
|
DataType dt = sortedDataTypes.get(index);
|
||||||
if (!name.equals(DataTypeUtilities.getNameWithoutConflict(dt, false))) {
|
String baseDtName = DataTypeUtilities.getNameWithoutConflict(dt, false);
|
||||||
break;
|
if (!baseName.equals(baseDtName)) {
|
||||||
|
break; // not foo or foo.conflict
|
||||||
}
|
}
|
||||||
|
|
||||||
list.add(dt);
|
list.add(dt);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
@ -2143,9 +2150,9 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
||||||
list.add(DataType.DEFAULT);
|
list.add(DataType.DEFAULT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (monitor == null) {
|
|
||||||
monitor = TaskMonitor.DUMMY;
|
monitor = TaskMonitor.dummyIfNull(monitor);
|
||||||
}
|
|
||||||
Pattern regexp = UserSearchUtils.createSearchPattern(name, caseSensitive);
|
Pattern regexp = UserSearchUtils.createSearchPattern(name, caseSensitive);
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -698,7 +698,7 @@ public class DataTypeUtilities {
|
||||||
* @param dtName datatype name
|
* @param dtName datatype name
|
||||||
* @param classConstraint type of datatype by its interface class (e.g., {@link Structure}).
|
* @param classConstraint type of datatype by its interface class (e.g., {@link Structure}).
|
||||||
* @param parentNamespacePreferred if true matching on parent namespace is
|
* @param parentNamespacePreferred if true matching on parent namespace is
|
||||||
* enabled and preferred over match on actual namespace. This is relavent for
|
* enabled and preferred over match on actual namespace. This is relevant for
|
||||||
* class structure searching.
|
* class structure searching.
|
||||||
* @return preferred datatype match if found
|
* @return preferred datatype match if found
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -169,11 +169,10 @@ public interface DataTypeManager {
|
||||||
public Iterator<FunctionDefinition> getAllFunctionDefinitions();
|
public Iterator<FunctionDefinition> getAllFunctionDefinitions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin searching at the root category for all data types with the
|
* Begin searching at the root category for all data types with the given name. Places all the
|
||||||
* given name. Places all the data types in this data type manager
|
* data types in this data type manager with the given name into the list. The presence of
|
||||||
* with the given name into the list. Presence of {@code .conflict}
|
* {@code .conflict} extension will be ignored and thus included in the results.
|
||||||
* extension will be ignored for both specified name and returned
|
*
|
||||||
* results.
|
|
||||||
* @param name name of the data type (wildcards are not supported and will be treated
|
* @param name name of the data type (wildcards are not supported and will be treated
|
||||||
* as explicit search characters)
|
* as explicit search characters)
|
||||||
* @param list list that will be populated with matching DataType objects
|
* @param list list that will be populated with matching DataType objects
|
||||||
|
@ -181,9 +180,13 @@ public interface DataTypeManager {
|
||||||
public void findDataTypes(String name, List<DataType> list);
|
public void findDataTypes(String name, List<DataType> list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin searching at the root category for all data types with names
|
* Begin searching at the root category for all data types with names that match the given name
|
||||||
* that match the given name that may contain wildcards using familiar globbing
|
* that may contain wildcards using familiar globbing characters '*' and '?'.
|
||||||
* characters '*' and '?'.
|
* <p>
|
||||||
|
* Unlike {@link #findDataTypes(String, List)}, data types with a {@code .conflict} extension
|
||||||
|
* will not be included in the results of this method unless they explicitly match the provided
|
||||||
|
* name.
|
||||||
|
*
|
||||||
* @param name name to match; may contain wildcards
|
* @param name name to match; may contain wildcards
|
||||||
* @param list list that will be populated with matching DataType objects
|
* @param list list that will be populated with matching DataType objects
|
||||||
* @param caseSensitive true if the match is case sensitive
|
* @param caseSensitive true if the match is case sensitive
|
||||||
|
@ -421,7 +424,7 @@ public interface DataTypeManager {
|
||||||
* transaction is ended.
|
* transaction is ended.
|
||||||
* <P>
|
* <P>
|
||||||
* NOTE: Use of rollback ({@code commit=false} should be avoided unless absolutely
|
* NOTE: Use of rollback ({@code commit=false} should be avoided unless absolutely
|
||||||
* neccessary since it will incur overhead to revert changes and may rollback multiple
|
* necessary since it will incur overhead to revert changes and may rollback multiple
|
||||||
* concurrent transactions if they exist.
|
* concurrent transactions if they exist.
|
||||||
* <P>
|
* <P>
|
||||||
* NOTE: If this manager is part of a larger {@link DomainObject} its transactions may become
|
* NOTE: If this manager is part of a larger {@link DomainObject} its transactions may become
|
||||||
|
@ -630,7 +633,7 @@ public interface DataTypeManager {
|
||||||
public SourceArchive getLocalSourceArchive();
|
public SourceArchive getLocalSourceArchive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the given data type and its dependencies so thier source archive is set to
|
* Change the given data type and its dependencies so their source archive is set to
|
||||||
* given archive. Only those data types not already associated with a source archive
|
* given archive. Only those data types not already associated with a source archive
|
||||||
* will be changed.
|
* will be changed.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue