GP-6659: Adding PyGhidra headless launcher to GhidraDev

This commit is contained in:
Ryan Kurtz
2026-04-07 05:49:10 -04:00
parent bc32719545
commit f8f779c5f2
13 changed files with 383 additions and 31 deletions
@@ -2,7 +2,7 @@
<feature
id="ghidra.ghidradev"
label="GhidraDev"
version="5.0.1.qualifier"
version="5.1.0.qualifier"
provider-name="Ghidra">
<description>
@@ -172,14 +172,13 @@
<setEntry value="com.python.pydev.analysis*9.3.0.202203051235@default:default"/>
<setEntry value="com.python.pydev.debug*9.3.0.202203051235@default:default"/>
<setEntry value="com.python.pydev.refactoring*9.3.0.202203051235@default:default"/>
<setEntry value="com.sun.el.javax.el@default:default"/>
<setEntry value="com.sun.jna.platform@default:default"/>
<setEntry value="com.sun.jna@default:default"/>
<setEntry value="jakarta.annotation-api@default:default"/>
<setEntry value="jakarta.annotation-api*1.3.5@default:default"/>
<setEntry value="jakarta.annotation-api*2.1.1@default:default"/>
<setEntry value="jakarta.inject.jakarta.inject-api*1.0.5@default:default"/>
<setEntry value="jakarta.inject.jakarta.inject-api*2.0.1@default:default"/>
<setEntry value="jakarta.servlet-api@default:default"/>
<setEntry value="javax.annotation@default:default"/>
<setEntry value="jaxen@default:default"/>
<setEntry value="org.apache.aries.spifly.dynamic.bundle@default:default"/>
<setEntry value="org.apache.batik.constants@default:default"/>
@@ -189,8 +188,8 @@
<setEntry value="org.apache.commons.cli@default:default"/>
<setEntry value="org.apache.commons.commons-codec@default:default"/>
<setEntry value="org.apache.commons.commons-io@default:default"/>
<setEntry value="org.apache.commons.commons-logging@default:default"/>
<setEntry value="org.apache.commons.lang3@default:default"/>
<setEntry value="org.apache.commons.logging@default:default"/>
<setEntry value="org.apache.felix.gogo.command@default:default"/>
<setEntry value="org.apache.felix.gogo.runtime@default:default"/>
<setEntry value="org.apache.felix.gogo.shell@default:default"/>
@@ -202,7 +201,7 @@
<setEntry value="org.apache.xml.resolver@default:default"/>
<setEntry value="org.apache.xml.serializer@default:default"/>
<setEntry value="org.apache.xmlgraphics@default:default"/>
<setEntry value="org.commonmark-gfm-tables@default:default"/>
<setEntry value="org.commonmark.ext-gfm-tables@default:default"/>
<setEntry value="org.commonmark@default:default"/>
<setEntry value="org.eclipse.ant.core@default:default"/>
<setEntry value="org.eclipse.buildship.compat@default:default"/>
@@ -310,12 +309,12 @@
<setEntry value="org.eclipse.jdt.launching@default:default"/>
<setEntry value="org.eclipse.jdt.ui@default:default"/>
<setEntry value="org.eclipse.jem.util@default:default"/>
<setEntry value="org.eclipse.jetty.ee.webapp@default:default"/>
<setEntry value="org.eclipse.jetty.ee10.servlet@default:default"/>
<setEntry value="org.eclipse.jetty.ee10.webapp@default:default"/>
<setEntry value="org.eclipse.jetty.ee8.security@default:default"/>
<setEntry value="org.eclipse.jetty.ee8.server@default:default"/>
<setEntry value="org.eclipse.jetty.ee8.servlet@default:default"/>
<setEntry value="org.eclipse.jetty.ee@default:default"/>
<setEntry value="org.eclipse.jetty.http@default:default"/>
<setEntry value="org.eclipse.jetty.io@default:default"/>
<setEntry value="org.eclipse.jetty.security@default:default"/>
@@ -350,7 +349,7 @@
<setEntry value="org.eclipse.search.core@default:default"/>
<setEntry value="org.eclipse.search@default:default"/>
<setEntry value="org.eclipse.swt.cocoa.macosx.aarch64@default:false"/>
<setEntry value="org.eclipse.swt.svg@default:default"/>
<setEntry value="org.eclipse.swt.svg@default:false"/>
<setEntry value="org.eclipse.swt@default:default"/>
<setEntry value="org.eclipse.team.core@default:default"/>
<setEntry value="org.eclipse.team.ui@default:default"/>
@@ -392,8 +391,6 @@
<setEntry value="org.hamcrest@default:default"/>
<setEntry value="org.jdom2@default:default"/>
<setEntry value="org.junit@default:default"/>
<setEntry value="org.mortbay.jasper.apache-el@default:default"/>
<setEntry value="org.mortbay.jasper.apache-jsp@default:default"/>
<setEntry value="org.objectweb.asm.commons@default:default"/>
<setEntry value="org.objectweb.asm.tree.analysis@default:default"/>
<setEntry value="org.objectweb.asm.tree@default:default"/>
@@ -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",
@@ -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
`<GhidraInstallDir>/support/analyzeHeadlessREADME.html`.
## Upgrading
GhidraDev is upgraded differently depending on how it was installed. If GhidraDev was
Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

