factor GhidraScriptInfoManager out of GhidraScriptUtil

- move bundlehost to ghidrascriptmgrplugin
This commit is contained in:
Jason P. Leasure
2020-04-27 15:41:42 -04:00
parent a26ce496ef
commit 2b49816c6c
21 changed files with 375 additions and 344 deletions
@@ -54,9 +54,7 @@ public class BundleHost {
}
public void dispose() {
if (felix != null) {
forceStopFramework();
}
disposeFramework();
}
HashMap<ResourceFile, GhidraBundle> bp2gb = new HashMap<>();
@@ -503,14 +501,16 @@ public class BundleHost {
}
}
void forceStopFramework() {
try {
felix.stop();
felix.waitForStop(5000);
felix = null;
}
catch (BundleException | InterruptedException e) {
e.printStackTrace();
void disposeFramework() {
if (felix != null) {
try {
felix.stop();
felix.waitForStop(5000);
felix = null;
}
catch (BundleException | InterruptedException e) {
e.printStackTrace();
}
}
}
@@ -518,7 +518,7 @@ public class BundleHost {
Task t = new Task("killing OSGi framework", false, false, true, true) {
@Override
public void run(TaskMonitor monitor) throws CancelledException {
forceStopFramework();
disposeFramework();
}
};
@@ -599,10 +599,10 @@ public class BundleHost {
List<BundleHostListener> listeners = new ArrayList<>();
void fireBundleBuilt(GhidraBundle sbi) {
void fireBundleBuilt(GhidraBundle gb) {
synchronized (listeners) {
for (BundleHostListener l : listeners) {
l.bundleBuilt(sbi);
l.bundleBuilt(gb);
}
}
}
@@ -140,6 +140,11 @@ public class GhidraSourceBundle extends GhidraBundle {
Collectors.joining());
}
private String parseImps(ResourceFile javaSource) {
// XXX don't use @imports, use an annotation
return GhidraScriptUtil.newScriptInfo(javaSource).getImports();
}
/**
* update buildReqs based on \@imports tag in java files from the default package
*
@@ -155,8 +160,7 @@ public class GhidraSourceBundle extends GhidraBundle {
// this might be the earliest need for ScriptInfo, so allow construction.
// NB: ScriptInfo will update field values if lastModified has changed since last time they were computed
ScriptInfo si = GhidraScriptUtil.getScriptInfo(rf);
String imps = si.getImports();
String imps = parseImps(rf);
if (imps != null && !imps.isEmpty()) {
List<BundleRequirement> reqs;
try {
@@ -33,8 +33,7 @@ import docking.actions.KeyBindingUtils;
import docking.tool.ToolConstants;
import docking.widgets.table.GTable;
import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.ScriptInfo;
import ghidra.app.script.*;
import ghidra.framework.Application;
import ghidra.framework.options.SaveState;
import ghidra.util.*;
@@ -51,6 +50,7 @@ class GhidraScriptActionManager {
private GhidraScriptComponentProvider provider;
private GhidraScriptMgrPlugin plugin;
private GhidraScriptInfoManager infoManager;
private DockingAction refreshAction;
private DockingAction bundleStatusAction;
private DockingAction newAction;
@@ -65,10 +65,11 @@ class GhidraScriptActionManager {
private DockingAction helpAction;
private Map<ResourceFile, ScriptAction> actionMap = new HashMap<>();
GhidraScriptActionManager(GhidraScriptComponentProvider provider,
GhidraScriptMgrPlugin plugin) {
GhidraScriptActionManager(GhidraScriptComponentProvider provider, GhidraScriptMgrPlugin plugin,
GhidraScriptInfoManager infoManager) {
this.provider = provider;
this.plugin = plugin;
this.infoManager = infoManager;
createActions();
}
@@ -107,7 +108,7 @@ class GhidraScriptActionManager {
void restoreScriptsThatAreInTool(SaveState saveState) {
String[] array = saveState.getStrings(SCRIPT_ACTIONS_KEY, new String[0]);
for (String filename : array) {
ScriptInfo info = GhidraScriptUtil.findScriptByName(filename);
ScriptInfo info = infoManager.findScriptByName(filename);
if (info != null) { // the file may have been deleted from disk
provider.getActionManager().createAction(info.getSourceFile());
}
@@ -129,7 +130,7 @@ class GhidraScriptActionManager {
continue;
}
ResourceFile scriptFile = action.getScript();
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(scriptFile);
ScriptInfo info = infoManager.getExistingScriptInfo(scriptFile);
if (info == null) {
Msg.showError(this, provider.getComponent(), "Bad state?",
"action associated with a script that has no info");
@@ -71,6 +71,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
private RootNode scriptRoot;
private GTree scriptCategoryTree;
private DraggableScriptTable scriptTable;
private GhidraScriptInfoManager infoManager;
private GhidraScriptTableModel tableModel;
private BundleStatusComponentProvider bundleStatusComponentProvider;
private TaskListener taskListener = new ScriptTaskListener();
@@ -102,23 +103,12 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
final private RefreshingBundleHostListener refreshingBundleHostListener =
new RefreshingBundleHostListener();
static private int loaded = 0;
GhidraScriptComponentProvider(GhidraScriptMgrPlugin plugin) {
GhidraScriptComponentProvider(GhidraScriptMgrPlugin plugin, BundleHost bundleHost) {
super(plugin.getTool(), "Script Manager", plugin.getName());
this.plugin = plugin;
if (loaded == 0) {
bundleHost = new BundleHost();
GhidraScriptUtil.initialize(bundleHost);
bundleHost.addGhidraBundle(GhidraScriptUtil.getUserScriptDirectory(), true, false);
bundleHost.addGhidraBundles(GhidraScriptUtil.getSystemScriptPaths(), true, true);
}
else {
bundleHost = GhidraScriptUtil.getBundleHost();
}
loaded += 1;
this.bundleHost = bundleHost;
this.infoManager = new GhidraScriptInfoManager();
bundleStatusComponentProvider =
new BundleStatusComponentProvider(plugin.getTool(), plugin.getName(), bundleHost);
@@ -133,7 +123,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
build();
plugin.getTool().addComponentProvider(this, false);
actionManager = new GhidraScriptActionManager(this, plugin);
actionManager = new GhidraScriptActionManager(this, plugin, infoManager);
updateTitle();
}
@@ -171,7 +161,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
scriptCategoryTree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tableModel = new GhidraScriptTableModel(this);
tableModel = new GhidraScriptTableModel(this, infoManager);
scriptTable = new DraggableScriptTable(this, tableModel);
scriptTable.setName("SCRIPT_TABLE");
@@ -292,11 +282,6 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
tableFilterPanel.dispose();
actionManager.dispose();
bundleStatusComponentProvider.dispose();
loaded -= 1;
if (loaded == 0) {
GhidraScriptUtil.dispose();
}
}
public BundleHost getBundleHost() {
@@ -307,6 +292,10 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
return actionManager;
}
GhidraScriptInfoManager getInfoManager() {
return infoManager;
}
Map<ResourceFile, GhidraScriptEditorComponentProvider> getEditorMap() {
return editorMap;
}
@@ -410,6 +399,8 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
renameFile.delete();
return;
}
infoManager.removeMetadata(script);
if (actionManager.hasScriptAction(script)) {
KeyStroke ks = actionManager.getKeyBinding(script);
actionManager.removeAction(script);
@@ -417,9 +408,9 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
action.setKeyBindingData(new KeyBindingData(ks));
}
assert !GhidraScriptUtil.containsMetadata(
assert !infoManager.containsMetadata(
renameFile) : "renamed script already has metadata";
GhidraScriptUtil.getScriptInfo(renameFile);
infoManager.getScriptInfo(renameFile);
tableModel.switchScript(script, renameFile);
setSelectedScript(renameFile);
@@ -496,6 +487,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
if (removeScript(script)) {
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(script);
if (provider.deleteScript(script)) {
infoManager.removeMetadata(script);
restoreSelection(script);
}
else {
@@ -563,8 +555,8 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
// create the ScriptInfo object now, before the TableModelEvent handlers
// attempt to use it.
assert !GhidraScriptUtil.containsMetadata(newFile) : "new source already has metadata?";
GhidraScriptUtil.getScriptInfo(newFile);
assert !infoManager.containsMetadata(newFile) : "new source already has metadata?";
infoManager.getScriptInfo(newFile);
tableModel.insertScript(newFile);
@@ -710,8 +702,8 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
if (sb instanceof GhidraSourceBundle) {
GhidraSourceBundle gsb = (GhidraSourceBundle) sb;
for (ResourceFile sf : gsb.getNewSources()) {
if (GhidraScriptUtil.containsMetadata(sf)) {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(sf);
if (infoManager.containsMetadata(sf)) {
ScriptInfo info = infoManager.getExistingScriptInfo(sf);
BuildFailure e = gsb.getErrors(sf);
info.setCompileErrors(e != null);
}
@@ -753,7 +745,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
}
private void performRefresh() {
GhidraScriptUtil.clearMetadata();
infoManager.clearMetadata();
refresh();
}
@@ -787,7 +779,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
removeScript(file);
}
GhidraScriptUtil.refreshDuplicates();
infoManager.refreshDuplicates();
refreshScriptData();
}
@@ -808,7 +800,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
// new ScriptInfo objects are created on performRefresh, e.g. on startup. Other
// refresh operations might have old infos.
// assert !GhidraScriptUtil.containsMetadata(scriptFile): "info already exists for script during refresh";
ScriptInfo info = GhidraScriptUtil.getScriptInfo(scriptFile);
ScriptInfo info = infoManager.getScriptInfo(scriptFile);
String[] categoryPath = info.getCategory();
scriptRoot.insert(categoryPath);
}
@@ -823,7 +815,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
for (ResourceFile script : scripts) {
// First get the ScriptInfo object and refresh, which will ensure any
// info data (ie: script icons) will be reloaded.
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
info.refresh();
ScriptAction scriptAction = actionManager.get(script);
@@ -851,7 +843,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
// note: turn String[] to List<String> to use hashing
Set<List<String>> categories = new HashSet<>();
for (ScriptInfo info : GhidraScriptUtil.getScriptInfoIterable()) {
for (ScriptInfo info : infoManager.getScriptInfoIterable()) {
String[] path = info.getCategory();
List<String> category = Arrays.asList(path);
for (int i = 1; i <= category.size(); i++) {
@@ -938,7 +930,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
editorMap.put(newScript, editor);
editorMap.remove(oldScript);
// create corresponding info before inserting in table
GhidraScriptUtil.getScriptInfo(newScript);
infoManager.getScriptInfo(newScript);
tableModel.insertScript(newScript);
}
@@ -953,7 +945,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
}
actionManager.removeAction(script);
GhidraScriptUtil.removeMetadata(script);
infoManager.removeMetadata(script);
return true;
}
@@ -1012,7 +1004,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
// the selected script has been changed, update the description panel
updateDescriptionPanel();
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
updateCategoryTree(info.getCategory());
}
@@ -1029,7 +1021,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
@Override
public List<String> transform(ResourceFile script) {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
list.clear();
list.add(info.getName());
list.add(info.getDescription());
@@ -1063,7 +1055,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
String text = "Error! no script info!";
ResourceFile script = getSelectedScript();
if (script != null) {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
if (info != null) {
text = info.getToolTipText();
}
@@ -1200,7 +1192,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
@Override
public boolean acceptsRow(ResourceFile script) {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
String[] category = getSelectedCategoryPath();
if (category == null) { // root node
@@ -25,6 +25,8 @@ import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.plugin.core.eclipse.EclipseConnection;
import ghidra.app.plugin.core.eclipse.EclipseIntegrationOptionsPlugin;
import ghidra.app.plugin.core.osgi.BundleHost;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.GhidraState;
import ghidra.app.services.*;
import ghidra.framework.options.SaveState;
@@ -50,16 +52,31 @@ public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScript
final private GhidraScriptComponentProvider provider;
static private int loaded = 0;
final private BundleHost bundleHost;
public GhidraScriptMgrPlugin(PluginTool tool) {
super(tool, true, true, true);
if (loaded == 0) {
bundleHost = new BundleHost();
GhidraScriptUtil.initialize(bundleHost, null);
}
else {
bundleHost = GhidraScriptUtil.getBundleHost();
}
loaded += 1;
provider = new GhidraScriptComponentProvider(this);
provider = new GhidraScriptComponentProvider(this, bundleHost);
}
@Override
protected void dispose() {
super.dispose();
provider.dispose();
loaded -= 1;
if (loaded == 0) {
GhidraScriptUtil.dispose();
}
}
@Override
@@ -23,7 +23,7 @@ import javax.swing.*;
import docking.widgets.table.*;
import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.GhidraScriptInfoManager;
import ghidra.app.script.ScriptInfo;
import ghidra.docking.settings.Settings;
import ghidra.framework.plugintool.ServiceProvider;
@@ -44,10 +44,13 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
private GhidraScriptComponentProvider provider;
private List<ResourceFile> scriptList = new ArrayList<>();
final private GhidraScriptInfoManager infoManager;
GhidraScriptTableModel(GhidraScriptComponentProvider provider) {
GhidraScriptTableModel(GhidraScriptComponentProvider provider,
GhidraScriptInfoManager infoManager) {
super(provider.getTool());
this.provider = provider;
this.infoManager = infoManager;
}
@Override
@@ -105,7 +108,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
scriptList.add(script);
}
}
fireTableRowsInserted(rowStart, rowStart + scriptFiles.size()-1);
fireTableRowsInserted(rowStart, rowStart + scriptFiles.size() - 1);
}
void removeScript(ResourceFile script) {
@@ -238,7 +241,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
JLabel label = (JLabel) super.getTableCellRendererComponent(data);
ResourceFile file = (ResourceFile) data.getRowObject();
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(file);
ScriptInfo info = infoManager.getExistingScriptInfo(file);
label.setText(null);
label.setToolTipText(null);
@@ -279,7 +282,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
@Override
public ImageIcon getValue(ResourceFile rowObject, Settings settings, Object data,
ServiceProvider sp) throws IllegalArgumentException {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(rowObject);
ScriptInfo info = infoManager.getExistingScriptInfo(rowObject);
if (info.isCompileErrors() || info.isDuplicate()) {
return ERROR_IMG;
}
@@ -329,7 +332,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
@Override
public String getValue(ResourceFile rowObject, Settings settings, Object data,
ServiceProvider sp) throws IllegalArgumentException {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(rowObject);
ScriptInfo info = infoManager.getExistingScriptInfo(rowObject);
return info.getDescription();
}
@@ -401,7 +404,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
@Override
public KeyBindingsInfo getValue(ResourceFile rowObject, Settings settings, Object data,
ServiceProvider sp) throws IllegalArgumentException {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(rowObject);
ScriptInfo info = infoManager.getExistingScriptInfo(rowObject);
KeyStroke actionKeyStroke = provider.getActionManager().getKeyBinding(rowObject);
boolean isActionBinding = false;
KeyStroke keyBinding = info.getKeyBinding();
@@ -459,7 +462,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel<ResourceFile, Obje
@Override
public String getValue(ResourceFile rowObject, Settings settings, Object data,
ServiceProvider sp) throws IllegalArgumentException {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(rowObject);
ScriptInfo info = infoManager.getExistingScriptInfo(rowObject);
return getCategoryString(info);
}
@@ -36,7 +36,7 @@ import ghidra.app.script.*;
import ghidra.util.HelpLocation;
public class SaveDialog extends DialogComponentProvider implements ListSelectionListener {
private GhidraScriptComponentProvider componentProvider;
protected GhidraScriptComponentProvider componentProvider;
private GhidraScriptProvider provider;
private List<ResourceFile> paths;
@@ -49,7 +49,8 @@ public class SaveDialog extends DialogComponentProvider implements ListSelection
public SaveDialog(Component parent, String title,
GhidraScriptComponentProvider componentProvider, ResourceFile scriptFile,
HelpLocation help) {
this(parent, title, componentProvider, componentProvider.getWritableScriptDirectories(), scriptFile, help);
this(parent, title, componentProvider, componentProvider.getWritableScriptDirectories(),
scriptFile, help);
}
public SaveDialog(Component parent, String title,
@@ -161,7 +162,7 @@ public class SaveDialog extends DialogComponentProvider implements ListSelection
}
protected String getDuplicateNameErrorMessage(String name) {
ScriptInfo existingInfo = GhidraScriptUtil.getExistingScriptInfo(name);
ScriptInfo existingInfo = componentProvider.getInfoManager().getExistingScriptInfo(name);
if (existingInfo != null) {
// make sure the script has not been deleted
ResourceFile sourceFile = existingInfo.getSourceFile();
@@ -15,20 +15,18 @@
*/
package ghidra.app.plugin.core.script;
import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.util.HelpLocation;
import java.awt.Component;
import java.io.File;
import generic.jar.ResourceFile;
import ghidra.util.HelpLocation;
class SaveNewScriptDialog extends SaveDialog {
SaveNewScriptDialog(Component parent, String title,
GhidraScriptComponentProvider componentProvider, ResourceFile scriptFile,
HelpLocation help) {
super(parent, title, componentProvider, scriptFile, help);
}
/**
@@ -37,7 +35,7 @@ class SaveNewScriptDialog extends SaveDialog {
*/
@Override
protected String getDuplicateNameErrorMessage(String name) {
if (GhidraScriptUtil.alreadyExists(name)) {
if (componentProvider.getInfoManager().alreadyExists(name)) {
return "Duplicate script name.";
}
@@ -21,7 +21,7 @@ import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.GhidraScriptInfoManager;
import ghidra.app.script.ScriptInfo;
import ghidra.util.HelpLocation;
import ghidra.util.SystemUtilities;
@@ -30,6 +30,7 @@ class ScriptAction extends DockingAction {
private static final String SCRIPT_GROUP = "_SCRIPT_GROUP_";
private GhidraScriptMgrPlugin plugin;
private GhidraScriptInfoManager infoManager;
private ResourceFile script;
/** Signals that the keybinding value has been set by the user from the GUI (used for persistence) */
@@ -38,6 +39,7 @@ class ScriptAction extends DockingAction {
ScriptAction(GhidraScriptMgrPlugin plugin, ResourceFile script) {
super(script.getName(), plugin.getName());
this.plugin = plugin;
this.infoManager = plugin.getProvider().getInfoManager();
this.script = script;
setEnabled(true);
setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName()));
@@ -90,7 +92,7 @@ class ScriptAction extends DockingAction {
}
// check to see if we have a fallback value
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
KeyStroke metadataKeyStroke = info.getKeyBinding();
if (metadataKeyStroke == null) {
// there is no fallback value; the current keybinding data is what we want
@@ -105,7 +107,7 @@ class ScriptAction extends DockingAction {
// we have a user defined keybinding if the keystroke for the action differs from
// that which is defined in the metadata of the script
KeyStroke actionKeyStroke = keyBindingData.getKeyBinding();
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
KeyStroke metadataKeyBinding = info.getKeyBinding();
isUserDefinedKeyBinding = !SystemUtilities.isEqual(actionKeyStroke, metadataKeyBinding);
}
@@ -119,7 +121,7 @@ class ScriptAction extends DockingAction {
}
void refresh() {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(script);
ScriptInfo info = infoManager.getExistingScriptInfo(script);
KeyStroke stroke = info.getKeyBinding();
if (!isUserDefinedKeyBinding) {
setKeyBindingData(new KeyBindingData(stroke));
@@ -0,0 +1,193 @@
/* ###
* 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.app.script;
import java.util.*;
import generic.jar.ResourceFile;
import ghidra.util.Msg;
/**
* A utility class for managing script directories and ScriptInfo objects.
*/
public class GhidraScriptInfoManager {
private Map<ResourceFile, ScriptInfo> scriptFileToInfoMap = new HashMap<>();
private Map<String, List<ResourceFile>> scriptNameToFilesMap = new HashMap<>();
public void dispose() {
clearMetadata();
}
/**
* clear ScriptInfo metadata cached by GhidraScriptUtil
*/
public void clearMetadata() {
scriptFileToInfoMap.clear();
scriptNameToFilesMap.clear();
}
/**
* Removes the ScriptInfo object for the specified file
* @param scriptFile the script file
*/
public void removeMetadata(ResourceFile scriptFile) {
scriptFileToInfoMap.remove(scriptFile);
String name = scriptFile.getName();
List<ResourceFile> files = scriptNameToFilesMap.get(name);
if (files != null) {
Iterator<ResourceFile> iter = files.iterator();
while (iter.hasNext()) {
ResourceFile rFile = iter.next();
if (scriptFile.equals(rFile)) {
iter.remove();
break;
}
}
if (files.isEmpty()) {
scriptNameToFilesMap.remove(name);
}
}
}
/**
* get all scripts
* @return an iterable over all script info objects
*/
public Iterable<ScriptInfo> getScriptInfoIterable() {
return () -> scriptFileToInfoMap.values().iterator();
}
/**
* Returns the script info object for the specified script file,
* construct a new one if necessary.
*
* Only call this method if you expect to be creating ScriptInfo objects.
* Prefer getExistingScriptInfo instead.
*
* @param scriptFile the script file
* @return the script info object for the specified script file
*/
public ScriptInfo getScriptInfo(ResourceFile scriptFile) {
ScriptInfo info = scriptFileToInfoMap.get(scriptFile);
if (info != null) {
return info;
}
info = GhidraScriptUtil.newScriptInfo(scriptFile);
scriptFileToInfoMap.put(scriptFile, info);
String name = scriptFile.getName();
List<ResourceFile> matchingFiles =
scriptNameToFilesMap.computeIfAbsent(name, (n) -> new ArrayList<>());
matchingFiles.add(scriptFile);
markAnyDuplicates(matchingFiles);
return info;
}
/**
* Returns true if a ScriptInfo object exists for
* the specified script file.
* @param scriptFile the script file
* @return true if a ScriptInfo object exists
*/
public boolean containsMetadata(ResourceFile scriptFile) {
return scriptFileToInfoMap.containsKey(scriptFile);
}
public ScriptInfo getExistingScriptInfo(ResourceFile script) {
ScriptInfo info = scriptFileToInfoMap.get(script);
if (info == null) {
String s = (script.exists() ? "" : "non") + "existing script" + script.toString() +
" is missing expected ScriptInfo";
System.err.println(s);
Msg.showError(GhidraScriptInfoManager.class, null, "ScriptInfo lookup", s);
}
return info;
}
/**
* Returns the existing script info for the given name. The script environment limits
* scripts such that names are unique. If this method returns a non-null value, then the
* name given name is taken.
*
* @param scriptName the name of the script for which to get a ScriptInfo
* @return a ScriptInfo matching the given name; null if no script by that name is known to
* the script manager
*/
public ScriptInfo getExistingScriptInfo(String scriptName) {
List<ResourceFile> matchingFiles = scriptNameToFilesMap.get(scriptName);
if (matchingFiles == null || matchingFiles.isEmpty()) {
return null;
}
return scriptFileToInfoMap.get(matchingFiles.get(0));
}
/**
* Looks through all of the current {@link ScriptInfo}s to see if one already exists with
* the given name.
* @param scriptName The name to check
* @return true if the name is not taken by an existing {@link ScriptInfo}.
*/
public boolean alreadyExists(String scriptName) {
return getExistingScriptInfo(scriptName) != null;
}
private void markAnyDuplicates(List<ResourceFile> files) {
boolean isDuplicate = files.size() > 1;
files.forEach(f -> scriptFileToInfoMap.get(f).setDuplicate(isDuplicate));
}
/**
* Updates every known script's duplicate value.
*/
public void refreshDuplicates() {
scriptNameToFilesMap.values().forEach(files -> {
boolean isDuplicate = files.size() > 1;
files.forEach(file -> scriptFileToInfoMap.get(file).setDuplicate(isDuplicate));
});
}
/**
* Uses the given name to find a matching script. This method only works because of the
* limitation that all script names in Ghidra must be unique. If the given name has multiple
* script matches, then a warning will be logged.
*
* @param name The name for which to find a script
* @return The ScriptInfo that has the given name
*/
public ScriptInfo findScriptByName(String name) {
List<ResourceFile> matchingFiles = scriptNameToFilesMap.get(name);
if (matchingFiles != null && !matchingFiles.isEmpty()) {
ScriptInfo info = scriptFileToInfoMap.get(matchingFiles.get(0));
if (matchingFiles.size() > 1) {
Msg.warn(GhidraScriptInfoManager.class, "Found duplicate scripts for name: " +
name + ". Binding to script: " + info.getSourceFile());
}
return info;
}
ResourceFile file = GhidraScriptUtil.findScriptFileInPaths(
GhidraScriptUtil.getBundleHost().getBundlePaths(), name);
if (file == null) {
return null;
}
return getExistingScriptInfo(file); // this will cache the created info
}
}
@@ -15,19 +15,19 @@
*/
package ghidra.app.script;
import generic.jar.ResourceFile;
import ghidra.util.classfinder.ExtensionPoint;
import java.io.IOException;
import java.io.PrintWriter;
import generic.jar.ResourceFile;
import ghidra.util.classfinder.ExtensionPoint;
/**
* NOTE: ALL GhidraScriptProvider CLASSES MUST END IN "ScriptProvider". If not,
* the ClassSearcher will not find them.
*
*/
public abstract class GhidraScriptProvider implements ExtensionPoint,
Comparable<GhidraScriptProvider> {
public abstract class GhidraScriptProvider
implements ExtensionPoint, Comparable<GhidraScriptProvider> {
@Override
public String toString() {
@@ -59,11 +59,7 @@ public abstract class GhidraScriptProvider implements ExtensionPoint,
* @return true if the script was completely deleted and cleaned up
*/
public boolean deleteScript(ResourceFile scriptSource) {
boolean deleted = !scriptSource.exists() || scriptSource.delete();
if (deleted) {
GhidraScriptUtil.removeMetadata(scriptSource);
}
return deleted;
return !scriptSource.exists() || scriptSource.delete();
}
/**
@@ -44,17 +44,13 @@ public class GhidraScriptUtil {
*/
public static String USER_SCRIPTS_DIR = buildUserScriptsDirectory();
private static Map<ResourceFile, ScriptInfo> scriptFileToInfoMap = new HashMap<>();
private static Map<String, List<ResourceFile>> scriptNameToFilesMap = new HashMap<>();
static BundleHost _bundleHost;
public static BundleHost getBundleHost() {
return _bundleHost;
}
public static void initialize(BundleHost bundleHost) {
private static void setBundleHost(BundleHost bundleHost) {
if (_bundleHost != null) {
throw new RuntimeException("GhidraScriptUtil initialized multiple times!");
}
@@ -70,15 +66,14 @@ public class GhidraScriptUtil {
}
/**
* initialization for headless runs.
* initialize state of GhidraScriptUtil with user, system paths, and optional extra system paths.
*
* @param bundleHost the host to use
* @param extraSystemPaths additional system paths for this run, can be null
*
*/
public static void initialize(BundleHost bundleHost, List<String> extraSystemPaths) {
initialize(bundleHost);
setBundleHost(bundleHost);
if (extraSystemPaths != null) {
for (String path : extraSystemPaths) {
bundleHost.addGhidraBundle(new ResourceFile(path), true, true);
@@ -90,19 +85,13 @@ public class GhidraScriptUtil {
}
public static void dispose() {
clearMetadata();
_bundleHost = null;
if (_bundleHost != null) {
_bundleHost.dispose();
_bundleHost = null;
}
providers = null;
}
/**
* clear ScriptInfo metadata cached by GhidraScriptUtil
*/
public static void clearMetadata() {
scriptFileToInfoMap.clear();
scriptNameToFilesMap.clear();
}
/**
* Returns a list of the current script directories.
* @return a list of the current script directories
@@ -112,6 +101,20 @@ public class GhidraScriptUtil {
Collectors.toList());
}
public static ResourceFile getSourceDirectoryContaining(ResourceFile sourceFile) {
String sourcePath = sourceFile.getAbsolutePath();
for (ResourceFile sourceDir : getScriptSourceDirectories()) {
if (sourcePath.startsWith(sourceDir.getAbsolutePath() + File.separatorChar)) {
return sourceDir;
}
}
return null;
}
public static ResourceFile findScriptByName(String scriptName) {
return findScriptFileInPaths(getScriptSourceDirectories(), scriptName);
}
/**
* User's home scripts directory. Some tests may override the default using the
* SystemUtilities.USER_SCRIPTS_DIR system property.
@@ -224,130 +227,6 @@ public class GhidraScriptUtil {
return name.substring(0, pos);
}
/**
* Removes the ScriptInfo object for the specified file
* @param scriptFile the script file
*/
public static void removeMetadata(ResourceFile scriptFile) {
scriptFileToInfoMap.remove(scriptFile);
String name = scriptFile.getName();
List<ResourceFile> files = scriptNameToFilesMap.get(name);
if (files != null) {
Iterator<ResourceFile> iter = files.iterator();
while (iter.hasNext()) {
ResourceFile rFile = iter.next();
if (scriptFile.equals(rFile)) {
iter.remove();
break;
}
}
if (files.isEmpty()) {
scriptNameToFilesMap.remove(name);
}
}
}
/**
* get all scripts
* @return an iterable over all script info objects
*/
public static Iterable<ScriptInfo> getScriptInfoIterable() {
return () -> scriptFileToInfoMap.values().iterator();
}
/**
* Returns the script info object for the specified script file,
* construct a new one if necessary.
*
* Only call this method if you expect to be creating ScriptInfo objects.
* Prefer getExistingScriptInfo instead.
*
* @param scriptFile the script file
* @return the script info object for the specified script file
*/
public static ScriptInfo getScriptInfo(ResourceFile scriptFile) {
ScriptInfo info = scriptFileToInfoMap.get(scriptFile);
if (info != null) {
return info;
}
GhidraScriptProvider gsp = getProvider(scriptFile);
info = new ScriptInfo(gsp, scriptFile);
scriptFileToInfoMap.put(scriptFile, info);
String name = scriptFile.getName();
List<ResourceFile> matchingFiles =
scriptNameToFilesMap.computeIfAbsent(name, (n) -> new ArrayList<>());
matchingFiles.add(scriptFile);
markAnyDuplicates(matchingFiles);
return info;
}
/**
* Returns true if a ScriptInfo object exists for
* the specified script file.
* @param scriptFile the script file
* @return true if a ScriptInfo object exists
*/
public static boolean containsMetadata(ResourceFile scriptFile) {
return scriptFileToInfoMap.containsKey(scriptFile);
}
public static ScriptInfo getExistingScriptInfo(ResourceFile script) {
ScriptInfo info = scriptFileToInfoMap.get(script);
if (info == null) {
String s = (script.exists() ? "" : "non") + "existing script" + script.toString() +
" is missing info we thought was there";
System.err.println(s);
Msg.showError(GhidraScriptUtil.class, null, "ScriptInfo lookup", s);
}
return info;
}
/**
* Returns the existing script info for the given name. The script environment limits
* scripts such that names are unique. If this method returns a non-null value, then the
* name given name is taken.
*
* @param scriptName the name of the script for which to get a ScriptInfo
* @return a ScriptInfo matching the given name; null if no script by that name is known to
* the script manager
*/
public static ScriptInfo getExistingScriptInfo(String scriptName) {
List<ResourceFile> matchingFiles = scriptNameToFilesMap.get(scriptName);
if (matchingFiles == null || matchingFiles.isEmpty()) {
return null;
}
return scriptFileToInfoMap.get(matchingFiles.get(0));
}
/**
* Looks through all of the current {@link ScriptInfo}s to see if one already exists with
* the given name.
* @param scriptName The name to check
* @return true if the name is not taken by an existing {@link ScriptInfo}.
*/
public static boolean alreadyExists(String scriptName) {
return getExistingScriptInfo(scriptName) != null;
}
private static void markAnyDuplicates(List<ResourceFile> files) {
boolean isDuplicate = files.size() > 1;
files.forEach(f -> scriptFileToInfoMap.get(f).setDuplicate(isDuplicate));
}
/**
* Updates every known script's duplicate value.
*/
public static void refreshDuplicates() {
scriptNameToFilesMap.values().forEach(files -> {
boolean isDuplicate = files.size() > 1;
files.forEach(file -> scriptFileToInfoMap.get(file).setDuplicate(isDuplicate));
});
}
/**
* Returns a list of all Ghidra script providers
*
@@ -435,6 +314,10 @@ public class GhidraScriptUtil {
return new ResourceFile(parentDirctory, className);
}
public static ScriptInfo newScriptInfo(ResourceFile file) {
return new ScriptInfo(getProvider(file), file);
}
/**
* Fixup name issues, such as package parts in the name and inner class names.
* <p>
@@ -457,8 +340,8 @@ public class GhidraScriptUtil {
return path + ".java";
}
/** Returns true if the given filename exists in any of the given directories */
private static ResourceFile findScriptFileInPaths(Collection<ResourceFile> scriptDirectories,
static ResourceFile findScriptFileInPaths(
Collection<ResourceFile> scriptDirectories,
String filename) {
String validatedName = fixupName(filename);
@@ -474,33 +357,6 @@ public class GhidraScriptUtil {
return null;
}
/**
* Uses the given name to find a matching script. This method only works because of the
* limitation that all script names in Ghidra must be unique. If the given name has multiple
* script matches, then a warning will be logged.
*
* @param name The name for which to find a script
* @return The ScriptInfo that has the given name
*/
public static ScriptInfo findScriptByName(String name) {
List<ResourceFile> matchingFiles = scriptNameToFilesMap.get(name);
if (matchingFiles != null && !matchingFiles.isEmpty()) {
ScriptInfo info = scriptFileToInfoMap.get(matchingFiles.get(0));
if (matchingFiles.size() > 1) {
Msg.warn(GhidraScriptUtil.class, "Found duplicate scripts for name: " + name +
". Binding to script: " + info.getSourceFile());
}
return info;
}
ResourceFile file = findScriptFileInPaths(_bundleHost.getBundlePaths(), name);
if (file == null) {
return null;
}
return getExistingScriptInfo(file); // this will cache the created info
}
/* only used by GhidraScriptAnalyzerAdapter */
/**
* Runs the specified script with the specified state
@@ -537,31 +393,4 @@ public class GhidraScriptUtil {
return true;
}
@Deprecated
private static void updateAvailableScriptFilesForDirectory(List<ResourceFile> scriptAccumulator,
ResourceFile directory) {
ResourceFile[] files = directory.listFiles();
if (files == null) {
return;
}
for (ResourceFile scriptFile : files) {
if (scriptFile.isFile() && hasScriptProvider(scriptFile)) {
scriptAccumulator.add(scriptFile);
}
}
}
/*
* used only by RecipeEditorDialog
*/
@Deprecated
public static List<ResourceFile> getAllScripts() {
List<ResourceFile> scriptList = new ArrayList<>();
for (ResourceFile dirPath : _bundleHost.getBundlePaths()) {
updateAvailableScriptFilesForDirectory(scriptList, dirPath);
}
return scriptList;
}
}
@@ -31,7 +31,7 @@ public class JavaScriptProvider extends GhidraScriptProvider {
}
public GhidraSourceBundle getBundleForSource(ResourceFile sourceFile) {
ResourceFile sourceDir = getSourceDirectoryContaining(sourceFile);
ResourceFile sourceDir = GhidraScriptUtil.getSourceDirectoryContaining(sourceFile);
if (sourceDir == null) {
return null;
}
@@ -67,8 +67,6 @@ public class JavaScriptProvider extends GhidraScriptProvider {
@Override
public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter writer)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// in headless operation, ScriptInfo objects can be created here
ScriptInfo info = GhidraScriptUtil.getScriptInfo(sourceFile);
try {
Class<?> clazz = loadClass(sourceFile, writer);
Object object;
@@ -83,16 +81,13 @@ public class JavaScriptProvider extends GhidraScriptProvider {
String message = "Not a valid Ghidra script: " + sourceFile.getName();
writer.println(message);
Msg.error(this, message);
info.setCompileErrors(true);
return null; // class is not GhidraScript
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
info.setCompileErrors(true);
throw e;
}
catch (Exception e) {
info.setCompileErrors(true);
throw new ClassNotFoundException("", e);
}
}
@@ -109,16 +104,6 @@ public class JavaScriptProvider extends GhidraScriptProvider {
return clazz;
}
public static ResourceFile getSourceDirectoryContaining(ResourceFile sourceFile) {
String sourcePath = sourceFile.getAbsolutePath();
for (ResourceFile sourceDir : GhidraScriptUtil.getScriptSourceDirectories()) {
if (sourcePath.startsWith(sourceDir.getAbsolutePath() + File.separatorChar)) {
return sourceDir;
}
}
return null;
}
@Override
public void createNewScript(ResourceFile newScript, String category) throws IOException {
String scriptName = newScript.getName();
@@ -78,7 +78,7 @@ public class ScriptInfo {
* @param provider the script provider (for example, java or python)
* @param sourceFile the script source file
*/
public ScriptInfo(GhidraScriptProvider provider, ResourceFile sourceFile) {
ScriptInfo(GhidraScriptProvider provider, ResourceFile sourceFile) {
this.provider = provider;
this.sourceFile = sourceFile;
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,13 +15,12 @@
*/
package ghidra.framework.analysis;
import org.jdom.Element;
import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.ScriptInfo;
import ghidra.app.services.*;
import org.jdom.Element;
class AnalyzerInfo implements Comparable<AnalyzerInfo> {
static final String XML_ELEMENT_NAME = "ANALYZER";
static final String CLASS_NAME = "CLASS_NAME";
@@ -48,10 +46,12 @@ class AnalyzerInfo implements Comparable<AnalyzerInfo> {
// first make all One-Shot Analyzers sort before all other types.
AnalyzerType myType = analyzer.getAnalysisType();
AnalyzerType otherType = o.analyzer.getAnalysisType();
if (myType == AnalyzerType.ONE_SHOT_ANALYZER && otherType != AnalyzerType.ONE_SHOT_ANALYZER) {
if (myType == AnalyzerType.ONE_SHOT_ANALYZER &&
otherType != AnalyzerType.ONE_SHOT_ANALYZER) {
return -1;
}
if (myType != AnalyzerType.ONE_SHOT_ANALYZER && otherType == AnalyzerType.ONE_SHOT_ANALYZER) {
if (myType != AnalyzerType.ONE_SHOT_ANALYZER &&
otherType == AnalyzerType.ONE_SHOT_ANALYZER) {
return 1;
}
@@ -125,13 +125,13 @@ class AnalyzerInfo implements Comparable<AnalyzerInfo> {
return startPhase;
}
public static AnalyzerInfo createInfoForWrappedAnalzyer(AnalysisRecipe recipe, Element element) {
public static AnalyzerInfo createInfoForWrappedAnalzyer(AnalysisRecipe recipe,
Element element) {
String scriptName = element.getAttributeValue("SCRIPT_NAME");
String type = element.getAttributeValue("ANALYZER_TYPE");
AnalyzerType analyzerType = AnalyzerType.valueOf(type);
int priority = Integer.parseInt(element.getAttributeValue("PRIORITY"));
ScriptInfo scriptInfo = GhidraScriptUtil.findScriptByName(scriptName);
ResourceFile file = scriptInfo.getSourceFile();
ResourceFile file = GhidraScriptUtil.findScriptByName(scriptName);
Analyzer analyzer = new GhidraScriptAnalyzerAdapter(file, analyzerType, priority);
return new AnalyzerInfo(recipe, analyzer, true);
}
@@ -48,7 +48,7 @@ public class GhidraScriptAnalyzerAdapter extends AbstractAnalyzer {
}
private static String getDescription(ResourceFile file) {
return GhidraScriptUtil.getScriptInfo(file).getDescription();
return GhidraScriptUtil.newScriptInfo(file).getDescription();
}
public void setPrintWriter(PrintWriter writer) {
@@ -26,7 +26,6 @@ import docking.widgets.label.GLabel;
import docking.widgets.textfield.IntegerTextField;
import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.ScriptInfo;
import ghidra.app.services.AnalyzerType;
import ghidra.util.layout.HorizontalLayout;
import ghidra.util.layout.VerticalLayout;
@@ -36,8 +35,9 @@ public class GhidraScriptSelectionDialog extends ListSelectionDialog<ResourceFil
private IntegerTextField priorityField;
public GhidraScriptSelectionDialog() {
super("Create Script Based Analyzer", "Script Name:", GhidraScriptUtil.getAllScripts(),
new ScriptNameConverter(), new ScriptDescriptionConverter());
super("Create Script Based Analyzer", "Script Name:",
GhidraScriptUtil.getScriptSourceDirectories(), new ScriptNameConverter(),
new ScriptDescriptionConverter());
}
@Override
@@ -116,8 +116,7 @@ public class GhidraScriptSelectionDialog extends ListSelectionDialog<ResourceFil
private static class ScriptDescriptionConverter implements DataToStringConverter<ResourceFile> {
@Override
public String getString(ResourceFile resourceFile) {
ScriptInfo info = GhidraScriptUtil.getScriptInfo(resourceFile);
return info.getDescription();
return GhidraScriptUtil.newScriptInfo(resourceFile).getDescription();
}
}
@@ -231,13 +231,12 @@ public abstract class AbstractGhidraScriptMgrPluginTest
}
protected void assertScriptManagerKnowsAbout(ResourceFile script) {
assertTrue(GhidraScriptUtil.containsMetadata(script));
assertTrue(provider.getInfoManager().containsMetadata(script));
assertNull(provider.getActionManager().get(script));
}
protected void assertScriptManagerForgotAbout(ResourceFile script) {
assertFalse(GhidraScriptUtil.containsMetadata(script));
assertFalse(provider.getInfoManager().containsMetadata(script));
assertNull(provider.getActionManager().get(script));
assertNull(provider.getEditorMap().get(script));
}
@@ -989,7 +988,8 @@ public abstract class AbstractGhidraScriptMgrPluginTest
// destroy any NewScriptxxx files...and Temp ones too
BundleStatusComponentProvider bundleStatusComponentProvider =
(BundleStatusComponentProvider) TestUtils.getInstanceField("bundleStatusComponentProvider", provider);
(BundleStatusComponentProvider) TestUtils.getInstanceField(
"bundleStatusComponentProvider", provider);
List<ResourceFile> paths = bundleStatusComponentProvider.getModel().getEnabledPaths();
for (ResourceFile path : paths) {
@@ -1161,7 +1161,7 @@ public abstract class AbstractGhidraScriptMgrPluginTest
}
protected ResourceFile findScript(String name) {
ScriptInfo info = GhidraScriptUtil.getExistingScriptInfo(name);
ScriptInfo info = provider.getInfoManager().getExistingScriptInfo(name);
assertNotNull("Cannot find script by the given name: " + name, info);
return info.getSourceFile();
}
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +15,9 @@
*/
package ghidra.app.plugin.prototype.MicrosoftCodeAnalyzerPlugin;
import java.io.PrintWriter;
import generic.jar.ResourceFile;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.script.*;
import ghidra.app.services.*;
@@ -32,8 +34,6 @@ import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.io.PrintWriter;
public class WindowsResourceReferenceAnalyzer extends AbstractAnalyzer {
private static final String NAME = "WindowsResourceReference";
private static final String DESCRIPTION =
@@ -81,23 +81,21 @@ public class WindowsResourceReferenceAnalyzer extends AbstractAnalyzer {
PluginTool tool = analysisManager.getAnalysisTool();
Project project = findProject(tool);
GhidraState state =
new GhidraState(tool, project, program, new ProgramLocation(program,
set.getMinAddress()), new ProgramSelection(set), null);
GhidraState state = new GhidraState(tool, project, program,
new ProgramLocation(program, set.getMinAddress()), new ProgramSelection(set), null);
try {
ScriptInfo scriptInfo = GhidraScriptUtil.findScriptByName(scriptName);
if (scriptInfo == null) {
ResourceFile sourceFile = GhidraScriptUtil.findScriptByName(scriptName);
if (sourceFile == null) {
throw new IllegalAccessException("Couldn't find script");
}
GhidraScriptProvider provider =
GhidraScriptUtil.getProvider(scriptInfo.getSourceFile());
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(sourceFile);
if (provider == null) {
throw new IllegalAccessException("Couldn't find script provider");
}
PrintWriter writer = getOutputMsgStream(tool);
GhidraScript script = provider.getScriptInstance(scriptInfo.getSourceFile(), writer);
GhidraScript script = provider.getScriptInstance(sourceFile, writer);
script.set(state, monitor, writer);
// This code was added so the analyzer won't print script messages to console
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import org.junit.*;
import generic.jar.ResourceFile;
import ghidra.app.plugin.core.osgi.BundleHost;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.services.*;
import ghidra.framework.task.GScheduledTask;
@@ -77,6 +78,12 @@ public class AnalysisManagerTest extends AbstractGhidraHeadlessIntegrationTest {
programBuilder.createMemory("AAA", "0x100", 0x1000);
program = programBuilder.getProgram();
analyzers = new ArrayList<>();
GhidraScriptUtil.initialize(new BundleHost(), null);
}
@After
public void cleanup() {
GhidraScriptUtil.dispose();
}
@Test
@@ -21,11 +21,11 @@ import java.util.ArrayList;
import java.util.List;
import org.jdom.Element;
import org.junit.Before;
import org.junit.Test;
import org.junit.*;
import generic.jar.ResourceFile;
import ghidra.app.plugin.core.osgi.BundleHost;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.ScriptInfo;
import ghidra.app.services.*;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB;
@@ -47,6 +47,12 @@ public class AnalysisRecipeTest extends AbstractGhidraHeadlessIntegrationTest {
programBuilder.createMemory("AAA", "0x100", 0x1000);
program = programBuilder.getProgram();
analyzers = new ArrayList<>();
GhidraScriptUtil.initialize(new BundleHost(), null);
}
@After
public void cleanup() {
GhidraScriptUtil.dispose();
}
@Test
@@ -88,9 +94,9 @@ public class AnalysisRecipeTest extends AbstractGhidraHeadlessIntegrationTest {
analyzers.add(analyzer1);
analyzers.add(analyzer2);
recipe = new AnalysisRecipe("Test Recipe", analyzers, program);
ScriptInfo info = GhidraScriptUtil.findScriptByName("HelloWorldScript.java");
assertNotNull(info);
recipe.addScriptAnalyzer(info.getSourceFile(), AnalyzerType.INSTRUCTION_ANALYZER, 15);
ResourceFile sourceFile = GhidraScriptUtil.findScriptByName("HelloWorldScript.java");
assertNotNull(sourceFile);
recipe.addScriptAnalyzer(sourceFile, AnalyzerType.INSTRUCTION_ANALYZER, 15);
AnalysisPhase lastPhase = recipe.getLastPhase();
AnalysisPhase firstPhase = recipe.createPhase();