From 2b49816c6cf45b5d23706c69bed46e49f0acd8c5 Mon Sep 17 00:00:00 2001 From: "Jason P. Leasure" Date: Mon, 27 Apr 2020 15:41:42 -0400 Subject: [PATCH] factor GhidraScriptInfoManager out of GhidraScriptUtil - move bundlehost to ghidrascriptmgrplugin --- .../app/plugin/core/osgi/BundleHost.java | 28 +-- .../plugin/core/osgi/GhidraSourceBundle.java | 8 +- .../script/GhidraScriptActionManager.java | 13 +- .../script/GhidraScriptComponentProvider.java | 68 +++--- .../core/script/GhidraScriptMgrPlugin.java | 19 +- .../core/script/GhidraScriptTableModel.java | 19 +- .../app/plugin/core/script/SaveDialog.java | 7 +- .../core/script/SaveNewScriptDialog.java | 10 +- .../app/plugin/core/script/ScriptAction.java | 10 +- .../app/script/GhidraScriptInfoManager.java | 193 +++++++++++++++ .../app/script/GhidraScriptProvider.java | 16 +- .../ghidra/app/script/GhidraScriptUtil.java | 225 +++--------------- .../ghidra/app/script/JavaScriptProvider.java | 17 +- .../java/ghidra/app/script/ScriptInfo.java | 2 +- .../framework/analysis/AnalyzerInfo.java | 18 +- .../analysis/GhidraScriptAnalyzerAdapter.java | 2 +- .../gui/GhidraScriptSelectionDialog.java | 9 +- .../AbstractGhidraScriptMgrPluginTest.java | 10 +- .../WindowsResourceReferenceAnalyzer.java | 20 +- .../analysis/AnalysisManagerTest.java | 7 + .../analysis/AnalysisRecipeTest.java | 18 +- 21 files changed, 375 insertions(+), 344 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptInfoManager.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java index 0f8e66345e..458bd9b5ea 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java @@ -54,9 +54,7 @@ public class BundleHost { } public void dispose() { - if (felix != null) { - forceStopFramework(); - } + disposeFramework(); } HashMap 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 listeners = new ArrayList<>(); - void fireBundleBuilt(GhidraBundle sbi) { + void fireBundleBuilt(GhidraBundle gb) { synchronized (listeners) { for (BundleHostListener l : listeners) { - l.bundleBuilt(sbi); + l.bundleBuilt(gb); } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/GhidraSourceBundle.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/GhidraSourceBundle.java index 67202972ae..85a6534365 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/GhidraSourceBundle.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/GhidraSourceBundle.java @@ -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 reqs; try { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java index 941121f48d..99ee86620d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java @@ -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 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"); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java index e34a3eef92..fb1af03f0e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java @@ -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 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 to use hashing Set> categories = new HashSet<>(); - for (ScriptInfo info : GhidraScriptUtil.getScriptInfoIterable()) { + for (ScriptInfo info : infoManager.getScriptInfoIterable()) { String[] path = info.getCategory(); List 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 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 diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java index d32df4dfaa..38b91d9eca 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java @@ -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 diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java index e1c27dfcbd..6eabde2ced 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java @@ -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 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 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(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/SaveNewScriptDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/SaveNewScriptDialog.java index 383e900785..3551c56f40 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/SaveNewScriptDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/SaveNewScriptDialog.java @@ -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."; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/ScriptAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/ScriptAction.java index 443933c57f..9d6d3a87c3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/ScriptAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/ScriptAction.java @@ -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)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptInfoManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptInfoManager.java new file mode 100644 index 0000000000..77b82255a9 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptInfoManager.java @@ -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 scriptFileToInfoMap = new HashMap<>(); + private Map> 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 files = scriptNameToFilesMap.get(name); + if (files != null) { + Iterator 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 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 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 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 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 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 + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java index 0fca25bd82..a9f18480ab 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java @@ -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 { +public abstract class GhidraScriptProvider + implements ExtensionPoint, Comparable { @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(); } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java index 33fb48b025..d84f1e0884 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java @@ -44,17 +44,13 @@ public class GhidraScriptUtil { */ public static String USER_SCRIPTS_DIR = buildUserScriptsDirectory(); - private static Map scriptFileToInfoMap = new HashMap<>(); - - private static Map> 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 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 files = scriptNameToFilesMap.get(name); - if (files != null) { - Iterator 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 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 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 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 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. *

@@ -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 scriptDirectories, + static ResourceFile findScriptFileInPaths( + Collection 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 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 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 getAllScripts() { - List scriptList = new ArrayList<>(); - for (ResourceFile dirPath : _bundleHost.getBundlePaths()) { - updateAvailableScriptFilesForDirectory(scriptList, dirPath); - } - return scriptList; - } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/JavaScriptProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/JavaScriptProvider.java index a6cf13aba0..dd0e5f1ddd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/JavaScriptProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/JavaScriptProvider.java @@ -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(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java index 51c2032627..2bb59ec05c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java @@ -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; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/AnalyzerInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/AnalyzerInfo.java index 288f6358bf..933f8b8f3d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/AnalyzerInfo.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/AnalyzerInfo.java @@ -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 { static final String XML_ELEMENT_NAME = "ANALYZER"; static final String CLASS_NAME = "CLASS_NAME"; @@ -48,10 +46,12 @@ class AnalyzerInfo implements Comparable { // 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 { 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); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/GhidraScriptAnalyzerAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/GhidraScriptAnalyzerAdapter.java index 391f50d46b..5a3219450c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/GhidraScriptAnalyzerAdapter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/GhidraScriptAnalyzerAdapter.java @@ -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) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/gui/GhidraScriptSelectionDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/gui/GhidraScriptSelectionDialog.java index 9dc5562200..c199fb8359 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/gui/GhidraScriptSelectionDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/analysis/gui/GhidraScriptSelectionDialog.java @@ -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 { @Override public String getString(ResourceFile resourceFile) { - ScriptInfo info = GhidraScriptUtil.getScriptInfo(resourceFile); - return info.getDescription(); + return GhidraScriptUtil.newScriptInfo(resourceFile).getDescription(); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AbstractGhidraScriptMgrPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AbstractGhidraScriptMgrPluginTest.java index 2dab082b00..c3a3b7ea11 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AbstractGhidraScriptMgrPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AbstractGhidraScriptMgrPluginTest.java @@ -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 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(); } diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/WindowsResourceReferenceAnalyzer.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/WindowsResourceReferenceAnalyzer.java index bef3831a86..ef3bacf2e5 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/WindowsResourceReferenceAnalyzer.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/WindowsResourceReferenceAnalyzer.java @@ -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 diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisManagerTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisManagerTest.java index a1bf6470aa..7ae454ef8b 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisManagerTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisManagerTest.java @@ -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 diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisRecipeTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisRecipeTest.java index 905704b6f0..39f1bdfc32 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisRecipeTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/analysis/AnalysisRecipeTest.java @@ -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();