@@ -383,6 +383,11 @@
id="PyGhidraGuiLaunchConfigurationType"
name="PyGhidra">
</launchConfigurationType>
<launchConfigurationType
delegate="ghidradev.ghidraprojectcreator.launchers.PyGhidraLaunchDelegate"
id="PyGhidraHeadlessLaunchConfigurationType"
name="PyGhidra Headless">
</launchConfigurationType>
</extension>
<extension
point="org.eclipse.debug.ui.launchConfigurationTypeImages">
@@ -401,6 +406,11 @@
icon="icons/python.png"
id="PyGhidraGuiLaunchConfigurationTypeImage">
</launchConfigurationTypeImage>
<launchConfigurationTypeImage
configTypeID="PyGhidraHeadlessLaunchConfigurationType"
icon="icons/python_bw.png"
id="PyGhidraHeadlessLaunchConfigurationTypeImage">
</launchConfigurationTypeImage>
</extension>
<extension
point="org.eclipse.debug.core.launchDelegates">
@@ -425,6 +435,13 @@
name="PyGhidra GUI"
type="PyGhidraGuiLaunchConfigurationType">
</launchDelegate>
<launchDelegate
delegate="ghidradev.ghidraprojectcreator.launchers.PyGhidraLaunchDelegate"
id="PyGhidraHeadlessLaunchDelegate"
modes="run, debug"
name="PyGhidra Headless"
type="PyGhidraHeadlessLaunchConfigurationType">
</launchDelegate>
</extension>
<extension
point="org.eclipse.debug.ui.launchConfigurationTabGroups">
@@ -441,11 +458,17 @@
type="GhidraHeadlessLaunchConfigurationType">
</launchConfigurationTabGroup>
<launchConfigurationTabGroup
class="org.python.pydev.debug.ui.PythonTabGroup"
class="ghidradev.ghidraprojectcreator.launchers.PyGhidraLaunchTabGroup"
description="Run and debug PyGhidra modules and scripts"
id="PyGhidraGuiLaunchConfigurationTabGroup"
type="PyGhidraGuiLaunchConfigurationType">
</launchConfigurationTabGroup>
<launchConfigurationTabGroup
class="ghidradev.ghidraprojectcreator.launchers.PyGhidraLaunchTabGroup"
description="Run and debug PyGhidra modules and scripts in headless mode"
id="PyGhidraHeadlessLaunchConfigurationTabGroup"
type="PyGhidraHeadlessLaunchConfigurationType">
</launchConfigurationTabGroup>
</extension>
<extension
point="org.eclipse.debug.ui.launchShortcuts">
@@ -521,6 +544,30 @@
</enablement>
</contextualLaunch>
</shortcut>
<shortcut
class="ghidradev.ghidraprojectcreator.launchers.PyGhidraHeadlessLaunchShortcut"
icon="icons/python_bw.png"
id="PyGhidraHeadlessLaunchShortcut"
label="PyGhidra Headless"
modes="run, debug">
<contextualLaunch>
<enablement>
<with
variable="selection">
<count
value="1">
</count>
<iterate
ifEmpty="false">
<test
property="ghidradev.ghidraprojectcreator.testers.isPyGhidraProject"
value="true">
</test>
</iterate>
</with>
</enablement>
</contextualLaunch>
</shortcut>
</extension>
<extension
point="org.eclipse.core.expressions.propertyTesters">
@@ -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
@@ -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)");
}
}
@@ -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)");
}
}
@@ -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<String, String> 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));
@@ -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<ILaunchConfigurationTab> 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);
}
}
};
}
}
@@ -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.");
}
}
@@ -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|