diff --git a/Ghidra/Features/Base/certification.manifest b/Ghidra/Features/Base/certification.manifest
index 8afcc61691..98ad1f984a 100644
--- a/Ghidra/Features/Base/certification.manifest
+++ b/Ghidra/Features/Base/certification.manifest
@@ -437,6 +437,7 @@ src/main/help/help/topics/GhidraScriptMgrPlugin/images/text_list_bullets.png||FA
src/main/help/help/topics/GhidraScriptMgrPlugin/images/text_lowercase.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/GhidraScriptMgrPlugin/images/textfield_rename.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/GhidraScriptMgrPlugin/images/undo.png||GHIDRA||||END|
+src/main/help/help/topics/BundleManager/BundleManager.htm||GHIDRA||||END|
src/main/help/help/topics/GhidraServer/GhidraServer.htm||GHIDRA||||END|
src/main/help/help/topics/Glossary/glossary.htm||GHIDRA||||END|
src/main/help/help/topics/Glossary/images/BigEndian.png||GHIDRA||reviewed||END|
diff --git a/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml b/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml
index d154fd594e..9a27608027 100644
--- a/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml
+++ b/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml
@@ -354,9 +354,10 @@
Scripting brings a poweful form of dynamic extensibilty to Ghidra,
+ where Java source code is (re)compiled, loaded, and run without exiting
+ Ghidra. When a script grows large or requires external dependencies, it
+ might be worth the effort think of how to split up code into sensible
+ pieces, or modules. To support modularity while preserving the dynamic nature of scripts,
+ Ghidra uses OSGi. Without delving too
+ much into terminology, the key things to know are When a directory is added to the Bundle Manager, it is treated as a
+ source bundle and of its Java contents will be compiled to
+ Each subdirectory of
+ If there is no manifest in the source directory, Ghidra generates one
+ using bndlib so that:
+
+ If no bundle activator is present, a stub is created and referenced in the generated manifest.
+ Two basic types of code dependency are available when developing with
+ OSGi, intra-bundle and inter-bundle. Classes within a bundle, e.g. source files in a source bundle, can rely
+ one another with Java's usual package This kind of dependency is resolved at compile time -- if a class isn't
+ imported or present, compilation will fail! To make use of code from other bundles, a bundle must declare its
+ requirements. When a bundle is activated, the framework attempts to
+ resolve its declared dependencies against active bundles. The
+ first match, in the order those bundles were activated, will be "wired" to
+ the dependent. Note: OSGi bundle dependency is very similar to Java 9 modules, except
+ that Java 9 modules provide load time resolution. Via the Jar manifest, there are multiple ways to configure the
+ requirements of a bundle. We'll describe only one, the
+ You can find more detail at https://osgi.org for more detail. These examples should demonstrated the most common usage. Note: the
+ file If a source bundle includes a file Ghidra provides a shortcut to populate Adding a directory to the bundle manager and then enabling it makes any
+ contained scripts visible in the script manager. Removing a bundle deactives, disables, and removes it from the list. In order to make a bundle's contents available to other bundles, it must
+ be activated. This corresponds the OSGi bundle On deactivation, any dependents of a bundle are stopped first, then the
+ bundle itself is stopped When Ghidra builds a source bundle, the result is cached to a
+ subdirectory of Ghidra Bundles
+
+ Dynamic modules
+
+
+
+
+ Source bundles
+
+ <user home>/.ghidra/.ghidra-<version>/osgi/compiled-bundles/<hash>,
+ where <hash> is a hash of the source bundle location.exploded bundles
+ compiled-bundles/ is an exploded jar -- by re-compressing it,
+ we get a standard Jar bundle:
+
+
+
+ jar cMf mybundle.jar -C $HOME/.ghidra/.ghidra_<version>/osgi/compiled-bundles/<hash> .
+
+ mybundle.jar could then be shared in binary form.
+ generated files
+
+
+ private or internal in its name.@importpackage requirments made available for import.Dependency
+ intra-bundle (compile time) dependency
+ import.inter-bundle (run time) dependency
+ Import-Package attribute, because Ghidra provides a shortcut
+ which we'll describe afterwards.
+ Import-Package in the manifestMETA-INF/MANIFEST.MF should have only one
+ Import-Package entry:
+
+
+
+ Import-Package:com.example.stuff
+ Import-Package:com.example.stuff;version=1.2.3
+ Import-Package:com.example.stuff;version="[1.2.0,1.3)"
+ Import-Package:com.example.stuff,org.example.otherstuff
+ Import-Package:com.example.stuff;version="[1.2.0,1.3)",org.example.otherstuff
+ Import-Package:com.example.stuff;version="[1.2.0,1.3)",org.example.otherstuff;version=2.3.4
+
+
+ @importpackage in sourceMETA-INF/MANIFEST.MF, it
+ will be used as the bundle's manifest. If not, a manifest will be
+ generated, see above.Import-Package, the
+ @importpackage metadata tag. The @importpackage
+ values from all source files in a source bundle are appended to the
+ generated manifest Import-Package attribute.Adding and removing bundles from the manager
+ Activating and deactivating bundles
+ ACTIVE state.
+ Ghidra will compile source bundles prior to installing and activating.Cleaning bundles
+
+ <user home>/.ghidra/.ghidra-<version>/osgi/compiled-bundles/<hash>.
+ These cached files speed up subsequent builds. A clean
+ deactivates then wipes the subdirectory of the selected bundle.

