mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-2687 - Filter modules used by using the classpath
This commit is contained in:
parent
843aee1df1
commit
98927d7e4e
13 changed files with 288 additions and 321 deletions
|
@ -36,7 +36,6 @@ import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.framework.plugintool.util.PluginException;
|
import ghidra.framework.plugintool.util.PluginException;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.TaskUtilities;
|
import ghidra.util.TaskUtilities;
|
||||||
import ghidra.util.exception.AssertException;
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
import utility.application.ApplicationLayout;
|
import utility.application.ApplicationLayout;
|
||||||
|
|
||||||
|
@ -44,21 +43,14 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
extends AbstractGhidraHeadlessIntegrationTest {
|
extends AbstractGhidraHeadlessIntegrationTest {
|
||||||
|
|
||||||
public AbstractGhidraHeadedIntegrationTest() {
|
public AbstractGhidraHeadedIntegrationTest() {
|
||||||
super();
|
|
||||||
|
|
||||||
// Ensure that all headed tests use swing popups when displaying errors. Setting this
|
// Ensure that all headed tests use swing popups when displaying errors. Setting this
|
||||||
// to false would force errors to only be written to the console.
|
// to false would force errors to only be written to the console.
|
||||||
setErrorGUIEnabled(true);
|
setErrorGUIEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ApplicationLayout createApplicationLayout() {
|
protected ApplicationLayout createApplicationLayout() throws IOException {
|
||||||
try {
|
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
||||||
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new AssertException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,7 +62,7 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flushes the given program's events before waiting for the swing update manager
|
* Flushes the given program's events before waiting for the swing update manager
|
||||||
*
|
*
|
||||||
* @param program The program whose events will be flushed; may be null
|
* @param program The program whose events will be flushed; may be null
|
||||||
*/
|
*/
|
||||||
public static void waitForProgram(Program program) {
|
public static void waitForProgram(Program program) {
|
||||||
|
@ -84,11 +76,11 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
/**
|
/**
|
||||||
* Adds the given plugin to the tool and then returns the instance of the plugin that was
|
* Adds the given plugin to the tool and then returns the instance of the plugin that was
|
||||||
* added
|
* added
|
||||||
*
|
*
|
||||||
* @param tool the tool
|
* @param tool the tool
|
||||||
* @param c the class of the plugin to add
|
* @param c the class of the plugin to add
|
||||||
* @return the newly added plugin
|
* @return the newly added plugin
|
||||||
* @throws PluginException if the plugin could not be constructed, or there was problem
|
* @throws PluginException if the plugin could not be constructed, or there was problem
|
||||||
* executing its init() method, or if a plugin of this class already exists in the tool
|
* executing its init() method, or if a plugin of this class already exists in the tool
|
||||||
*/
|
*/
|
||||||
public static <T extends Plugin> T addPlugin(PluginTool tool, Class<T> c)
|
public static <T extends Plugin> T addPlugin(PluginTool tool, Class<T> c)
|
||||||
|
@ -122,9 +114,9 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the given DialogComponentProvider using the given tool's
|
* Shows the given DialogComponentProvider using the given tool's
|
||||||
* {@link PluginTool#showDialog(DialogComponentProvider)} method.
|
* {@link PluginTool#showDialog(DialogComponentProvider)} method.
|
||||||
*
|
*
|
||||||
* @param tool The tool used to show the given provider.
|
* @param tool The tool used to show the given provider.
|
||||||
* @param provider The DialogComponentProvider to show.
|
* @param provider The DialogComponentProvider to show.
|
||||||
* @return The provider once it has been shown, or null if the provider is not shown within
|
* @return The provider once it has been shown, or null if the provider is not shown within
|
||||||
|
@ -143,7 +135,7 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for the tool to finish executing commands and tasks
|
* Waits for the tool to finish executing commands and tasks
|
||||||
*
|
*
|
||||||
* @param tool the tool
|
* @param tool the tool
|
||||||
* @throws AssertionFailedError if the tool does not finish work within a reasonable limit
|
* @throws AssertionFailedError if the tool does not finish work within a reasonable limit
|
||||||
*/
|
*/
|
||||||
|
@ -171,8 +163,8 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the given tool to the project tool chest. If the tool already exists, then it will
|
* Save the given tool to the project tool chest. If the tool already exists, then it will
|
||||||
* be overwritten with the given tool.
|
* be overwritten with the given tool.
|
||||||
*
|
*
|
||||||
* @param project The project which with the tool is associated.
|
* @param project The project which with the tool is associated.
|
||||||
* @param tool The tool to be saved
|
* @param tool The tool to be saved
|
||||||
* @return the new tool
|
* @return the new tool
|
||||||
|
@ -194,9 +186,9 @@ public abstract class AbstractGhidraHeadedIntegrationTest
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers a browser click at the current cursor location. Thus, this method should be
|
* Triggers a browser click at the current cursor location. Thus, this method should be
|
||||||
* called only after the browser location is set the the desired field.
|
* called only after the browser location is set the the desired field.
|
||||||
*
|
*
|
||||||
* @param codeBrowser the CodeBrowserPlugin
|
* @param codeBrowser the CodeBrowserPlugin
|
||||||
* @param clickCount the click count
|
* @param clickCount the click count
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -46,7 +46,6 @@ import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
import ghidra.util.exception.AssertException;
|
|
||||||
import ghidra.util.exception.RollbackException;
|
import ghidra.util.exception.RollbackException;
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
import utility.application.ApplicationLayout;
|
import utility.application.ApplicationLayout;
|
||||||
|
@ -75,13 +74,8 @@ public abstract class AbstractGhidraHeadlessIntegrationTest extends AbstractDock
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ApplicationLayout createApplicationLayout() {
|
protected ApplicationLayout createApplicationLayout() throws IOException {
|
||||||
try {
|
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
||||||
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new AssertException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.server.remote;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import ghidra.framework.ApplicationProperties;
|
import ghidra.framework.ApplicationProperties;
|
||||||
|
@ -27,14 +26,14 @@ import utility.application.ApplicationUtilities;
|
||||||
import utility.module.ModuleUtilities;
|
import utility.module.ModuleUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Ghidra server application layout defines the customizable elements of the Ghidra
|
* The Ghidra server application layout defines the customizable elements of the Ghidra
|
||||||
* server application's directory structure.
|
* server application's directory structure.
|
||||||
*/
|
*/
|
||||||
public class GhidraServerApplicationLayout extends ApplicationLayout {
|
public class GhidraServerApplicationLayout extends ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Ghidra server application layout object.
|
* Constructs a new Ghidra server application layout object.
|
||||||
*
|
*
|
||||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||||
* @throws IOException if there was a problem getting the application properties.
|
* @throws IOException if there was a problem getting the application properties.
|
||||||
*/
|
*/
|
||||||
|
@ -61,7 +60,7 @@ public class GhidraServerApplicationLayout extends ApplicationLayout {
|
||||||
|
|
||||||
// Modules - required to find module data files
|
// Modules - required to find module data files
|
||||||
modules = ModuleUtilities.findModules(applicationRootDirs,
|
modules = ModuleUtilities.findModules(applicationRootDirs,
|
||||||
ModuleUtilities.findModuleRootDirectories(applicationRootDirs, new ArrayList<>()));
|
ModuleUtilities.findModuleRootDirectories(applicationRootDirs));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
package docking.framework;
|
package docking.framework;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.framework.ApplicationProperties;
|
import ghidra.framework.ApplicationProperties;
|
||||||
|
@ -24,10 +25,11 @@ import ghidra.util.SystemUtilities;
|
||||||
import util.CollectionUtils;
|
import util.CollectionUtils;
|
||||||
import utility.application.ApplicationLayout;
|
import utility.application.ApplicationLayout;
|
||||||
import utility.application.ApplicationUtilities;
|
import utility.application.ApplicationUtilities;
|
||||||
|
import utility.module.ClasspathFilter;
|
||||||
import utility.module.ModuleUtilities;
|
import utility.module.ModuleUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The docking application layout defines the customizable elements of a docking application's
|
* The docking application layout defines the customizable elements of a docking application's
|
||||||
* directory structure.
|
* directory structure.
|
||||||
*/
|
*/
|
||||||
public class DockingApplicationLayout extends ApplicationLayout {
|
public class DockingApplicationLayout extends ApplicationLayout {
|
||||||
|
@ -36,7 +38,7 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new docking application layout object with the given name and version.
|
* Constructs a new docking application layout object with the given name and version.
|
||||||
*
|
*
|
||||||
* @param name The name of the application.
|
* @param name The name of the application.
|
||||||
* @param version The version of the application.
|
* @param version The version of the application.
|
||||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||||
|
@ -48,7 +50,7 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
||||||
/**
|
/**
|
||||||
* Constructs a new docking application layout object with the given set of application
|
* Constructs a new docking application layout object with the given set of application
|
||||||
* properties. The default Ghidra application root directory(s) will be used.
|
* properties. The default Ghidra application root directory(s) will be used.
|
||||||
*
|
*
|
||||||
* @param applicationProperties The properties object that will be read system properties.
|
* @param applicationProperties The properties object that will be read system properties.
|
||||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||||
*/
|
*/
|
||||||
|
@ -60,9 +62,9 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
||||||
/**
|
/**
|
||||||
* Constructs a new docking application layout object with the given set of application
|
* Constructs a new docking application layout object with the given set of application
|
||||||
* properties.
|
* properties.
|
||||||
*
|
*
|
||||||
* @param applicationRootDirs list of application root directories which should be
|
* @param applicationRootDirs list of application root directories which should be
|
||||||
* used to idenitfy modules and resources. The first entry will be treated as the
|
* used to identify modules and resources. The first entry will be treated as the
|
||||||
* installation root.
|
* installation root.
|
||||||
* @param applicationProperties The properties object that will be read system properties.
|
* @param applicationProperties The properties object that will be read system properties.
|
||||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||||
|
@ -81,8 +83,14 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
if (SystemUtilities.isInDevelopmentMode()) {
|
if (SystemUtilities.isInDevelopmentMode()) {
|
||||||
|
|
||||||
|
// In development mode we rely on the IDE's classpath to determine which modules to
|
||||||
|
// include, as opposed to scanning the filesystem. This prevents unrelated modules
|
||||||
|
// from being used.
|
||||||
|
|
||||||
modules = ModuleUtilities.findModules(applicationRootDirs,
|
modules = ModuleUtilities.findModules(applicationRootDirs,
|
||||||
ModuleUtilities.findModuleRootDirectories(applicationRootDirs, new ArrayList<>()));
|
ModuleUtilities.findModuleRootDirectories(applicationRootDirs),
|
||||||
|
new ClasspathFilter());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
modules = ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs);
|
modules = ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs);
|
||||||
|
@ -95,10 +103,10 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default list of Application directories. In repo-based
|
* Get the default list of Application directories. In repo-based
|
||||||
* development mode this includes the root Ghidra directory within each repo.
|
* development mode this includes the root Ghidra directory within each repo.
|
||||||
* When not in development mode, the requirement is that the current working
|
* When not in development mode, the requirement is that the current working
|
||||||
* directory correspond to the installation root. The first entry will be
|
* directory correspond to the installation root. The first entry will be
|
||||||
* the primary root in both cases.
|
* the primary root in both cases.
|
||||||
* @return root directories
|
* @return root directories
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -76,8 +76,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
new TestFailingErrorDisplayWrapper();
|
new TestFailingErrorDisplayWrapper();
|
||||||
|
|
||||||
public AbstractDockingTest() {
|
public AbstractDockingTest() {
|
||||||
super();
|
|
||||||
|
|
||||||
installNonNativeSystemClipboard();
|
installNonNativeSystemClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,13 +108,8 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ApplicationLayout createApplicationLayout() {
|
protected ApplicationLayout createApplicationLayout() throws IOException {
|
||||||
try {
|
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
||||||
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new AssertException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -445,7 +438,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
/**
|
/**
|
||||||
* A convenience method to close all of the windows and frames that the current Java
|
* A convenience method to close all of the windows and frames that the current Java
|
||||||
* windowing environment knows about
|
* windowing environment knows about
|
||||||
*
|
*
|
||||||
* @deprecated instead call the new {@link #closeAllWindows()}
|
* @deprecated instead call the new {@link #closeAllWindows()}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -727,11 +720,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
T t = windowManager.getComponentProvider(clazz);
|
T t = windowManager.getComponentProvider(clazz);
|
||||||
if (t != null) {
|
return t;
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1167,10 +1156,10 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
* If you do not know the owner name, then use
|
* If you do not know the owner name, then use
|
||||||
* the call {@link #getActionsByName(Tool, String)} instead (this will not include
|
* the call {@link #getActionsByName(Tool, String)} instead (this will not include
|
||||||
* reserved system actions).
|
* reserved system actions).
|
||||||
*
|
*
|
||||||
* <P>Note: more specific test case subclasses provide other methods for finding actions
|
* <P>Note: more specific test case subclasses provide other methods for finding actions
|
||||||
* when you have an owner name (which is usually the plugin name).
|
* when you have an owner name (which is usually the plugin name).
|
||||||
*
|
*
|
||||||
* @param tool the tool containing all system actions
|
* @param tool the tool containing all system actions
|
||||||
* @param owner the owner of the action
|
* @param owner the owner of the action
|
||||||
* @param name the name to match
|
* @param name the name to match
|
||||||
|
@ -1193,7 +1182,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the action by the given name that belongs to the given provider
|
* Returns the action by the given name that belongs to the given provider
|
||||||
*
|
*
|
||||||
* @param provider the provider
|
* @param provider the provider
|
||||||
* @param actionName the action name
|
* @param actionName the action name
|
||||||
* @return the action
|
* @return the action
|
||||||
|
@ -1485,7 +1474,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates a user initiated keystroke using the keybinding of the given action
|
* Simulates a user initiated keystroke using the keybinding of the given action
|
||||||
*
|
*
|
||||||
* @param destination the component for the action being executed
|
* @param destination the component for the action being executed
|
||||||
* @param action The action to simulate pressing
|
* @param action The action to simulate pressing
|
||||||
*/
|
*/
|
||||||
|
@ -1717,7 +1706,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
* Fires a {@link KeyListener#keyPressed(KeyEvent)},
|
* Fires a {@link KeyListener#keyPressed(KeyEvent)},
|
||||||
* {@link KeyListener#keyTyped(KeyEvent)}
|
* {@link KeyListener#keyTyped(KeyEvent)}
|
||||||
* and {@link KeyListener#keyReleased(KeyEvent)} for the given key stroke
|
* and {@link KeyListener#keyReleased(KeyEvent)} for the given key stroke
|
||||||
*
|
*
|
||||||
* @param c the destination component
|
* @param c the destination component
|
||||||
* @param ks the key stroke
|
* @param ks the key stroke
|
||||||
*/
|
*/
|
||||||
|
@ -2141,8 +2130,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
return runSwing(() -> action.isEnabledForContext(new ActionContext()));
|
return runSwing(() -> action.isEnabledForContext(new ActionContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEnabled(DockingActionIf action,
|
public static boolean isEnabled(DockingActionIf action, ActionContextProvider contextProvider) {
|
||||||
ActionContextProvider contextProvider) {
|
|
||||||
return runSwing(() -> action.isEnabledForContext(contextProvider.getActionContext(null)));
|
return runSwing(() -> action.isEnabledForContext(contextProvider.getActionContext(null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,14 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
||||||
|
|
||||||
initializeSystemProperties();
|
initializeSystemProperties();
|
||||||
|
|
||||||
ApplicationLayout layout = test.createApplicationLayout();
|
ApplicationLayout layout;
|
||||||
|
try {
|
||||||
|
layout = test.createApplicationLayout();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertException(e);
|
||||||
|
}
|
||||||
|
|
||||||
initializeLayout(layout);
|
initializeLayout(layout);
|
||||||
ApplicationConfiguration configuration = test.createApplicationConfiguration();
|
ApplicationConfiguration configuration = test.createApplicationConfiguration();
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
|
@ -157,7 +164,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
||||||
Application.initializeApplication(layout, configuration);
|
Application.initializeApplication(layout, configuration);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw e;
|
throw new AssertException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,13 +215,8 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
||||||
initialize(this);
|
initialize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ApplicationLayout createApplicationLayout() {
|
protected ApplicationLayout createApplicationLayout() throws IOException {
|
||||||
try {
|
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
||||||
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath()));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new AssertException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ApplicationConfiguration createApplicationConfiguration() {
|
protected ApplicationConfiguration createApplicationConfiguration() {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Ghidra application layout object.
|
* Constructs a new Ghidra application layout object.
|
||||||
*
|
*
|
||||||
* @throws FileNotFoundException if there was a problem getting a user
|
* @throws FileNotFoundException if there was a problem getting a user
|
||||||
* directory.
|
* directory.
|
||||||
* @throws IOException if there was a problem getting the application
|
* @throws IOException if there was a problem getting the application
|
||||||
|
@ -52,7 +52,6 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
// Application installation directory
|
// Application installation directory
|
||||||
applicationInstallationDir = findGhidraApplicationInstallationDir();
|
applicationInstallationDir = findGhidraApplicationInstallationDir();
|
||||||
|
|
||||||
|
|
||||||
// User directories
|
// User directories
|
||||||
userTempDir = ApplicationUtilities.getDefaultUserTempDir(getApplicationProperties());
|
userTempDir = ApplicationUtilities.getDefaultUserTempDir(getApplicationProperties());
|
||||||
userCacheDir = ApplicationUtilities.getDefaultUserCacheDir(getApplicationProperties());
|
userCacheDir = ApplicationUtilities.getDefaultUserCacheDir(getApplicationProperties());
|
||||||
|
@ -76,7 +75,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
* <p>
|
* <p>
|
||||||
* This is used when something external to Ghidra needs Ghidra's layout
|
* This is used when something external to Ghidra needs Ghidra's layout
|
||||||
* (like the Eclipse GhidraDevPlugin).
|
* (like the Eclipse GhidraDevPlugin).
|
||||||
*
|
*
|
||||||
* @param applicationInstallationDir The application installation directory.
|
* @param applicationInstallationDir The application installation directory.
|
||||||
* @throws FileNotFoundException if there was a problem getting a user
|
* @throws FileNotFoundException if there was a problem getting a user
|
||||||
* directory.
|
* directory.
|
||||||
|
@ -101,21 +100,21 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
userCacheDir = ApplicationUtilities.getDefaultUserCacheDir(getApplicationProperties());
|
userCacheDir = ApplicationUtilities.getDefaultUserCacheDir(getApplicationProperties());
|
||||||
userSettingsDir = ApplicationUtilities.getDefaultUserSettingsDir(getApplicationProperties(),
|
userSettingsDir = ApplicationUtilities.getDefaultUserSettingsDir(getApplicationProperties(),
|
||||||
getApplicationInstallationDir());
|
getApplicationInstallationDir());
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
extensionInstallationDirs = findExtensionInstallationDirectories();
|
extensionInstallationDirs = findExtensionInstallationDirectories();
|
||||||
extensionArchiveDir = findExtensionArchiveDirectory();
|
extensionArchiveDir = findExtensionArchiveDirectory();
|
||||||
|
|
||||||
// Patch directory
|
// Patch directory
|
||||||
patchDir = findPatchDirectory();
|
patchDir = findPatchDirectory();
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
modules = findGhidraModules();
|
modules = findGhidraModules();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the application root directories for this application layout.
|
* Finds the application root directories for this application layout.
|
||||||
*
|
*
|
||||||
* @return A collection of the application root directories for this layout.
|
* @return A collection of the application root directories for this layout.
|
||||||
*/
|
*/
|
||||||
protected Collection<ResourceFile> findGhidraApplicationRootDirs() {
|
protected Collection<ResourceFile> findGhidraApplicationRootDirs() {
|
||||||
|
@ -125,7 +124,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
/**
|
/**
|
||||||
* Finds the application installation directory for this Ghidra application
|
* Finds the application installation directory for this Ghidra application
|
||||||
* layout.
|
* layout.
|
||||||
*
|
*
|
||||||
* @return The application installation directory for this Ghidra
|
* @return The application installation directory for this Ghidra
|
||||||
* application layout. Could be null if there is no application
|
* application layout. Could be null if there is no application
|
||||||
* installation directory.
|
* installation directory.
|
||||||
|
@ -144,7 +143,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the modules for this Ghidra application layout.
|
* Finds the modules for this Ghidra application layout.
|
||||||
*
|
*
|
||||||
* @return The modules for this Ghidra application layout.
|
* @return The modules for this Ghidra application layout.
|
||||||
* @throws IOException if there was a problem finding the modules on disk.
|
* @throws IOException if there was a problem finding the modules on disk.
|
||||||
*/
|
*/
|
||||||
|
@ -161,7 +160,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
if (extensionModuleDirs != null) {
|
if (extensionModuleDirs != null) {
|
||||||
for (File extensionModuleDir : extensionModuleDirs) {
|
for (File extensionModuleDir : extensionModuleDirs) {
|
||||||
|
|
||||||
// Skip extensions that live in an application root directory...we've already
|
// Skip extensions that live in an application root directory...we've already
|
||||||
// found those.
|
// found those.
|
||||||
if (applicationRootDirs.stream()
|
if (applicationRootDirs.stream()
|
||||||
.anyMatch(dir -> FileUtilities.isPathContainedWithin(dir.getFile(false),
|
.anyMatch(dir -> FileUtilities.isPathContainedWithin(dir.getFile(false),
|
||||||
|
@ -183,7 +182,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
// These might exist if Ghidra was launched from an Eclipse project that resides
|
// These might exist if Ghidra was launched from an Eclipse project that resides
|
||||||
// external to the Ghidra installation.
|
// external to the Ghidra installation.
|
||||||
for (String entry : System.getProperty("java.class.path", "").split(File.pathSeparator)) {
|
for (String entry : System.getProperty("java.class.path", "").split(File.pathSeparator)) {
|
||||||
final ResourceFile classpathEntry = new ResourceFile(entry);
|
ResourceFile classpathEntry = new ResourceFile(entry);
|
||||||
|
|
||||||
// We only care about directories (skip jars)
|
// We only care about directories (skip jars)
|
||||||
if (!classpathEntry.isDirectory()) {
|
if (!classpathEntry.isDirectory()) {
|
||||||
|
@ -193,8 +192,8 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
// Skip classpath entries that live in an application root directory...we've already
|
// Skip classpath entries that live in an application root directory...we've already
|
||||||
// found those.
|
// found those.
|
||||||
if (applicationRootDirs.stream()
|
if (applicationRootDirs.stream()
|
||||||
.anyMatch(dir -> FileUtilities.isPathContainedWithin(
|
.anyMatch(dir -> FileUtilities.isPathContainedWithin(dir.getFile(false),
|
||||||
dir.getFile(false), classpathEntry.getFile(false)))) {
|
classpathEntry.getFile(false)))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +233,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>[application root]/Extensions/Ghidra</code></li>
|
* <li><code>[application root]/Extensions/Ghidra</code></li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @return the archive folder, or null if can't be determined
|
* @return the archive folder, or null if can't be determined
|
||||||
*/
|
*/
|
||||||
protected ResourceFile findExtensionArchiveDirectory() {
|
protected ResourceFile findExtensionArchiveDirectory() {
|
||||||
|
@ -250,23 +249,23 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a prioritized list of directories where Ghidra extensions are installed. These
|
* Returns a prioritized list of directories where Ghidra extensions are installed. These
|
||||||
* should be at the following locations:<br>
|
* should be at the following locations:<br>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>[user settings dir]/Extensions</code></li>
|
* <li><code>[user settings dir]/Extensions</code></li>
|
||||||
* <li><code>[application install dir]/Ghidra/Extensions</code></li>
|
* <li><code>[application install dir]/Ghidra/Extensions</code></li>
|
||||||
* <li><code>ghidra/Ghidra/Extensions</code> (development mode)</li>
|
* <li><code>ghidra/Ghidra/Extensions</code> (development mode)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @return the install folder, or null if can't be determined
|
* @return the install folder, or null if can't be determined
|
||||||
*/
|
*/
|
||||||
protected List<ResourceFile> findExtensionInstallationDirectories() {
|
protected List<ResourceFile> findExtensionInstallationDirectories() {
|
||||||
|
|
||||||
List<ResourceFile> dirs = new ArrayList<>();
|
List<ResourceFile> dirs = new ArrayList<>();
|
||||||
|
|
||||||
// Would like to find a better way to do this, but for the moment this seems the
|
// Would like to find a better way to do this, but for the moment this seems the
|
||||||
// only solution. We want to get the 'Extensions' directory in ghidra, but there's
|
// only solution. We want to get the 'Extensions' directory in ghidra, but there's
|
||||||
// no way to retrieve that directory directly. We can only get the full set of
|
// no way to retrieve that directory directly. We can only get the full set of
|
||||||
// application root dirs and search for it, hoping we don't encounter one with the
|
// application root dirs and search for it, hoping we don't encounter one with the
|
||||||
// name 'Extensions' in one of the other root dirs.
|
// name 'Extensions' in one of the other root dirs.
|
||||||
if (SystemUtilities.isInDevelopmentMode()) {
|
if (SystemUtilities.isInDevelopmentMode()) {
|
||||||
|
|
|
@ -16,13 +16,17 @@
|
||||||
package ghidra;
|
package ghidra;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Collections;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
|
import ghidra.framework.GModule;
|
||||||
|
import utility.module.ClasspathFilter;
|
||||||
|
import utility.module.ModuleUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Ghidra test application layout defines the customizable elements of the Ghidra
|
* The Ghidra test application layout defines the customizable elements of the Ghidra
|
||||||
* application's directory structure when running a test.
|
* application's directory structure when running a test.
|
||||||
* <p>
|
* <p>
|
||||||
* This layout exists because tests often need to provide their own user settings
|
* This layout exists because tests often need to provide their own user settings
|
||||||
|
@ -35,14 +39,13 @@ public class GhidraTestApplicationLayout extends GhidraApplicationLayout {
|
||||||
* directory.
|
* directory.
|
||||||
* <p>
|
* <p>
|
||||||
* This layout is useful when running Ghidra tests.
|
* This layout is useful when running Ghidra tests.
|
||||||
*
|
*
|
||||||
* @param userSettingsDir The custom user settings directory to use.
|
* @param userSettingsDir The custom user settings directory to use.
|
||||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||||
* @throws IOException if there was a problem getting the application properties.
|
* @throws IOException if there was a problem getting the application properties.
|
||||||
*/
|
*/
|
||||||
public GhidraTestApplicationLayout(File userSettingsDir)
|
public GhidraTestApplicationLayout(File userSettingsDir)
|
||||||
throws FileNotFoundException, IOException {
|
throws FileNotFoundException, IOException {
|
||||||
super();
|
|
||||||
this.userSettingsDir = userSettingsDir;
|
this.userSettingsDir = userSettingsDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,4 +66,51 @@ public class GhidraTestApplicationLayout extends GhidraApplicationLayout {
|
||||||
File dir = new File(getUserTempDir(), "patch");
|
File dir = new File(getUserTempDir(), "patch");
|
||||||
return new ResourceFile(dir);
|
return new ResourceFile(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, GModule> findGhidraModules() throws IOException {
|
||||||
|
|
||||||
|
//
|
||||||
|
// 1) Enforces module dependencies by classpath to better control the test environment.
|
||||||
|
// 2) Add any dependent modules into the tests that are not already on the classpath. For
|
||||||
|
// example, this class adds all processor modules, as we do not use classpath
|
||||||
|
// dependencies for processor modules usage.
|
||||||
|
//
|
||||||
|
Set<String> modulePatterns = getDependentModulePatterns();
|
||||||
|
Predicate<Path> additionalPaths = path -> {
|
||||||
|
String pathString = path.toString();
|
||||||
|
return modulePatterns.stream().anyMatch(pattern -> pathString.contains(pattern));
|
||||||
|
};
|
||||||
|
|
||||||
|
Collection<ResourceFile> roots =
|
||||||
|
ModuleUtilities.findModuleRootDirectories(applicationRootDirs);
|
||||||
|
return ModuleUtilities.findModules(applicationRootDirs, roots,
|
||||||
|
new ClasspathFilter(additionalPaths));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns patterns that will be used to check against each discovered module. Matching module
|
||||||
|
* paths will be included as modules to be used during testing. By default, only modules that
|
||||||
|
* match the classpath entries are included. If your tests needs modules not referenced by the
|
||||||
|
* classpath, then you can override this method and add any module patterns needed.
|
||||||
|
*
|
||||||
|
* <p>The pattern is any desired text that will be matched against. If you wish to use path
|
||||||
|
* separators, be sure to do so in a platform-dependent manner.
|
||||||
|
*
|
||||||
|
* @return the patterns
|
||||||
|
*/
|
||||||
|
protected Set<String> getDependentModulePatterns() {
|
||||||
|
//@formatter:off
|
||||||
|
char slash = File.separatorChar;
|
||||||
|
return new HashSet<>(Set.of(
|
||||||
|
slash + "Processors" + slash,
|
||||||
|
"TestResources",
|
||||||
|
|
||||||
|
// This could easily be in a subclass, included by only those tests that need this
|
||||||
|
// entry. At the time of writing, there are 8 tests that need this module. For now,
|
||||||
|
// adding the entry here seems like the easiest thing to do.
|
||||||
|
"DemanglerGnu"
|
||||||
|
));
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,11 @@ import ghidra.framework.GModule;
|
||||||
import utilities.util.FileUtilities;
|
import utilities.util.FileUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Application Layout base class defines the customizable elements of the application's
|
* The Application Layout base class defines the customizable elements of the application's
|
||||||
* directory structure. Create a subclass to define a custom layout.
|
* directory structure. Create a subclass to define a custom layout.
|
||||||
* <p>
|
* <p>
|
||||||
* If a layout changes in a significant way, the
|
* If a layout changes in a significant way, the
|
||||||
* {@link ApplicationProperties#APPLICATION_LAYOUT_VERSION_PROPERTY} should be incremented so
|
* {@link ApplicationProperties#APPLICATION_LAYOUT_VERSION_PROPERTY} should be incremented so
|
||||||
* external things like Eclipse GhidraDev know to look in different places for things.
|
* external things like Eclipse GhidraDev know to look in different places for things.
|
||||||
*/
|
*/
|
||||||
public abstract class ApplicationLayout {
|
public abstract class ApplicationLayout {
|
||||||
|
@ -47,7 +47,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the application properties from the application layout
|
* Gets the application properties from the application layout
|
||||||
*
|
*
|
||||||
* @return The application properties. Should never be null.
|
* @return The application properties. Should never be null.
|
||||||
*/
|
*/
|
||||||
public final ApplicationProperties getApplicationProperties() {
|
public final ApplicationProperties getApplicationProperties() {
|
||||||
|
@ -56,7 +56,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the application root directories from the application layout.
|
* Gets the application root directories from the application layout.
|
||||||
*
|
*
|
||||||
* @return A collection of application root directories (or null if not set).
|
* @return A collection of application root directories (or null if not set).
|
||||||
*/
|
*/
|
||||||
public final Collection<ResourceFile> getApplicationRootDirs() {
|
public final Collection<ResourceFile> getApplicationRootDirs() {
|
||||||
|
@ -65,7 +65,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the application installation directory from the application layout.
|
* Gets the application installation directory from the application layout.
|
||||||
*
|
*
|
||||||
* @return The application installation directory (or null if not set).
|
* @return The application installation directory (or null if not set).
|
||||||
*/
|
*/
|
||||||
public final ResourceFile getApplicationInstallationDir() {
|
public final ResourceFile getApplicationInstallationDir() {
|
||||||
|
@ -74,7 +74,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the application's modules from the application layout.
|
* Gets the application's modules from the application layout.
|
||||||
*
|
*
|
||||||
* @return The application's modules as a map (mapping module name to module for convenience).
|
* @return The application's modules as a map (mapping module name to module for convenience).
|
||||||
*/
|
*/
|
||||||
public final Map<String, GModule> getModules() {
|
public final Map<String, GModule> getModules() {
|
||||||
|
@ -83,7 +83,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the user temp directory from the application layout.
|
* Gets the user temp directory from the application layout.
|
||||||
*
|
*
|
||||||
* @return The user temp directory (or null if not set).
|
* @return The user temp directory (or null if not set).
|
||||||
*/
|
*/
|
||||||
public final File getUserTempDir() {
|
public final File getUserTempDir() {
|
||||||
|
@ -92,7 +92,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the user cache directory from the application layout.
|
* Gets the user cache directory from the application layout.
|
||||||
*
|
*
|
||||||
* @return The user cache directory (or null if not set).
|
* @return The user cache directory (or null if not set).
|
||||||
*/
|
*/
|
||||||
public final File getUserCacheDir() {
|
public final File getUserCacheDir() {
|
||||||
|
@ -101,7 +101,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the user settings directory from the application layout.
|
* Gets the user settings directory from the application layout.
|
||||||
*
|
*
|
||||||
* @return The user settings directory (or null if not set).
|
* @return The user settings directory (or null if not set).
|
||||||
*/
|
*/
|
||||||
public final File getUserSettingsDir() {
|
public final File getUserSettingsDir() {
|
||||||
|
@ -110,10 +110,10 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the directory where archived application Extensions are stored.
|
* Returns the directory where archived application Extensions are stored.
|
||||||
*
|
*
|
||||||
* @return the application Extensions archive directory. Could be null if the
|
* @return the application Extensions archive directory. Could be null if the
|
||||||
* {@link ApplicationLayout} does not support application Extensions.
|
* {@link ApplicationLayout} does not support application Extensions.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final ResourceFile getExtensionArchiveDir() {
|
public final ResourceFile getExtensionArchiveDir() {
|
||||||
return extensionArchiveDir;
|
return extensionArchiveDir;
|
||||||
|
@ -121,7 +121,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an {@link List ordered list} of the application Extensions installation directories.
|
* Returns an {@link List ordered list} of the application Extensions installation directories.
|
||||||
*
|
*
|
||||||
* @return an {@link List ordered list} of the application Extensions installation directories.
|
* @return an {@link List ordered list} of the application Extensions installation directories.
|
||||||
* Could be empty if the {@link ApplicationLayout} does not support application Extensions.
|
* Could be empty if the {@link ApplicationLayout} does not support application Extensions.
|
||||||
*/
|
*/
|
||||||
|
@ -140,7 +140,7 @@ public abstract class ApplicationLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the application's user directories (or ensures they already exist).
|
* Creates the application's user directories (or ensures they already exist).
|
||||||
*
|
*
|
||||||
* @throws IOException if there was a problem creating the application's user directories.
|
* @throws IOException if there was a problem creating the application's user directories.
|
||||||
*/
|
*/
|
||||||
public final void createUserDirs() throws IOException {
|
public final void createUserDirs() throws IOException {
|
||||||
|
@ -168,13 +168,14 @@ public abstract class ApplicationLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether or not the application is using a "single jar" layout. Custom application
|
* Checks whether or not the application is using a "single jar" layout. Custom application
|
||||||
* layouts that extend this class can override this method once they determine they are in
|
* layouts that extend this class can override this method once they determine they are in
|
||||||
* single jar mode.
|
* single jar mode.
|
||||||
*
|
*
|
||||||
* @return true if the application is using a "single jar" layout; otherwise, false.
|
* @return true if the application is using a "single jar" layout; otherwise, false.
|
||||||
*/
|
*/
|
||||||
public boolean inSingleJarMode() {
|
public boolean inSingleJarMode() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package utility.module;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import generic.jar.ResourceFile;
|
||||||
|
import ghidra.framework.GModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A predicate used to filter modules using the classpath. Only modules included in the classpath
|
||||||
|
* will pass this filter. Any modules not on the classpath may be included by calling
|
||||||
|
* {@link #ClasspathFilter(Predicate)} with a predicate that allows other module paths.
|
||||||
|
*/
|
||||||
|
public class ClasspathFilter implements Predicate<GModule> {
|
||||||
|
|
||||||
|
private Predicate<Path> additionalPaths = p -> false;
|
||||||
|
private Set<Path> cpModulePaths = new HashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor to allow only modules on the classpath.
|
||||||
|
*/
|
||||||
|
public ClasspathFilter() {
|
||||||
|
String cp = System.getProperty("java.class.path");
|
||||||
|
String[] cpPathStrings = cp.split(File.pathSeparator);
|
||||||
|
for (String cpPathString : cpPathStrings) {
|
||||||
|
Path modulePath = ModuleUtilities.getModule(cpPathString);
|
||||||
|
if (modulePath != null) {
|
||||||
|
Path normalized = modulePath.normalize().toAbsolutePath();
|
||||||
|
cpModulePaths.add(normalized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that allows any module to be included whose path passed the given predicate. If
|
||||||
|
* the predicate returns false, then a given module will only be included if it is in the
|
||||||
|
* classpath.
|
||||||
|
*
|
||||||
|
* @param additionalPaths a predicate that allows additional module paths (they do not need to
|
||||||
|
* be on the system classpath)
|
||||||
|
*/
|
||||||
|
public ClasspathFilter(Predicate<Path> additionalPaths) {
|
||||||
|
this();
|
||||||
|
this.additionalPaths = additionalPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(GModule m) {
|
||||||
|
ResourceFile file = m.getModuleRoot();
|
||||||
|
Path path = Path.of(file.getAbsolutePath());
|
||||||
|
Path normalized = path.normalize().toAbsolutePath();
|
||||||
|
return additionalPaths.test(normalized) || cpModulePaths.contains(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.framework.GModule;
|
import ghidra.framework.GModule;
|
||||||
|
@ -39,14 +40,14 @@ public class ModuleUtilities {
|
||||||
public static final String MODULE_LIST = "MODULE_LIST";
|
public static final String MODULE_LIST = "MODULE_LIST";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How many directories deep to look for module directories, starting from an application root
|
* How many directories deep to look for module directories, starting from an application root
|
||||||
* directory. For example, 3 would pick up modules as deep as: root/category/category/module
|
* directory. For example, 3 would pick up modules as deep as: root/category/category/module
|
||||||
*/
|
*/
|
||||||
private static final int MAX_MODULE_DEPTH = 3;
|
private static final int MAX_MODULE_DEPTH = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given directory is a module.
|
* Checks if the given directory is a module.
|
||||||
*
|
*
|
||||||
* @param dir the directory to check.
|
* @param dir the directory to check.
|
||||||
* @return true if the given directory is a module
|
* @return true if the given directory is a module
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +57,7 @@ public class ModuleUtilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the given path is a module root directory.
|
* Returns true if the given path is a module root directory.
|
||||||
*
|
*
|
||||||
* @param path the path to check
|
* @param path the path to check
|
||||||
* @return true if the given path is a module root directory.
|
* @return true if the given path is a module root directory.
|
||||||
*/
|
*/
|
||||||
|
@ -68,14 +69,14 @@ public class ModuleUtilities {
|
||||||
/**
|
/**
|
||||||
* Searches the given root directory for module root directories. Adds any discovered module
|
* Searches the given root directory for module root directories. Adds any discovered module
|
||||||
* root directories to the given collection.
|
* root directories to the given collection.
|
||||||
*
|
*
|
||||||
* @param rootDir The directory to start looking for module root directories in.
|
* @param rootDir The directory to start looking for module root directories in.
|
||||||
* @param moduleRootDirs A collection to add discovered module root directories to.
|
* @param moduleRootDirs A collection to add discovered module root directories to.
|
||||||
* @return The given collection with any discovered modules added.
|
* @return The given collection with any discovered modules added.
|
||||||
*/
|
*/
|
||||||
public static Collection<ResourceFile> findModuleRootDirectories(ResourceFile rootDir,
|
public static Collection<ResourceFile> findModuleRootDirectories(ResourceFile rootDir,
|
||||||
Collection<ResourceFile> moduleRootDirs) {
|
Collection<ResourceFile> moduleRootDirs) {
|
||||||
// look for any external GPL modules
|
// look for any external GPL modules
|
||||||
findModuleRootDirectoriesHelper(new ResourceFile(rootDir, "../GPL"), moduleRootDirs,
|
findModuleRootDirectoriesHelper(new ResourceFile(rootDir, "../GPL"), moduleRootDirs,
|
||||||
MAX_MODULE_DEPTH);
|
MAX_MODULE_DEPTH);
|
||||||
return findModuleRootDirectoriesHelper(rootDir, moduleRootDirs, MAX_MODULE_DEPTH);
|
return findModuleRootDirectoriesHelper(rootDir, moduleRootDirs, MAX_MODULE_DEPTH);
|
||||||
|
@ -100,10 +101,25 @@ public class ModuleUtilities {
|
||||||
return moduleRootDirs;
|
return moduleRootDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the given root directories for module root directories. Adds any discovered module
|
||||||
|
* root directories to the returned collection.
|
||||||
|
*
|
||||||
|
* <p>Note: if you need to control the type of collection used to store the module roots, then
|
||||||
|
* call {@link #findModuleRootDirectories(Collection, Collection)}.
|
||||||
|
*
|
||||||
|
* @param rootDirs The directories to look for module root directories in.
|
||||||
|
* @return a new collection with any discovered modules added.
|
||||||
|
*/
|
||||||
|
public static Collection<ResourceFile> findModuleRootDirectories(
|
||||||
|
Collection<ResourceFile> rootDirs) {
|
||||||
|
return findModuleRootDirectories(rootDirs, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the given root directories for module root directories. Adds any discovered module
|
* Searches the given root directories for module root directories. Adds any discovered module
|
||||||
* root directories to the given collection.
|
* root directories to the given collection.
|
||||||
*
|
*
|
||||||
* @param rootDirs The directories to look for module root directories in.
|
* @param rootDirs The directories to look for module root directories in.
|
||||||
* @param moduleRootDirs A collection to add discovered module root directories to.
|
* @param moduleRootDirs A collection to add discovered module root directories to.
|
||||||
* @return The given collection with any discovered modules added.
|
* @return The given collection with any discovered modules added.
|
||||||
|
@ -120,7 +136,7 @@ public class ModuleUtilities {
|
||||||
* Searches the given jar root directory for module root directories. Uses a "module list"
|
* Searches the given jar root directory for module root directories. Uses a "module list"
|
||||||
* file to locate the module root directories. Adds any discovered module root directories
|
* file to locate the module root directories. Adds any discovered module root directories
|
||||||
* to the given collection.
|
* to the given collection.
|
||||||
*
|
*
|
||||||
* @param rootDir The jar directory to start looking for module root directories in.
|
* @param rootDir The jar directory to start looking for module root directories in.
|
||||||
* @param moduleRootDirs A collection to add discovered module root directories to.
|
* @param moduleRootDirs A collection to add discovered module root directories to.
|
||||||
* @return The given collection with any discovered modules added.
|
* @return The given collection with any discovered modules added.
|
||||||
|
@ -137,7 +153,7 @@ public class ModuleUtilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for modules in a given collection of module root directories.
|
* Searches for modules in a given collection of module root directories.
|
||||||
*
|
*
|
||||||
* @param appRootDirs The collection of application root directories associated with the the given
|
* @param appRootDirs The collection of application root directories associated with the the given
|
||||||
* list of module root directories.
|
* list of module root directories.
|
||||||
* @param moduleRootDirs A collection of module root directories to search for modules in.
|
* @param moduleRootDirs A collection of module root directories to search for modules in.
|
||||||
|
@ -146,10 +162,31 @@ public class ModuleUtilities {
|
||||||
public static Map<String, GModule> findModules(Collection<ResourceFile> appRootDirs,
|
public static Map<String, GModule> findModules(Collection<ResourceFile> appRootDirs,
|
||||||
Collection<ResourceFile> moduleRootDirs) {
|
Collection<ResourceFile> moduleRootDirs) {
|
||||||
|
|
||||||
|
Predicate<GModule> allModules = module -> true;
|
||||||
|
return findModules(appRootDirs, moduleRootDirs, allModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for modules in a given collection of module root directories.
|
||||||
|
*
|
||||||
|
* @param appRootDirs The collection of application root directories associated with the the given
|
||||||
|
* list of module root directories.
|
||||||
|
* @param moduleRootDirs A collection of module root directories to search for modules in.
|
||||||
|
* @param moduleFilter a predicate used to filter modules; a given module will not be included
|
||||||
|
* when the predicate returns false.
|
||||||
|
* @return The discovered modules as a map (mapping module name to module for convenience).
|
||||||
|
*/
|
||||||
|
public static Map<String, GModule> findModules(Collection<ResourceFile> appRootDirs,
|
||||||
|
Collection<ResourceFile> moduleRootDirs, Predicate<GModule> moduleFilter) {
|
||||||
|
|
||||||
Map<String, GModule> map = new TreeMap<>();
|
Map<String, GModule> map = new TreeMap<>();
|
||||||
|
|
||||||
for (ResourceFile moduleRoot : moduleRootDirs) {
|
for (ResourceFile moduleRoot : moduleRootDirs) {
|
||||||
GModule gModule = new GModule(appRootDirs, moduleRoot);
|
GModule gModule = new GModule(appRootDirs, moduleRoot);
|
||||||
|
if (!moduleFilter.test(gModule)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (map.put(moduleRoot.getName(), gModule) != null) {
|
if (map.put(moduleRoot.getName(), gModule) != null) {
|
||||||
StringBuilder collided = new StringBuilder();
|
StringBuilder collided = new StringBuilder();
|
||||||
for (ResourceFile collideRoot : moduleRootDirs) {
|
for (ResourceFile collideRoot : moduleRootDirs) {
|
||||||
|
@ -167,7 +204,7 @@ public class ModuleUtilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the "lib" directories from the given modules.
|
* Gets the "lib" directories from the given modules.
|
||||||
*
|
*
|
||||||
* @param modules The modules to get the lib directories of.
|
* @param modules The modules to get the lib directories of.
|
||||||
* @return A collection of lib directories from the given modules.
|
* @return A collection of lib directories from the given modules.
|
||||||
*/
|
*/
|
||||||
|
@ -189,7 +226,7 @@ public class ModuleUtilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the directory locations of the .class files and resources from the given modules.
|
* Gets the directory locations of the .class files and resources from the given modules.
|
||||||
*
|
*
|
||||||
* @param modules The modules to get the compiled .class and resources directories of.
|
* @param modules The modules to get the compiled .class and resources directories of.
|
||||||
* @return A collection of directories containing classes and resources from the given modules.
|
* @return A collection of directories containing classes and resources from the given modules.
|
||||||
*/
|
*/
|
||||||
|
@ -197,8 +234,8 @@ public class ModuleUtilities {
|
||||||
String[] binaryPathTokens = BINARY_PATH.split(":");
|
String[] binaryPathTokens = BINARY_PATH.split(":");
|
||||||
List<ResourceFile> binDirectories = new ArrayList<>();
|
List<ResourceFile> binDirectories = new ArrayList<>();
|
||||||
for (GModule module : modules.values()) {
|
for (GModule module : modules.values()) {
|
||||||
Arrays.stream(binaryPathTokens).forEach(
|
Arrays.stream(binaryPathTokens)
|
||||||
token -> module.collectExistingModuleDirs(binDirectories, token));
|
.forEach(token -> module.collectExistingModuleDirs(binDirectories, token));
|
||||||
}
|
}
|
||||||
return binDirectories;
|
return binDirectories;
|
||||||
}
|
}
|
||||||
|
@ -215,10 +252,10 @@ public class ModuleUtilities {
|
||||||
* <br>
|
* <br>
|
||||||
* <br>and false for these paths:
|
* <br>and false for these paths:
|
||||||
* <br>
|
* <br>
|
||||||
* <br>
|
* <br>
|
||||||
* <code>/some/random/path</code><br>
|
* <code>/some/random/path</code><br>
|
||||||
* <code>/some/dir/features/</code>
|
* <code>/some/dir/features/</code>
|
||||||
*
|
*
|
||||||
* @param pathName the path name to check
|
* @param pathName the path name to check
|
||||||
* @return true if the given path is parented by a module root directory.
|
* @return true if the given path is parented by a module root directory.
|
||||||
* @see #isModuleDirectory(Path)
|
* @see #isModuleDirectory(Path)
|
||||||
|
@ -228,7 +265,7 @@ public class ModuleUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path of the module containing the given path string, if it is parented by a
|
* Returns the path of the module containing the given path string, if it is parented by a
|
||||||
* module root directory.
|
* module root directory.
|
||||||
* <p>
|
* <p>
|
||||||
* For example, given a module path of <code>/some/dir/features/cool_module/</code>, then this
|
* For example, given a module path of <code>/some/dir/features/cool_module/</code>, then this
|
||||||
|
@ -240,10 +277,10 @@ public class ModuleUtilities {
|
||||||
* <br>
|
* <br>
|
||||||
* <br>and null for these paths:
|
* <br>and null for these paths:
|
||||||
* <br>
|
* <br>
|
||||||
* <br>
|
* <br>
|
||||||
* <code>/some/random/path</code><br>
|
* <code>/some/random/path</code><br>
|
||||||
* <code>/some/dir/features/</code>
|
* <code>/some/dir/features/</code>
|
||||||
*
|
*
|
||||||
* @param pathName the path name to check
|
* @param pathName the path name to check
|
||||||
* @return the module root directory; null if the path is not in a module
|
* @return the module root directory; null if the path is not in a module
|
||||||
* @see #isModuleDirectory(Path)
|
* @see #isModuleDirectory(Path)
|
||||||
|
@ -271,18 +308,18 @@ public class ModuleUtilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a file that is the root folder of the repository containing the given file. 'Root'
|
* Returns a file that is the root folder of the repository containing the given file. 'Root'
|
||||||
* here means a folder that contains a repository folder. As an example, given a repo
|
* here means a folder that contains a repository folder. As an example, given a repo
|
||||||
* structure of:
|
* structure of:
|
||||||
*
|
*
|
||||||
* <p><code>/userdir/repoRoot/repoDir/.git</code><br>
|
* <p><code>/userdir/repoRoot/repoDir/.git</code><br>
|
||||||
*
|
*
|
||||||
* <p>then this method, given will produce the following results (input -> output):<br>
|
* <p>then this method, given will produce the following results (input -> output):<br>
|
||||||
*
|
*
|
||||||
* <p><code>/userdir/repoRoot/repoDir/.git -> /userdir/repoRoot</code>
|
* <p><code>/userdir/repoRoot/repoDir/.git -> /userdir/repoRoot</code>
|
||||||
* <br><code>/userdir/repoRoot/repoDir -> /userdir/repoRoot</code>
|
* <br><code>/userdir/repoRoot/repoDir -> /userdir/repoRoot</code>
|
||||||
* <br><code>/userdir/repoRoot -> /userdir/repoRoot</code>
|
* <br><code>/userdir/repoRoot -> /userdir/repoRoot</code>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param f the child file of the desired repo
|
* @param f the child file of the desired repo
|
||||||
* @return a file that is the root folder of the repository containing the given file; null
|
* @return a file that is the root folder of the repository containing the given file; null
|
||||||
* if the given file is not under a repo directory or itself a repo root
|
* if the given file is not under a repo directory or itself a repo root
|
||||||
|
@ -311,16 +348,16 @@ public class ModuleUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a file that is the repository folder containing the given file. As an example,
|
* Returns a file that is the repository folder containing the given file. As an example,
|
||||||
* given a repo structure of:
|
* given a repo structure of:
|
||||||
*
|
*
|
||||||
* <p><code>/userdir/repoRoot/repoDir/.git</code><br>
|
* <p><code>/userdir/repoRoot/repoDir/.git</code><br>
|
||||||
*
|
*
|
||||||
* <p>then this method, given will produce the following results (input -> output):<br>
|
* <p>then this method, given will produce the following results (input -> output):<br>
|
||||||
*
|
*
|
||||||
* <p><code>/userdir/repoRoot/repoDir/.git -> /userdir/repoRoot/repoDir</code>
|
* <p><code>/userdir/repoRoot/repoDir/.git -> /userdir/repoRoot/repoDir</code>
|
||||||
* <br><code>/userdir/repoRoot/repoDir -> /userdir/repoRoot/repoDir</code>
|
* <br><code>/userdir/repoRoot/repoDir -> /userdir/repoRoot/repoDir</code>
|
||||||
*
|
*
|
||||||
* @param f the child file of the desired repo
|
* @param f the child file of the desired repo
|
||||||
* @return a file that is the repo folder of the repository containing the given file; null
|
* @return a file that is the repo folder of the repository containing the given file; null
|
||||||
* if the given file is not under a repo directory
|
* if the given file is not under a repo directory
|
||||||
|
@ -339,7 +376,7 @@ public class ModuleUtilities {
|
||||||
/**
|
/**
|
||||||
* Checks to see if the given {@link GModule module} is external to the Ghidra installation
|
* Checks to see if the given {@link GModule module} is external to the Ghidra installation
|
||||||
* directory
|
* directory
|
||||||
*
|
*
|
||||||
* @param module the module to check
|
* @param module the module to check
|
||||||
* @param layout Ghidra's layout
|
* @param layout Ghidra's layout
|
||||||
* @return true if the given {@link GModule module} is external to the Ghidra installation
|
* @return true if the given {@link GModule module} is external to the Ghidra installation
|
||||||
|
|
|
@ -60,6 +60,7 @@ dependencies {
|
||||||
testImplementation project(path: ':Base', configuration: 'integrationTestArtifacts')
|
testImplementation project(path: ':Base', configuration: 'integrationTestArtifacts')
|
||||||
testImplementation project(path: ':FunctionGraph', configuration: 'testArtifacts')
|
testImplementation project(path: ':FunctionGraph', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':PDB', configuration: 'testArtifacts')
|
testImplementation project(path: ':PDB', configuration: 'testArtifacts')
|
||||||
|
testImplementation project(path: ':GnuDemangler', configuration: 'testArtifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Java 9, we must explicitly export references to the internal classes we are using.
|
// For Java 9, we must explicitly export references to the internal classes we are using.
|
||||||
|
|
|
@ -1,177 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.pcodeCPort.slgh_compile;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.languages.sleigh.ConstructorEntryVisitor;
|
|
||||||
import ghidra.app.plugin.languages.sleigh.SleighLanguages;
|
|
||||||
import ghidra.app.plugin.processors.sleigh.*;
|
|
||||||
import ghidra.app.plugin.processors.sleigh.pattern.DisjointPattern;
|
|
||||||
import ghidra.app.plugin.processors.sleigh.symbol.SubtableSymbol;
|
|
||||||
import ghidra.program.model.lang.LanguageID;
|
|
||||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
|
||||||
|
|
||||||
public class WithBlockTest extends AbstractGhidraHeadlessIntegrationTest {
|
|
||||||
|
|
||||||
protected static boolean setupDone;
|
|
||||||
protected static LanguageID langID;
|
|
||||||
protected static SleighLanguageProvider provider;
|
|
||||||
protected static SleighLanguage lang;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
if (!setupDone) {
|
|
||||||
langID = new LanguageID("TestWith:BE:32:default");
|
|
||||||
provider = new SleighLanguageProvider();
|
|
||||||
lang = (SleighLanguage) provider.getLanguage(langID);
|
|
||||||
setupDone = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String opnd(int n) {
|
|
||||||
return "\n" + (char) ('A' + n);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Pair<DisjointPattern, Constructor> findConstructor(String table, String firstPrint) {
|
|
||||||
AtomicReference<DisjointPattern> fpat = new AtomicReference<>(null);
|
|
||||||
AtomicReference<Constructor> fcon = new AtomicReference<>(null);
|
|
||||||
SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() {
|
|
||||||
@Override
|
|
||||||
public int visit(SubtableSymbol subtable, DisjointPattern pattern, Constructor cons) {
|
|
||||||
if (table.equals(subtable.getName()) &&
|
|
||||||
firstPrint.equals(cons.getPrintPieces().get(0))) {
|
|
||||||
if (null != fpat.get()) {
|
|
||||||
throw new AssertionError("Multiple constructors found. " +
|
|
||||||
"Write the test slaspec such that no two constructors in the same " +
|
|
||||||
"table share the same first printpiece.");
|
|
||||||
}
|
|
||||||
fpat.set(pattern);
|
|
||||||
fcon.set(cons);
|
|
||||||
}
|
|
||||||
return CONTINUE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (null == fpat.get()) {
|
|
||||||
throw new AssertionError(
|
|
||||||
"No such constructor found: " + table + ":" + firstPrint + "...");
|
|
||||||
}
|
|
||||||
return new ImmutablePair<>(fpat.get(), fcon.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNOP1_NoWith() {
|
|
||||||
Pair<DisjointPattern, Constructor> NOP1 = findConstructor("instruction", "NOP1");
|
|
||||||
assertEquals("ins:SS:XF:XX:XX:XX", NOP1.getLeft().toString());
|
|
||||||
assertEquals(0, NOP1.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRel8addr_WithTabRel8_WithChgPhase3() {
|
|
||||||
Pair<DisjointPattern, Constructor> Rel8addr = findConstructor("Rel8", opnd(1));
|
|
||||||
assertEquals("always", Rel8addr.getLeft().toString());
|
|
||||||
assertEquals(1, Rel8addr.getRight().getContextChanges().size());
|
|
||||||
assertEquals("ctx&F0:00:00:00 := 0x3( << 28)",
|
|
||||||
Rel8addr.getRight().getContextChanges().get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOP1r0_WithTabOp1() {
|
|
||||||
Pair<DisjointPattern, Constructor> OP1r0 = findConstructor("OP1", "r0");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:X0:XX:XX:XX)", OP1r0.getLeft().toString());
|
|
||||||
assertEquals(1, OP1r0.getRight().getContextChanges().size());
|
|
||||||
assertEquals("ctx&F0:00:00:00 := 0x2( << 28)",
|
|
||||||
OP1r0.getRight().getContextChanges().get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOP1r1_WithPatPhase1() {
|
|
||||||
Pair<DisjointPattern, Constructor> OP1r1 = findConstructor("OP1", "r1");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:X1:XX:XX:XX)", OP1r1.getLeft().toString());
|
|
||||||
assertEquals(1, OP1r1.getRight().getContextChanges().size());
|
|
||||||
assertEquals("ctx&F0:00:00:00 := 0x2( << 28)",
|
|
||||||
OP1r1.getRight().getContextChanges().get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOP1r2_WithChgPhase2() {
|
|
||||||
Pair<DisjointPattern, Constructor> OP1r2 = findConstructor("OP1", "r2");
|
|
||||||
assertEquals("ins:X2:XX:XX:XX", OP1r2.getLeft().toString());
|
|
||||||
assertEquals(2, OP1r2.getRight().getContextChanges().size());
|
|
||||||
assertEquals("ctx&F0:00:00:00 := 0x2( << 28)",
|
|
||||||
OP1r2.getRight().getContextChanges().get(0).toString());
|
|
||||||
assertEquals("ctx&F0:00:00:00 := 0x1( << 28)",
|
|
||||||
OP1r2.getRight().getContextChanges().get(1).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDSTr0_WithPatPhase1_WithTabDST() {
|
|
||||||
Pair<DisjointPattern, Constructor> DSTr0 = findConstructor("DST", "r0");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:SS:0X:XX:XX:XX)", DSTr0.getLeft().toString());
|
|
||||||
assertEquals(0, DSTr0.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOP1r3_WithPatPhase1_WithTabOP1() {
|
|
||||||
Pair<DisjointPattern, Constructor> OP1r3 = findConstructor("OP1", "r3");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:X3:XX:XX:XX)", OP1r3.getLeft().toString());
|
|
||||||
assertEquals(0, OP1r3.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOP2r1_WithPatPhase1_WithTabOP1() {
|
|
||||||
Pair<DisjointPattern, Constructor> OP2r1 = findConstructor("OP2", "r1");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:1X:XX:XX:XX)", OP2r1.getLeft().toString());
|
|
||||||
assertEquals(0, OP2r1.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOP2r0_WithPatPhase1_WithTabOP2() {
|
|
||||||
Pair<DisjointPattern, Constructor> OP2r0 = findConstructor("OP2", "r0");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:0X:XX:XX:XX)", OP2r0.getLeft().toString());
|
|
||||||
assertEquals(0, OP2r0.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNOP2_NoWith() {
|
|
||||||
Pair<DisjointPattern, Constructor> NOP2 = findConstructor("instruction", "NOP2");
|
|
||||||
assertEquals("ins:SS:XE:XX:XX:XX", NOP2.getLeft().toString());
|
|
||||||
assertEquals(0, NOP2.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testADD_NoWith() {
|
|
||||||
Pair<DisjointPattern, Constructor> ADD = findConstructor("instruction", "ADD");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:SS:X0:XX:XX:XX)", ADD.getLeft().toString());
|
|
||||||
assertEquals(0, ADD.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLD_NoWith() {
|
|
||||||
Pair<DisjointPattern, Constructor> LD = findConstructor("instruction", "LD");
|
|
||||||
assertEquals("cmb:(ctx:1X:XX:XX:XX,ins:SS:X8:XX:XX:XX)", LD.getLeft().toString());
|
|
||||||
assertEquals(0, LD.getRight().getContextChanges().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Explicit override of subtable in with
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue