diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml index 21961b1ea8..4fd89f6b04 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevFeature/feature.xml @@ -2,7 +2,7 @@ diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch index fe36c5c7ff..5fa2cec067 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch @@ -172,14 +172,13 @@ - - + + - @@ -189,8 +188,8 @@ + - @@ -202,7 +201,7 @@ - + @@ -310,12 +309,12 @@ + - @@ -350,7 +349,7 @@ - + @@ -392,8 +391,6 @@ - - diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/META-INF/MANIFEST.MF b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/META-INF/MANIFEST.MF index c4ae021280..427720d7df 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/META-INF/MANIFEST.MF +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: GhidraDev Bundle-SymbolicName: ghidra.ghidradev;singleton:=true -Bundle-Version: 5.0.1.qualifier +Bundle-Version: 5.1.0.qualifier Bundle-Activator: ghidradev.Activator Require-Bundle: org.eclipse.ant.core;bundle-version="3.7.200", org.eclipse.buildship.core;bundle-version="3.1.8", diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/README.md b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/README.md index a921932f04..2d503e6f36 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/README.md +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/README.md @@ -1,7 +1,7 @@ # GhidraDev Eclipse Plugin GhidraDev provides support for developing and debugging Ghidra scripts and modules in Eclipse. -The information provided in this document is effective as of GhidraDev 5.0.1 and is subject to +The information provided in this document is effective as of GhidraDev 5.1.0 and is subject to change with future releases. ## Table of Contents @@ -31,6 +31,9 @@ change with future releases. 12. [Building](#building) ## Change History +__5.1.0:__ +* Added a PyGhidra Headless run configuration + __5.0.1:__ * Fixed a bug that prevented Ghidra from discovering the Ghidra module project when launched with the PyGhidra run configuration. @@ -319,8 +322,16 @@ that was last used to launch PyGhidra. If it cannot find it, you will have to l and try again. ### Launching and Debugging PyGhidra -GhidraDev can interface with PyDev to provide a __PyGhidra__ run configuration that is capable of -launching PyGhidra in both GUI mode and GUI debug mode. +When PyDev is installed, GhidraDev introduces two new run configurations to Eclipse which are +capable of launching the installation of Ghidra (in PyGhidra mode) that an Eclipse Ghidra project is +linked to: +* __PyGhidra:__ Launches the PyGhidra GUI. +* __PyGhidra Headless:__ Launches PyGhidra in headless mode. By default, this run configuration will + not have any program arguments associated with it, which are required to tell headless PyGhidra + what project to open, what scripts to run, etc. Newly created `PyGhidra Headless` run + configurations will have to be modified with the desired headless program arguments. For more + information on headless command line arguments, see + `/support/analyzeHeadlessREADME.html`. ## Upgrading GhidraDev is upgraded differently depending on how it was installed. If GhidraDev was diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/icons/python_bw.png b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/icons/python_bw.png new file mode 100644 index 0000000000..6f9a5f1b4f Binary files /dev/null and b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/icons/python_bw.png differ diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/plugin.xml b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/plugin.xml index 834baa1ee3..7ca6135a2e 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/plugin.xml +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/plugin.xml @@ -383,6 +383,11 @@ id="PyGhidraGuiLaunchConfigurationType" name="PyGhidra"> + + @@ -401,6 +406,11 @@ icon="icons/python.png" id="PyGhidraGuiLaunchConfigurationTypeImage"> + + @@ -425,6 +435,13 @@ name="PyGhidra GUI" type="PyGhidraGuiLaunchConfigurationType"> + + @@ -441,11 +458,17 @@ type="GhidraHeadlessLaunchConfigurationType"> + + @@ -521,6 +544,30 @@ + + + + + + + + + + + + + + diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/GhidraLaunchDelegate.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/GhidraLaunchDelegate.java index 276e5ca8f5..2eff32b6b6 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/GhidraLaunchDelegate.java +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/GhidraLaunchDelegate.java @@ -90,11 +90,7 @@ public class GhidraLaunchDelegate extends JavaLaunchDelegate { programArgs += " " + customProgramArgs; wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, programArgs); if (isHeadless && customProgramArgs.isEmpty()) { - EclipseMessageUtils.showInfoDialog("Ghidra Run Configuration", - "Headless launch is being performed without any command line arguments!\n\n" + - "Edit the \"" + configuration.getName() + - "\" run configuration's program arguments to customize headless behavior. " + - "See support/analyzeHeadlessREADME.html for more information."); + GhidraLaunchUtils.notifyAboutHeadlessWithNoArgs(configuration); } // Set VM arguments diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraGuiLaunchShortcut.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraGuiLaunchShortcut.java index ea081e950e..28944124b1 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraGuiLaunchShortcut.java +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraGuiLaunchShortcut.java @@ -20,7 +20,7 @@ import ghidradev.ghidraprojectcreator.utils.GhidraLaunchUtils; /** * The PyGhidra GUI launch shortcut actions. * - * @see AbstractGhidraLaunchShortcut + * @see AbstractPyGhidraLaunchShortcut */ public class PyGhidraGuiLaunchShortcut extends AbstractPyGhidraLaunchShortcut { @@ -28,6 +28,6 @@ public class PyGhidraGuiLaunchShortcut extends AbstractPyGhidraLaunchShortcut { * Creates a new PyGhidra GUI launch shortcut. */ public PyGhidraGuiLaunchShortcut() { - super(GhidraLaunchUtils.PYGHIDRA_GUI_LAUNCH, " GUI"); + super(GhidraLaunchUtils.PYGHIDRA_GUI_LAUNCH, " (PyGhidra)"); } } diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraHeadlessLaunchShortcut.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraHeadlessLaunchShortcut.java new file mode 100644 index 0000000000..bc819328a5 --- /dev/null +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraHeadlessLaunchShortcut.java @@ -0,0 +1,33 @@ +/* ### + * 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 ghidradev.ghidraprojectcreator.launchers; + +import ghidradev.ghidraprojectcreator.utils.GhidraLaunchUtils; + +/** + * The PyGhidra Headless launch shortcut actions. + * + * @see AbstractPyGhidraLaunchShortcut + */ +public class PyGhidraHeadlessLaunchShortcut extends AbstractPyGhidraLaunchShortcut { + + /** + * Creates a new PyGhidra Headless launch shortcut. + */ + public PyGhidraHeadlessLaunchShortcut() { + super(GhidraLaunchUtils.PYGHIDRA_HEADLESS_LAUNCH, " (PyGhidra Headless)"); + } +} diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchDelegate.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchDelegate.java index 582a89617f..8353bca8e3 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchDelegate.java +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchDelegate.java @@ -37,8 +37,7 @@ import org.python.pydev.debug.ui.launching.RegularLaunchConfigurationDelegate; import ghidra.launch.AppConfig; import ghidradev.EclipseMessageUtils; -import ghidradev.ghidraprojectcreator.utils.GhidraProjectUtils; -import ghidradev.ghidraprojectcreator.utils.PyDevUtils; +import ghidradev.ghidraprojectcreator.utils.*; /** * The PyGhidra Launch delegate handles the final launch of PyGhidra. @@ -51,6 +50,9 @@ public class PyGhidraLaunchDelegate extends RegularLaunchConfigurationDelegate { IProgressMonitor monitor) throws CoreException { try { + boolean isHeadless = configuration.getType() + .getIdentifier() + .equals(GhidraLaunchUtils.PYGHIDRA_HEADLESS_LAUNCH); ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); // Get project @@ -82,16 +84,45 @@ public class PyGhidraLaunchDelegate extends RegularLaunchConfigurationDelegate { return; } + // Determine which module to call + String module = "pyghidra"; + if (isHeadless) { + module += "/ghidra_launch.py"; + } + // Set program location wc.setAttribute(PyDevUtils.getAttrLocation(), - "${workspace_loc:%s/Ghidra/Ghidra/Features/PyGhidra/pypkg/src/pyghidra}" - .formatted(project.getName())); + "${workspace_loc:%s/Ghidra/Ghidra/Features/PyGhidra/pypkg/src/%s}" + .formatted(project.getName(), module)); + + // Set VM arguments + String vmArgs = + " " + configuration.getAttribute(GhidraLaunchUtils.ATTR_VM_ARGUMENTS, "").trim(); + vmArgs += " -Dghidra.external.modules=\"%s%s%s\"".formatted( + javaProject.getProject().getLocation(), File.pathSeparator, + GhidraProjectUtils.getProjectDependencyDirs(javaProject)); + File pyDevSrcDir = PyDevUtils.getPyDevSrcDir(); + if (pyDevSrcDir != null) { + vmArgs += " " + "-Declipse.pysrc.dir=\"" + pyDevSrcDir + "\""; + } // Set program arguments - wc.setAttribute(PyDevUtils.getAttrProgramArguments(), - "-v -g -D ghidra.external.modules=\"%s%s%s\"".formatted( - javaProject.getProject().getLocation(), File.pathSeparator, - GhidraProjectUtils.getProjectDependencyDirs(javaProject))); + String customProgramArgs = + configuration.getAttribute(GhidraLaunchUtils.ATTR_PROGAM_ARGUMENTS, "").trim(); + StringBuilder args = new StringBuilder(); + if (isHeadless) { + args.append("ghidra.app.util.headless.AnalyzeHeadless "); + } + else { + args.append("-v "); + args.append("-g "); + } + args.append(vmArgs + " "); + args.append(customProgramArgs); + wc.setAttribute(PyDevUtils.getAttrProgramArguments(), args.toString()); + if (isHeadless && customProgramArgs.isEmpty()) { + GhidraLaunchUtils.notifyAboutHeadlessWithNoArgs(configuration); + } // Set Python interpreter String interpreterName = PyDevUtils.getInterpreterName(project); @@ -100,7 +131,7 @@ public class PyGhidraLaunchDelegate extends RegularLaunchConfigurationDelegate { // Set environment variables Map env = new HashMap<>(); - //env.put("GHIDRA_INSTALL_DIR", "${project_loc:/%s/Ghidra}".formatted(project.getName())); + env = wc.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, env); env.put("GHIDRA_INSTALL_DIR", "${resource_loc:/%s/Ghidra}".formatted(project.getName())); env.put("JAVA_HOME_OVERRIDE", "${ee_home:JavaSE-%s}".formatted(javaComplianceLevel)); diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchTabGroup.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchTabGroup.java new file mode 100644 index 0000000000..314a712734 --- /dev/null +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/launchers/PyGhidraLaunchTabGroup.java @@ -0,0 +1,215 @@ +/* ### + * 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 ghidradev.ghidraprojectcreator.launchers; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; +import org.python.pydev.debug.ui.*; + +import ghidradev.EclipseMessageUtils; +import ghidradev.ghidraprojectcreator.utils.GhidraLaunchUtils; + +/** + * The PyGhidra launcher tab group with default values needed for running/debugging + * PyGhidra. Some Python tabs are hidden here because we don't want the user changing their + * properties. These properties are set in {@link PyGhidraLaunchDelegate}, which occurs right before + * the launch. + */ +public class PyGhidraLaunchTabGroup extends PythonTabGroup { + + @Override + public void createTabs(ILaunchConfigurationDialog dialog, String mode) { + + // Create the tabs + List tabs = new ArrayList<>(); + tabs.add(getMainModuleTab()); + tabs.add(getUserDefinedArgumentsTab()); + tabs.add(getInterpreterTab()); + tabs.add(new EnvironmentTab()); + tabs.add(getCommonTab()); + + // Set the tabs + setTabs(tabs.toArray(new ILaunchConfigurationTab[tabs.size()])); + } + + /** + * Gets the {@link MainModuleTab} to use, with PyGhidra's main module pre-configured in. + * + * @return The {@link MainModuleTab} to use, with Ghidra's main method pre-configured in. + */ + private MainModuleTab getMainModuleTab() { + return new MainModuleTab() { + @Override + public void initializeFrom(ILaunchConfiguration config) { + try { + ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); + GhidraLaunchUtils.setMainTypeName(wc); + super.initializeFrom(wc.doSave()); + } + catch (CoreException e) { + EclipseMessageUtils.error("Failed to initialize the Python main module tab.", + e); + } + } + }; + } + + /** + * Gets the user-defined arguments to use. These will be appended to PyGhidra's required + * launch arguments, which are hidden from the tab group. + * + * @return The user-defined arguments to use. + */ + private AbstractLaunchConfigurationTab getUserDefinedArgumentsTab() { + return new AbstractLaunchConfigurationTab() { + + private Text programArgsText; + private Text vmArgsText; + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + container.setLayout(new GridLayout(1, true)); + GridData gd = new GridData(GridData.FILL_BOTH); + container.setLayoutData(gd); + + // Program arguments + Group group = new Group(container, SWT.NONE); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setText("Program arguments:"); + programArgsText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.heightHint = 40; + gd.widthHint = 100; + programArgsText.setLayoutData(gd); + programArgsText.addModifyListener(evt -> scheduleUpdateJob()); + + // VM arguments + group = new Group(container, SWT.NONE); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setText("VM arguments (appended to arguments defined in launch.properties):"); + vmArgsText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.heightHint = 40; + gd.widthHint = 100; + vmArgsText.setLayoutData(gd); + vmArgsText.addModifyListener(evt -> scheduleUpdateJob()); + + setControl(container); + } + + @Override + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + try { + ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); + wc.setAttribute(GhidraLaunchUtils.ATTR_PROGAM_ARGUMENTS, ""); + wc.setAttribute(GhidraLaunchUtils.ATTR_VM_ARGUMENTS, ""); + wc.doSave(); + } + catch (CoreException e) { + EclipseMessageUtils.error("Failed to set argument defaults.", e); + } + } + + @Override + public void initializeFrom(ILaunchConfiguration config) { + try { + programArgsText.setText( + config.getAttribute(GhidraLaunchUtils.ATTR_PROGAM_ARGUMENTS, "")); + vmArgsText.setText( + config.getAttribute(GhidraLaunchUtils.ATTR_VM_ARGUMENTS, "")); + } + catch (CoreException e) { + EclipseMessageUtils.error("Failed to initialize the arguments.", e); + } + } + + @Override + public void performApply(ILaunchConfigurationWorkingCopy config) { + try { + ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); + wc.setAttribute(GhidraLaunchUtils.ATTR_PROGAM_ARGUMENTS, + programArgsText.getText()); + wc.setAttribute(GhidraLaunchUtils.ATTR_VM_ARGUMENTS, vmArgsText.getText()); + wc.doSave(); + } + catch (CoreException e) { + EclipseMessageUtils.error("Failed to apply the arguments.", e); + } + } + + @Override + public String getName() { + return "Arguments"; + } + }; + } + + /** + * Gets the {@link InterpreterTab} to use + * + * @return The {@link InterpreterTab} to use + */ + private InterpreterTab getInterpreterTab() { + return new InterpreterTab() { + @Override + public void initializeFrom(ILaunchConfiguration config) { + try { + ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); + GhidraLaunchUtils.setClasspath(wc); + super.initializeFrom(wc.doSave()); + } + catch (CoreException e) { + EclipseMessageUtils.error("Failed to initialize the Python interpreter tab.", + e); + } + } + }; + } + + /** + * Gets the {@link CommonTab} to use, with the new launch configuration added to the favorites. + * + * @return The {@link CommonTab} to use, with the new launch configuration added to the + * favorites. + */ + private CommonTab getCommonTab() { + return new CommonTab() { + @Override + public void initializeFrom(ILaunchConfiguration config) { + try { + ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); + GhidraLaunchUtils.setFavorites(wc); + super.initializeFrom(wc.doSave()); + } + catch (CoreException e) { + EclipseMessageUtils.error("Failed to initialize the common tab.", e); + } + } + }; + } +} diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraLaunchUtils.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraLaunchUtils.java index bd88074cd0..af6d0627f7 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraLaunchUtils.java +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraLaunchUtils.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.launching.*; import ghidra.Ghidra; +import ghidradev.EclipseMessageUtils; /** * Utility methods for working with Ghidra launchers in Eclipse. @@ -55,6 +56,12 @@ public class GhidraLaunchUtils { */ public static final String PYGHIDRA_GUI_LAUNCH = "PyGhidraGuiLaunchConfigurationType"; + /** + * Launch configuration ID for a PyGhidra Headless launch. Must match corresponding value in + * plugin.xml. + */ + public static final String PYGHIDRA_HEADLESS_LAUNCH = "PyGhidraHeadlessLaunchConfigurationType"; + /** * Program arguments that will get passed to the launched Ghidra. These will be appended * to the required program arguments that are required to launch Ghidra, which are hidden @@ -277,4 +284,18 @@ public class GhidraLaunchUtils { runHistory.addFavorite(launchConfig); debugHistory.addFavorite(launchConfig); } + + /** + * Notifies the user that a headless launch is being performed without any command line + * arguments + * + * @param configuration The headless launch configuration + */ + public static void notifyAboutHeadlessWithNoArgs(ILaunchConfiguration configuration) { + EclipseMessageUtils.showInfoDialog("Ghidra Run Configuration", + "Headless launch is being performed without any command line arguments!\n\n" + + "Edit the \"" + configuration.getName() + + "\" run configuration's program arguments to customize headless behavior. " + + "See support/analyzeHeadlessREADME.html for more information."); + } } diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest b/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest index d7d8abed85..b5eadd6e11 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest +++ b/GhidraBuild/EclipsePlugins/GhidraDev/certification.manifest @@ -14,6 +14,7 @@ GhidraDevPlugin/icons/brick_add.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk i GhidraDevPlugin/icons/brick_go.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| GhidraDevPlugin/icons/folder_link.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| GhidraDevPlugin/icons/python.png||GHIDRA||||END| +GhidraDevPlugin/icons/python_bw.png||GHIDRA||||END| GhidraDevPlugin/icons/script_add.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| GhidraDevPlugin/icons/script_code_red.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| GhidraDevPlugin/plugin.xml||GHIDRA||||END|