-Allows you to add and remove directories to search for scripts. The default - directories are your home directory and the various system directories (e.g., - $GHIDRA_HOME/Features/Base/ghidra_scripts). You - can save directories, but ignore them in the Script Manager dialog by selecting/deselecting - the "Use" column checkbox.
+
-Allows you to add and remove directories to search for + scripts and bundle dependencies for use by scripts. The default + directories are your home directory and the various system directories + (e.g., $GHIDRA_HOME/Features/Base/ghidra_scripts). You can + save directories, but ignore them in the Script Manager dialog by + selecting/deselecting the "Enable" column checkbox.
+ +For more information on Ghidra's dynamic module support, see + Ghidra Bundles.
+
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/GhidraScriptMgrPlugin/ScriptDevelopment.htm b/Ghidra/Features/Base/src/main/help/help/topics/GhidraScriptMgrPlugin/ScriptDevelopment.htm index a4aa8f82ee..0a3e5f3afc 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/GhidraScriptMgrPlugin/ScriptDevelopment.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/GhidraScriptMgrPlugin/ScriptDevelopment.htm @@ -48,7 +48,7 @@ This is highly recommended if you plan to do more than simple edits to scripts. -
Meta-data
+Meta-data
+The scripting framework supports special meta-data comments. This comment is treated @@ -84,6 +84,28 @@
+ +
@importpackage++ +This tag is a convenience for declaring bundle dependencies. The tag's + contents syntax is that of the
+ +Import-Packageattribute + in an OSGi bundle manifest. +For example:
+ +++ ++ @importpackage com.example.library
+
+ @importpackage org.apache.commons.collections.properties;version=4.4
+ @importpackage org.ghidra.analysis;version="[1.1,2)"
+ @importpackage com.example.library1,com.example.library2
+
@keybindingdiff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusComponentProvider.java index 89ee83dd0d..4c506ac1db 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusComponentProvider.java @@ -37,6 +37,7 @@ import ghidra.app.services.ConsoleService; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.preferences.Preferences; +import ghidra.util.HelpLocation; import ghidra.util.exception.CancelledException; import ghidra.util.filechooser.GhidraFileChooserModel; import ghidra.util.filechooser.GhidraFileFilter; @@ -62,7 +63,10 @@ public class BundleStatusComponentProvider extends ComponentProviderAdapter { static final String BUNDLE_LIST_GROUP = "1bundle list group"; public BundleStatusComponentProvider(PluginTool tool, String owner, BundleHost bundleHost) { - super(tool, "Bundle Status Component", owner); + super(tool, "BundleManager", owner); + setHelpLocation(new HelpLocation("BundleManager", "BundleManager")); + setTitle("Bundle Manager"); + this.bundleHost = bundleHost; this.bundleStatusTableModel = new BundleStatusTableModel(this, bundleHost); @@ -119,10 +123,9 @@ public class BundleStatusComponentProvider extends ComponentProviderAdapter { // to allow custom cell renderers bundleStatusTable.setAutoCreateColumnsFromModel(false); - int skinnyWidth = 50; - TableColumn column; + int skinnyWidth = 60; // column = bundleStatusTable.getColumnModel().getColumn( bundleStatusTableModel.enabledColumn.index); 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 85a6534365..e612fac2e7 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 @@ -142,7 +142,7 @@ public class GhidraSourceBundle extends GhidraBundle { private String parseImps(ResourceFile javaSource) { // XXX don't use @imports, use an annotation - return GhidraScriptUtil.newScriptInfo(javaSource).getImports(); + return GhidraScriptUtil.newScriptInfo(javaSource).getImportPackage(); } /** 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 ca84b4b4d3..5db19973c8 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 @@ -353,7 +353,7 @@ class GhidraScriptActionManager { refreshAction.setEnabled(true); plugin.getTool().addLocalAction(provider, refreshAction); - bundleStatusAction = new DockingAction("Bundle Status", plugin.getName()) { + bundleStatusAction = new DockingAction("Script Directories", plugin.getName()) { @Override public void actionPerformed(ActionContext context) { provider.showBundleStatusComponent(); 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 2bb59ec05c..2c18083f5e 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 @@ -45,14 +45,14 @@ public class ScriptInfo { */ public static final String DELIMITTER = "."; - public static final String AT_AUTHOR = "@author"; - public static final String AT_CATEGORY = "@category"; - public static final String AT_KEYBINDING = "@keybinding"; - public static final String AT_MENUPATH = "@menupath"; - public static final String AT_TOOLBAR = "@toolbar"; + static final String AT_AUTHOR = "@author"; + static final String AT_CATEGORY = "@category"; + static final String AT_KEYBINDING = "@keybinding"; + static final String AT_MENUPATH = "@menupath"; + static final String AT_TOOLBAR = "@toolbar"; // omit from METADATA to avoid pre-populating in new scripts - public static final String AT_IMPORTS = "@imports"; + private static final String AT_IMPORTPACKAGE = "@importpackage"; public static final String[] METADATA = { AT_AUTHOR, AT_CATEGORY, AT_KEYBINDING, AT_MENUPATH, AT_TOOLBAR, }; @@ -71,7 +71,7 @@ public class ScriptInfo { private String[] menupath = new String[0]; private String toolbar; private ImageIcon toolbarImage; - private String imports; + private String importpackage; /** * Constructs a new script. @@ -96,7 +96,7 @@ public class ScriptInfo { menupath = new String[0]; toolbar = null; toolbarImage = null; - imports = null; + importpackage = null; keybindingErrorMessage = null; } @@ -277,8 +277,8 @@ public class ScriptInfo { else if (line.startsWith(AT_TOOLBAR)) { toolbar = getTagValue(AT_TOOLBAR, line); } - else if (line.startsWith(AT_IMPORTS)) { - imports = getTagValue(AT_IMPORTS, line); + else if (line.startsWith(AT_IMPORTPACKAGE)) { + importpackage = getTagValue(AT_IMPORTPACKAGE, line); } } catch (Exception e) { @@ -440,9 +440,9 @@ public class ScriptInfo { * Returns the script imports * @return the script imports */ - public String getImports() { + public String getImportPackage() { parseHeader(); - return imports; + return importpackage; } /** diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/BundleHostTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/BundleHostTest.java index cc453e31eb..e091ea3bdf 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/BundleHostTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/BundleHostTest.java @@ -301,7 +301,7 @@ public class BundleHostTest extends AbstractGhidraHeadlessIntegrationTest { pushNewBundle(); // @imports tag is only parsed from classes in default package addClass( - "//@imports lib\n" + "//@importpackage lib\n" , "import lib.Library;\n" , diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java index 3bbc990083..5142c63347 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java @@ -276,7 +276,7 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes // Tests that the user can add an additional script path directory and choose that one // to use // - DockingActionIf bundleStatusAction = getAction(plugin, "Bundle Status"); + DockingActionIf bundleStatusAction = getAction(plugin, "Script Directories"); performAction(bundleStatusAction, false); waitForSwing(); diff --git a/Ghidra/Features/Python/src/main/help/help/TOC_Source.xml b/Ghidra/Features/Python/src/main/help/help/TOC_Source.xml index 5069c64d9c..acdd831d0b 100644 --- a/Ghidra/Features/Python/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Features/Python/src/main/help/help/TOC_Source.xml @@ -3,7 +3,7 @@\ No newline at end of file + - - +