mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4659: Renaming "Python" module to "Jython"
This commit is contained in:
parent
9840eee937
commit
fb1f725f5b
46 changed files with 285 additions and 284 deletions
|
@ -21,7 +21,7 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
|
apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
|
|
||||||
eclipse.project.name = 'Features Python'
|
eclipse.project.name = 'Features Jython'
|
||||||
|
|
||||||
|
|
||||||
def JYTHON = "org.python:jython-standalone:2.7.3"
|
def JYTHON = "org.python:jython-standalone:2.7.3"
|
||||||
|
@ -51,15 +51,15 @@ task jythonUnpack(type: Copy) {
|
||||||
destinationDir file("build/data/${JYTHON_DIR}")
|
destinationDir file("build/data/${JYTHON_DIR}")
|
||||||
}
|
}
|
||||||
|
|
||||||
task pythonSrcCopy(type: Copy) {
|
task jythonSrcCopy(type: Copy) {
|
||||||
description "Copy python-src directory (for Feature Python)"
|
description "Copy jython-src directory (for Feature Jython)"
|
||||||
|
|
||||||
from(file("python-src"))
|
from(file("jython-src"))
|
||||||
|
|
||||||
destinationDir file("build/data/python-src")
|
destinationDir file("build/data/jython-src")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that Jython is usable in development xx
|
// Ensure that Jython is usable in development xx
|
||||||
rootProject.prepDev.dependsOn jythonUnpack
|
rootProject.prepDev.dependsOn jythonUnpack
|
||||||
jar.dependsOn jythonUnpack
|
jar.dependsOn jythonUnpack
|
||||||
jar.dependsOn pythonSrcCopy
|
jar.dependsOn jythonSrcCopy
|
|
@ -2,7 +2,7 @@
|
||||||
##MODULE IP: Jython License
|
##MODULE IP: Jython License
|
||||||
##MODULE IP: LGPL 2.1
|
##MODULE IP: LGPL 2.1
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
data/python.theme.properties||GHIDRA||||END|
|
data/jython.theme.properties||GHIDRA||||END|
|
||||||
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
|
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
|
||||||
src/main/help/help/topics/Python/interpreter.html||GHIDRA||||END|
|
src/main/help/help/topics/Jython/interpreter.html||GHIDRA||||END|
|
||||||
src/main/resources/images/python.png||GHIDRA||||END|
|
src/main/resources/images/python.png||GHIDRA||||END|
|
21
Ghidra/Features/Jython/data/jython.theme.properties
Normal file
21
Ghidra/Features/Jython/data/jython.theme.properties
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
[Defaults]
|
||||||
|
|
||||||
|
color.fg.plugin.jython.syntax.class = color.palette.blue
|
||||||
|
color.fg.plugin.jython.syntax.code = color.palette.darkgreen
|
||||||
|
color.fg.plugin.jython.syntax.function = color.palette.green
|
||||||
|
color.fg.plugin.jython.syntax.instance = color.palette.purple
|
||||||
|
color.fg.plugin.jython.syntax.map = color.palette.steelblue
|
||||||
|
color.fg.plugin.jython.syntax.method = color.palette.teal
|
||||||
|
color.fg.plugin.jython.syntax.null = color.palette.red
|
||||||
|
color.fg.plugin.jython.syntax.number = color.palette.darkgray
|
||||||
|
color.fg.plugin.jython.syntax.package = color.palette.darkred
|
||||||
|
color.fg.plugin.jython.syntax.sequence = color.palette.saddlebrown
|
||||||
|
color.fg.plugin.jython.syntax.special = color.palette.darkgreen
|
||||||
|
|
||||||
|
icon.plugin.jython = python.png
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Dark Defaults]
|
||||||
|
|
|
@ -16,7 +16,7 @@ import sys
|
||||||
import tokenize
|
import tokenize
|
||||||
import types
|
import types
|
||||||
import __main__
|
import __main__
|
||||||
from ghidra.python import PythonCodeCompletionFactory
|
from ghidra.jython import JythonCodeCompletionFactory
|
||||||
import java # needed for java.lang.Class
|
import java # needed for java.lang.Class
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -72,7 +72,7 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1,
|
||||||
pyObj = getattr(object, attribute)
|
pyObj = getattr(object, attribute)
|
||||||
else:
|
else:
|
||||||
pyObj = locals[attribute]
|
pyObj = locals[attribute]
|
||||||
completion_list.append(PythonCodeCompletionFactory.
|
completion_list.append(JythonCodeCompletionFactory.
|
||||||
newCodeCompletion(attribute,
|
newCodeCompletion(attribute,
|
||||||
attribute,
|
attribute,
|
||||||
pyObj,
|
pyObj,
|
|
@ -8,7 +8,7 @@ import string
|
||||||
import __builtin__
|
import __builtin__
|
||||||
import java # needed for java.lang.Class
|
import java # needed for java.lang.Class
|
||||||
import org # for org.python.core
|
import org # for org.python.core
|
||||||
import ghidra # for PythonCodeCompletionFactory
|
import ghidra # for JythonCodeCompletionFactory
|
||||||
|
|
||||||
__author__ = "Don Coleman <dcoleman@chariotsolutions.com>"
|
__author__ = "Don Coleman <dcoleman@chariotsolutions.com>"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<tocroot>
|
<tocroot>
|
||||||
<tocref id="Ghidra Functionality">
|
<tocref id="Ghidra Functionality">
|
||||||
<tocref id="Scripting">
|
<tocref id="Scripting">
|
||||||
<tocdef id="Python Interpreter" sortgroup="z" text="Python Interpreter" target="help/topics/Python/interpreter.html" />
|
<tocdef id="Jython Interpreter" sortgroup="z" text="Jython Interpreter" target="help/topics/Jython/interpreter.html" />
|
||||||
</tocref>
|
</tocref>
|
||||||
</tocref>
|
</tocref>
|
||||||
</tocroot>
|
</tocroot>
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
<HTML>
|
<HTML>
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<TITLE>Python Interpreter</TITLE>
|
<TITLE>Jython Interpreter</TITLE>
|
||||||
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||||
</HEAD>
|
</HEAD>
|
||||||
|
|
||||||
<BODY lang="EN-US">
|
<BODY lang="EN-US">
|
||||||
<H1><A name="Python"></A>Python Interpreter</H1>
|
<H1><A name="Jython"></A>Jython Interpreter</H1>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
The Ghidra <I>Python Interpreter</I> provides a full general-purpose Python interactive shell
|
The Ghidra <I>Jython Interpreter</I> provides a full general-purpose Jython interactive shell
|
||||||
and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java
|
and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java
|
||||||
API through the magic of Jython.
|
API through the magic of Jython.
|
||||||
</P>
|
</P>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<H2>Environment</H2>
|
<H2>Environment</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
The Ghidra <I>Python Interpreter</I> is configured to run in a similar context as a Ghidra
|
The Ghidra <I>Jython Interpreter</I> is configured to run in a similar context as a Ghidra
|
||||||
script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>,
|
script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>,
|
||||||
<TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them.
|
<TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them.
|
||||||
These variables exist as Java objects behind the scenes, but Jython allows you to interact with
|
These variables exist as Java objects behind the scenes, but Jython allows you to interact with
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
hierarchy, so nothing has to be explicitly imported before they can be used. However, because
|
hierarchy, so nothing has to be explicitly imported before they can be used. However, because
|
||||||
the <TT>DataTypeSelectionDialog</TT> class and <TT>AllowedDataType</TT> enum reside in
|
the <TT>DataTypeSelectionDialog</TT> class and <TT>AllowedDataType</TT> enum reside in
|
||||||
different packages, they must be explicitly imported. Failure to do so will result in a
|
different packages, they must be explicitly imported. Failure to do so will result in a
|
||||||
Python <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
Jython <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
||||||
</P>
|
</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
<H2>Keybindings</H2>
|
<H2>Keybindings</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
The Ghidra <I>Python Interpreter</I> supports the following hard-coded keybindings:
|
The Ghidra <I>Jython Interpreter</I> supports the following hard-coded keybindings:
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>(up):</B> Move backward in command stack</LI>
|
<LI><B>(up):</B> Move backward in command stack</LI>
|
||||||
<LI><B>(down):</B> Move forward in command stack</LI>
|
<LI><B>(down):</B> Move forward in command stack</LI>
|
||||||
|
@ -100,7 +100,7 @@
|
||||||
<H2>Copy/Paste</H2>
|
<H2>Copy/Paste</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
Copy and paste from within the Ghidra <I>Python Interpreter</I> should work as expected for
|
Copy and paste from within the Ghidra <I>Jython Interpreter</I> should work as expected for
|
||||||
your given environment:
|
your given environment:
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>Windows:</B> CTRL+C / CTRL+V</LI>
|
<LI><B>Windows:</B> CTRL+C / CTRL+V</LI>
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
<H2>API Documentation</H2>
|
<H2>API Documentation</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
The built-in <TT>help()</TT> Python function has been altered by the Ghidra <I>Python Interpreter</I>
|
The built-in <TT>help()</TT> Jython function has been altered by the Ghidra <I>Jython Interpreter</I>
|
||||||
to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method,
|
to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method,
|
||||||
or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do:
|
or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do:
|
||||||
<PRE>
|
<PRE>
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
</P>
|
</P>
|
||||||
<P>
|
<P>
|
||||||
<B>Note:</B> It may be necessary to import a Ghidra class before calling the built-in <TT>help()</TT>
|
<B>Note:</B> It may be necessary to import a Ghidra class before calling the built-in <TT>help()</TT>
|
||||||
Python function on it. Failure to do so will result in a Python <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
Jython function on it. Failure to do so will result in a Jython <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
||||||
</P>
|
</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@
|
||||||
</P>
|
</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P>
|
<P align="left" class="providedbyplugin">Provided by: <I>JythonPlugin</I></P>
|
||||||
|
|
||||||
<P> </P>
|
<P> </P>
|
||||||
<BR>
|
<BR>
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -41,7 +41,7 @@ import util.CollectionUtils;
|
||||||
* There is no longer a way to reset an interpreter...it was too complicated to get right.
|
* There is no longer a way to reset an interpreter...it was too complicated to get right.
|
||||||
* Instead, you should {@link #cleanup()} your old interpreter and make a new one.
|
* Instead, you should {@link #cleanup()} your old interpreter and make a new one.
|
||||||
*/
|
*/
|
||||||
public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
public class GhidraJythonInterpreter extends InteractiveInterpreter {
|
||||||
|
|
||||||
private static boolean pythonInitialized;
|
private static boolean pythonInitialized;
|
||||||
private static List<PyString> defaultPythonPath;
|
private static List<PyString> defaultPythonPath;
|
||||||
|
@ -58,23 +58,23 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
*
|
*
|
||||||
* @return A new GhidraPythonInterpreter. Could be null if it failed to be created.
|
* @return A new GhidraPythonInterpreter. Could be null if it failed to be created.
|
||||||
*/
|
*/
|
||||||
public static GhidraPythonInterpreter get() {
|
public static GhidraJythonInterpreter get() {
|
||||||
|
|
||||||
// Initialize the python environment if necessary. Only needs to happen once.
|
// Initialize the python environment if necessary. Only needs to happen once.
|
||||||
if (!pythonInitialized) {
|
if (!pythonInitialized) {
|
||||||
try {
|
try {
|
||||||
// Setup python home directory
|
// Setup python home directory
|
||||||
PythonUtils.setupPythonHomeDir();
|
JythonUtils.setupJythonHomeDir();
|
||||||
|
|
||||||
// Setup python cache directory
|
// Setup python cache directory
|
||||||
PythonUtils.setupPythonCacheDir(TaskMonitor.DUMMY);
|
JythonUtils.setupJythonCacheDir(TaskMonitor.DUMMY);
|
||||||
|
|
||||||
// Indicate that we've initialized the python environment, which should
|
// Indicate that we've initialized the python environment, which should
|
||||||
// only happen once.
|
// only happen once.
|
||||||
pythonInitialized = true;
|
pythonInitialized = true;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Msg.showError(GhidraPythonInterpreter.class, null, "Python error",
|
Msg.showError(GhidraJythonInterpreter.class, null, "Python error",
|
||||||
"Problem getting Ghirda Python interpreter", e);
|
"Problem getting Ghirda Python interpreter", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
state.ps2 = new PyString("... ");
|
state.ps2 = new PyString("... ");
|
||||||
|
|
||||||
// Return a new instance of our interpreter
|
// Return a new instance of our interpreter
|
||||||
return new GhidraPythonInterpreter(state);
|
return new GhidraJythonInterpreter(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,7 +94,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
*
|
*
|
||||||
* @param state The initial system state of the interpreter.
|
* @param state The initial system state of the interpreter.
|
||||||
*/
|
*/
|
||||||
private GhidraPythonInterpreter(PySystemState state) {
|
private GhidraJythonInterpreter(PySystemState state) {
|
||||||
super(null, state);
|
super(null, state);
|
||||||
|
|
||||||
// Store the default python path in case we need to reset it later.
|
// Store the default python path in case we need to reset it later.
|
||||||
|
@ -158,7 +158,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
* @throws PyException if an unhandled exception occurred while executing the line of python
|
* @throws PyException if an unhandled exception occurred while executing the line of python
|
||||||
* @throws IllegalStateException if this interpreter has been cleaned up.
|
* @throws IllegalStateException if this interpreter has been cleaned up.
|
||||||
*/
|
*/
|
||||||
public synchronized boolean push(String line, PythonScript script)
|
public synchronized boolean push(String line, JythonScript script)
|
||||||
throws PyException, IllegalStateException {
|
throws PyException, IllegalStateException {
|
||||||
|
|
||||||
if (cleanedUp) {
|
if (cleanedUp) {
|
||||||
|
@ -198,7 +198,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
* @param script A PythonScript from which we load state (or null).
|
* @param script A PythonScript from which we load state (or null).
|
||||||
* @throws IllegalStateException if this interpreter has been cleaned up.
|
* @throws IllegalStateException if this interpreter has been cleaned up.
|
||||||
*/
|
*/
|
||||||
public synchronized void execFile(ResourceFile file, PythonScript script)
|
public synchronized void execFile(ResourceFile file, JythonScript script)
|
||||||
throws IllegalStateException {
|
throws IllegalStateException {
|
||||||
|
|
||||||
if (cleanedUp) {
|
if (cleanedUp) {
|
||||||
|
@ -332,7 +332,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
*
|
*
|
||||||
* @param script The script whose class hierarchy is to be used for injection.
|
* @param script The script whose class hierarchy is to be used for injection.
|
||||||
*/
|
*/
|
||||||
void injectScriptHierarchy(PythonScript script) {
|
void injectScriptHierarchy(JythonScript script) {
|
||||||
|
|
||||||
if (script == null) {
|
if (script == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -447,7 +447,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||||
* @param includeBuiltins True if we should include python built-ins; otherwise, false.
|
* @param includeBuiltins True if we should include python built-ins; otherwise, false.
|
||||||
* @param caretPos The position of the caret in the input string 'cmd'
|
* @param caretPos The position of the caret in the input string 'cmd'
|
||||||
* @return A list of possible command completions. Could be empty if there aren't any.
|
* @return A list of possible command completions. Could be empty if there aren't any.
|
||||||
* @see PythonPlugin#getCompletions
|
* @see JythonPlugin#getCompletions
|
||||||
*/
|
*/
|
||||||
List<CodeCompletion> getCommandCompletions(String cmd, boolean includeBuiltins, int caretPos) {
|
List<CodeCompletion> getCommandCompletions(String cmd, boolean includeBuiltins, int caretPos) {
|
||||||
// At this point the caret is assumed to be positioned right after the value we need to
|
// At this point the caret is assumed to be positioned right after the value we need to
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -31,12 +31,12 @@ import ghidra.framework.options.Options;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates CodeCompletions from Python objects.
|
* Generates CodeCompletions from Jython objects.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class PythonCodeCompletionFactory {
|
public class JythonCodeCompletionFactory {
|
||||||
private static List<Class<?>> classes = new ArrayList<>();
|
private static List<Class<?>> classes = new ArrayList<>();
|
||||||
private static Map<Class<?>, Color> classToColorMap = new HashMap<>();
|
private static Map<Class<?>, Color> classToColorMap = new HashMap<>();
|
||||||
/* necessary because we only want to show the user the simple class name
|
/* necessary because we only want to show the user the simple class name
|
||||||
|
@ -47,7 +47,7 @@ public class PythonCodeCompletionFactory {
|
||||||
private static Map<Class<?>, String> classDescription = new HashMap<>();
|
private static Map<Class<?>, String> classDescription = new HashMap<>();
|
||||||
public static final String COMPLETION_LABEL = "Code Completion Colors";
|
public static final String COMPLETION_LABEL = "Code Completion Colors";
|
||||||
|
|
||||||
/* package-level accessibility so that PythonPlugin can tell this is
|
/* package-level accessibility so that JythonPlugin can tell this is
|
||||||
* our option
|
* our option
|
||||||
*/
|
*/
|
||||||
final static String INCLUDE_TYPES_LABEL = "Include type names in code completion popup?";
|
final static String INCLUDE_TYPES_LABEL = "Include type names in code completion popup?";
|
||||||
|
@ -59,19 +59,19 @@ public class PythonCodeCompletionFactory {
|
||||||
private static boolean includeTypes = INCLUDE_TYPES_DEFAULT;
|
private static boolean includeTypes = INCLUDE_TYPES_DEFAULT;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
public static final Color NULL_COLOR = new GColor("color.fg.plugin.python.syntax.null");
|
public static final Color NULL_COLOR = new GColor("color.fg.plugin.jython.syntax.null");
|
||||||
public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.python.syntax.function");
|
public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.jython.syntax.function");
|
||||||
public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.python.syntax.package");
|
public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.jython.syntax.package");
|
||||||
public static final Color CLASS_COLOR = new GColor("color.fg.plugin.python.syntax.class");
|
public static final Color CLASS_COLOR = new GColor("color.fg.plugin.jython.syntax.class");
|
||||||
public static final Color METHOD_COLOR = new GColor("color.fg.plugin.python.syntax.method");
|
public static final Color METHOD_COLOR = new GColor("color.fg.plugin.jython.syntax.method");
|
||||||
/* anonymous code chunks */
|
/* anonymous code chunks */
|
||||||
public static final Color CODE_COLOR = new GColor("color.fg.plugin.python.syntax.code");
|
public static final Color CODE_COLOR = new GColor("color.fg.plugin.jython.syntax.code");
|
||||||
public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.python.syntax.instance");
|
public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.jython.syntax.instance");
|
||||||
public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.python.syntax.sequence");
|
public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.jython.syntax.sequence");
|
||||||
public static final Color MAP_COLOR = new GColor("color.fg.plugin.python.syntax.map");
|
public static final Color MAP_COLOR = new GColor("color.fg.plugin.jython.syntax.map");
|
||||||
public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.python.syntax.number");
|
public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.jython.syntax.number");
|
||||||
/* for weird Jython-specific stuff */
|
/* for weird Jython-specific stuff */
|
||||||
public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.python.syntax.special");
|
public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.jython.syntax.special");
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -174,18 +174,18 @@ public class PythonCodeCompletionFactory {
|
||||||
classDescription.put(klass, description);
|
classDescription.put(klass, description);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException cnfe) {
|
catch (ClassNotFoundException cnfe) {
|
||||||
Msg.debug(PythonCodeCompletionFactory.class, "Unable to find class: " + className,
|
Msg.debug(JythonCodeCompletionFactory.class, "Unable to find class: " + className,
|
||||||
cnfe);
|
cnfe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new CodeCompletion from the given Python objects.
|
* Creates a new CodeCompletion from the given Jython objects.
|
||||||
*
|
*
|
||||||
* @param description description of the new CodeCompletion
|
* @param description description of the new CodeCompletion
|
||||||
* @param insertion what will be inserted to make the code complete
|
* @param insertion what will be inserted to make the code complete
|
||||||
* @param pyObj a Python Object
|
* @param pyObj a Jython Object
|
||||||
* @return A new CodeCompletion from the given Python objects.
|
* @return A new CodeCompletion from the given Jython objects.
|
||||||
* @deprecated use {@link #newCodeCompletion(String, String, PyObject, String)} instead,
|
* @deprecated use {@link #newCodeCompletion(String, String, PyObject, String)} instead,
|
||||||
* it allows creation of substituting code completions
|
* it allows creation of substituting code completions
|
||||||
*/
|
*/
|
||||||
|
@ -196,15 +196,15 @@ public class PythonCodeCompletionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new CodeCompletion from the given Python objects.
|
* Creates a new CodeCompletion from the given Jython objects.
|
||||||
*
|
*
|
||||||
* @param description description of the new CodeCompletion
|
* @param description description of the new CodeCompletion
|
||||||
* @param insertion what will be inserted to make the code complete
|
* @param insertion what will be inserted to make the code complete
|
||||||
* @param pyObj a Python Object
|
* @param pyObj a Jython Object
|
||||||
* @param userInput a word we want to complete, can be an empty string.
|
* @param userInput a word we want to complete, can be an empty string.
|
||||||
* It's used to determine which part (if any) of the input should be
|
* It's used to determine which part (if any) of the input should be
|
||||||
* removed before the insertion of the completion
|
* removed before the insertion of the completion
|
||||||
* @return A new CodeCompletion from the given Python objects.
|
* @return A new CodeCompletion from the given Jython objects.
|
||||||
*/
|
*/
|
||||||
public static CodeCompletion newCodeCompletion(String description, String insertion,
|
public static CodeCompletion newCodeCompletion(String description, String insertion,
|
||||||
PyObject pyObj, String userInput) {
|
PyObject pyObj, String userInput) {
|
||||||
|
@ -241,11 +241,11 @@ public class PythonCodeCompletionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up Python code completion Options.
|
* Sets up Jython code completion Options.
|
||||||
* @param plugin python plugin as options owner
|
* @param plugin jython plugin as options owner
|
||||||
* @param options an Options handle
|
* @param options an Options handle
|
||||||
*/
|
*/
|
||||||
public static void setupOptions(PythonPlugin plugin, Options options) {
|
public static void setupOptions(JythonPlugin plugin, Options options) {
|
||||||
includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT);
|
includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT);
|
||||||
options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null,
|
options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null,
|
||||||
INCLUDE_TYPES_DESCRIPTION);
|
INCLUDE_TYPES_DESCRIPTION);
|
||||||
|
@ -271,20 +271,20 @@ public class PythonCodeCompletionFactory {
|
||||||
includeTypes = ((Boolean) newValue).booleanValue();
|
includeTypes = ((Boolean) newValue).booleanValue();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Msg.error(PythonCodeCompletionFactory.class, "unknown option '" + name + "'");
|
Msg.error(JythonCodeCompletionFactory.class, "unknown option '" + name + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Java __call__ methods declared for a Python object.
|
* Returns the Java __call__ methods declared for a Jython object.
|
||||||
*
|
*
|
||||||
* Some Python "methods" in the new-style Python objects are actually
|
* Some Jython "methods" in the new-style Jython objects are actually
|
||||||
* classes in and of themselves, re-implementing __call__ methods to
|
* classes in and of themselves, re-implementing __call__ methods to
|
||||||
* tell us how to call them. This returns an array of those Methods
|
* tell us how to call them. This returns an array of those Methods
|
||||||
* (for code completion help).
|
* (for code completion help).
|
||||||
*
|
*
|
||||||
* @param obj a PyObject
|
* @param obj a PyObject
|
||||||
* @return the Java __call__ methods declared for the Python object
|
* @return the Java __call__ methods declared for the Jython object
|
||||||
*/
|
*/
|
||||||
public static Object[] getCallMethods(PyObject obj) {
|
public static Object[] getCallMethods(PyObject obj) {
|
||||||
List<Method> callMethodList = new ArrayList<>();
|
List<Method> callMethodList = new ArrayList<>();
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -44,44 +44,44 @@ import ghidra.util.task.*;
|
||||||
import resources.Icons;
|
import resources.Icons;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This plugin provides the interactive Python interpreter.
|
* This plugin provides the interactive Jython interpreter.
|
||||||
*/
|
*/
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@PluginInfo(
|
@PluginInfo(
|
||||||
status = PluginStatus.RELEASED,
|
status = PluginStatus.RELEASED,
|
||||||
packageName = CorePluginPackage.NAME,
|
packageName = CorePluginPackage.NAME,
|
||||||
category = PluginCategoryNames.COMMON,
|
category = PluginCategoryNames.COMMON,
|
||||||
shortDescription = "Python Interpreter",
|
shortDescription = "Jython Interpreter",
|
||||||
description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.",
|
description = "Provides an interactive Jython Interpreter that is tightly integrated with a loaded Ghidra program.",
|
||||||
servicesRequired = { InterpreterPanelService.class },
|
servicesRequired = { InterpreterPanelService.class },
|
||||||
isSlowInstallation = true
|
isSlowInstallation = true
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class PythonPlugin extends ProgramPlugin
|
public class JythonPlugin extends ProgramPlugin
|
||||||
implements InterpreterConnection, OptionsChangeListener {
|
implements InterpreterConnection, OptionsChangeListener {
|
||||||
|
|
||||||
private InterpreterConsole console;
|
private InterpreterConsole console;
|
||||||
private GhidraPythonInterpreter interpreter;
|
private GhidraJythonInterpreter interpreter;
|
||||||
private PythonScript interactiveScript;
|
private JythonScript interactiveScript;
|
||||||
private TaskMonitor interactiveTaskMonitor;
|
private TaskMonitor interactiveTaskMonitor;
|
||||||
private PythonPluginInputThread inputThread;
|
private JythonPluginInputThread inputThread;
|
||||||
|
|
||||||
// Plugin options
|
// Plugin options
|
||||||
private final static String INCLUDE_BUILTINS_LABEL = "Include \"builtins\" in code completion?";
|
private final static String INCLUDE_BUILTINS_LABEL = "Include \"builtins\" in code completion?";
|
||||||
private final static String INCLUDE_BUILTINS_DESCRIPTION =
|
private final static String INCLUDE_BUILTINS_DESCRIPTION =
|
||||||
"Whether or not to include Python's built-in functions and properties in the pop-up code completion window.";
|
"Whether or not to include Jython's built-in functions and properties in the pop-up code completion window.";
|
||||||
private final static boolean INCLUDE_BUILTINS_DEFAULT = true;
|
private final static boolean INCLUDE_BUILTINS_DEFAULT = true;
|
||||||
|
|
||||||
private static final Icon ICON = new GIcon("icon.plugin.python");
|
private static final Icon ICON = new GIcon("icon.plugin.jython");
|
||||||
|
|
||||||
private boolean includeBuiltins = INCLUDE_BUILTINS_DEFAULT;
|
private boolean includeBuiltins = INCLUDE_BUILTINS_DEFAULT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new PythonPlugin object.
|
* Creates a new {@link JythonPlugin} object.
|
||||||
*
|
*
|
||||||
* @param tool The tool associated with this plugin.
|
* @param tool The tool associated with this plugin.
|
||||||
*/
|
*/
|
||||||
public PythonPlugin(PluginTool tool) {
|
public JythonPlugin(PluginTool tool) {
|
||||||
super(tool);
|
super(tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,11 +95,11 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the plugin's Python interpreter.
|
* Gets the plugin's Jython interpreter.
|
||||||
*
|
*
|
||||||
* @return The plugin's Python interpreter. May be null.
|
* @return The plugin's Jython interpreter. May be null.
|
||||||
*/
|
*/
|
||||||
GhidraPythonInterpreter getInterpreter() {
|
GhidraJythonInterpreter getInterpreter() {
|
||||||
return interpreter;
|
return interpreter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
*
|
*
|
||||||
* @return The plugin's interactive script.
|
* @return The plugin's interactive script.
|
||||||
*/
|
*/
|
||||||
PythonScript getInteractiveScript() {
|
JythonScript getInteractiveScript() {
|
||||||
return interactiveScript;
|
return interactiveScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the interpreter to a new starting state. This is used when the plugin is first
|
* Resets the interpreter to a new starting state. This is used when the plugin is first
|
||||||
* initialized, as well as when an existing interpreter receives a Python exit command.
|
* initialized, as well as when an existing interpreter receives a Jython exit command.
|
||||||
* We used to try to reset the same interpreter, but it was really hard to do that correctly
|
* We used to try to reset the same interpreter, but it was really hard to do that correctly
|
||||||
* so we now just create a brand new one.
|
* so we now just create a brand new one.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -181,7 +181,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
*/
|
*/
|
||||||
private void resetInterpreter() {
|
private void resetInterpreter() {
|
||||||
|
|
||||||
TaskLauncher.launchModal("Resetting Python...", () -> {
|
TaskLauncher.launchModal("Resetting Jython...", () -> {
|
||||||
resetInterpreterInBackground();
|
resetInterpreterInBackground();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -193,23 +193,23 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
if (interpreter == null) {
|
if (interpreter == null) {
|
||||||
|
|
||||||
// Setup options
|
// Setup options
|
||||||
ToolOptions options = tool.getOptions("Python");
|
ToolOptions options = tool.getOptions("Jython");
|
||||||
includeBuiltins = options.getBoolean(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT);
|
includeBuiltins = options.getBoolean(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT);
|
||||||
options.registerOption(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT, null,
|
options.registerOption(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT, null,
|
||||||
INCLUDE_BUILTINS_DESCRIPTION);
|
INCLUDE_BUILTINS_DESCRIPTION);
|
||||||
options.addOptionsChangeListener(this);
|
options.addOptionsChangeListener(this);
|
||||||
|
|
||||||
interpreter = GhidraPythonInterpreter.get();
|
interpreter = GhidraJythonInterpreter.get();
|
||||||
|
|
||||||
// Setup code completion. This currently has to be done after the interpreter
|
// Setup code completion. This currently has to be done after the interpreter
|
||||||
// is created. Otherwise an exception will occur.
|
// is created. Otherwise an exception will occur.
|
||||||
PythonCodeCompletionFactory.setupOptions(this, options);
|
JythonCodeCompletionFactory.setupOptions(this, options);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
inputThread.shutdown();
|
inputThread.shutdown();
|
||||||
inputThread = null;
|
inputThread = null;
|
||||||
interpreter.cleanup();
|
interpreter.cleanup();
|
||||||
interpreter = GhidraPythonInterpreter.get();
|
interpreter = GhidraJythonInterpreter.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the console.
|
// Reset the console.
|
||||||
|
@ -224,20 +224,20 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
// Print a welcome message.
|
// Print a welcome message.
|
||||||
welcome();
|
welcome();
|
||||||
|
|
||||||
// Setup the PythonScript describing the state of the interactive prompt.
|
// Setup the JythonScript describing the state of the interactive prompt.
|
||||||
// This allows things like currentProgram and currentAddress to dynamically reflect
|
// This allows things like currentProgram and currentAddress to dynamically reflect
|
||||||
// what's happening in the listing. Injecting the script hierarchy early here allows
|
// what's happening in the listing. Injecting the script hierarchy early here allows
|
||||||
// code completion to work before commands are entered.
|
// code completion to work before commands are entered.
|
||||||
interactiveScript = new PythonScript();
|
interactiveScript = new JythonScript();
|
||||||
interactiveScript.set(
|
interactiveScript.set(
|
||||||
new GhidraState(tool, tool.getProject(), getCurrentProgram(), getProgramLocation(),
|
new GhidraState(tool, tool.getProject(), getCurrentProgram(), getProgramLocation(),
|
||||||
getProgramSelection(), getProgramHighlight()),
|
getProgramSelection(), getProgramHighlight()),
|
||||||
interactiveTaskMonitor, new PrintWriter(getConsole().getStdOut()));
|
interactiveTaskMonitor, new PrintWriter(getConsole().getStdOut()));
|
||||||
interpreter.injectScriptHierarchy(interactiveScript);
|
interpreter.injectScriptHierarchy(interactiveScript);
|
||||||
interactiveTaskMonitor = new PythonInteractiveTaskMonitor(console.getStdOut());
|
interactiveTaskMonitor = new JythonInteractiveTaskMonitor(console.getStdOut());
|
||||||
|
|
||||||
// Start the input thread that receives python commands to execute.
|
// Start the input thread that receives jython commands to execute.
|
||||||
inputThread = new PythonPluginInputThread(this);
|
inputThread = new JythonPluginInputThread(this);
|
||||||
inputThread.start();
|
inputThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,11 +252,11 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
@Override
|
@Override
|
||||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
if (optionName.startsWith(PythonCodeCompletionFactory.COMPLETION_LABEL)) {
|
if (optionName.startsWith(JythonCodeCompletionFactory.COMPLETION_LABEL)) {
|
||||||
PythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
JythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
||||||
}
|
}
|
||||||
else if (optionName.equals(PythonCodeCompletionFactory.INCLUDE_TYPES_LABEL)) {
|
else if (optionName.equals(JythonCodeCompletionFactory.INCLUDE_TYPES_LABEL)) {
|
||||||
PythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
JythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
||||||
}
|
}
|
||||||
else if (optionName.equals(INCLUDE_BUILTINS_LABEL)) {
|
else if (optionName.equals(INCLUDE_BUILTINS_LABEL)) {
|
||||||
includeBuiltins = ((Boolean) newValue).booleanValue();
|
includeBuiltins = ((Boolean) newValue).booleanValue();
|
||||||
|
@ -284,7 +284,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
@Override
|
@Override
|
||||||
public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
|
public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
|
||||||
// Refresh the environment
|
// Refresh the environment
|
||||||
interactiveScript.setSourceFile(new ResourceFile(new File("python")));
|
interactiveScript.setSourceFile(new ResourceFile(new File("jython")));
|
||||||
interactiveScript.set(
|
interactiveScript.set(
|
||||||
new GhidraState(tool, tool.getProject(), currentProgram, currentLocation,
|
new GhidraState(tool, tool.getProject(), currentProgram, currentLocation,
|
||||||
currentSelection, currentHighlight),
|
currentSelection, currentHighlight),
|
||||||
|
@ -327,7 +327,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
if (interpreter == null) {
|
if (interpreter == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
interpreter.interrupt(inputThread.getPythonPluginExecutionThread());
|
interpreter.interrupt(inputThread.getJythonPluginExecutionThread());
|
||||||
console.setPrompt(interpreter.getPrimaryPrompt());
|
console.setPrompt(interpreter.getPrimaryPrompt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "Python";
|
return "Jython";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -361,7 +361,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
* Prints a welcome message to the console.
|
* Prints a welcome message to the console.
|
||||||
*/
|
*/
|
||||||
private void welcome() {
|
private void welcome() {
|
||||||
console.getOutWriter().println("Python Interpreter for Ghidra");
|
console.getOutWriter().println("Jython Interpreter for Ghidra");
|
||||||
console.getOutWriter().println("Based on Jython version " + PySystemState.version);
|
console.getOutWriter().println("Based on Jython version " + PySystemState.version);
|
||||||
console.getOutWriter().println("Press 'F1' for usage instructions");
|
console.getOutWriter().println("Press 'F1' for usage instructions");
|
||||||
}
|
}
|
||||||
|
@ -369,20 +369,20 @@ public class PythonPlugin extends ProgramPlugin
|
||||||
/**
|
/**
|
||||||
* Support for cancelling execution using a TaskMonitor.
|
* Support for cancelling execution using a TaskMonitor.
|
||||||
*/
|
*/
|
||||||
class PythonInteractiveTaskMonitor extends TaskMonitorAdapter {
|
class JythonInteractiveTaskMonitor extends TaskMonitorAdapter {
|
||||||
private PrintWriter output = null;
|
private PrintWriter output = null;
|
||||||
|
|
||||||
public PythonInteractiveTaskMonitor(PrintWriter stdOut) {
|
public JythonInteractiveTaskMonitor(PrintWriter stdOut) {
|
||||||
output = stdOut;
|
output = stdOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PythonInteractiveTaskMonitor(OutputStream stdout) {
|
public JythonInteractiveTaskMonitor(OutputStream stdout) {
|
||||||
this(new PrintWriter(stdout));
|
this(new PrintWriter(stdout));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMessage(String message) {
|
public void setMessage(String message) {
|
||||||
output.println("<python-interactive>: " + message);
|
output.println("<jython-interactive>: " + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
@ -29,23 +29,24 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread responsible for executing a python command for the plugin.
|
* Thread responsible for executing a jython command for the plugin.
|
||||||
*/
|
*/
|
||||||
class PythonPluginExecutionThread extends Thread {
|
class JythonPluginExecutionThread extends Thread {
|
||||||
|
|
||||||
private PythonPlugin plugin;
|
private JythonPlugin plugin;
|
||||||
private String cmd;
|
private String cmd;
|
||||||
private AtomicBoolean moreInputWanted;
|
private AtomicBoolean moreInputWanted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new python plugin execution thread that executes the given command for the given plugin.
|
* Creates a new jython plugin execution thread that executes the given command for the given
|
||||||
|
* plugin.
|
||||||
*
|
*
|
||||||
* @param plugin The python plugin to execute the command for.
|
* @param plugin The jython plugin to execute the command for.
|
||||||
* @param cmd The python command to execute.
|
* @param cmd The jython command to execute.
|
||||||
* @param moreInputWanted Gets set to indicate that the executed command expects more input.
|
* @param moreInputWanted Gets set to indicate that the executed command expects more input.
|
||||||
*/
|
*/
|
||||||
PythonPluginExecutionThread(PythonPlugin plugin, String cmd, AtomicBoolean moreInputWanted) {
|
JythonPluginExecutionThread(JythonPlugin plugin, String cmd, AtomicBoolean moreInputWanted) {
|
||||||
super("Python plugin execution thread");
|
super("Jython plugin execution thread");
|
||||||
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.cmd = cmd;
|
this.cmd = cmd;
|
||||||
|
@ -56,14 +57,14 @@ class PythonPluginExecutionThread extends Thread {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
TaskMonitor interactiveTaskMonitor = plugin.getInteractiveTaskMonitor();
|
TaskMonitor interactiveTaskMonitor = plugin.getInteractiveTaskMonitor();
|
||||||
PythonScript interactiveScript = plugin.getInteractiveScript();
|
JythonScript interactiveScript = plugin.getInteractiveScript();
|
||||||
Program program = plugin.getCurrentProgram();
|
Program program = plugin.getCurrentProgram();
|
||||||
|
|
||||||
// Setup transaction for the execution.
|
// Setup transaction for the execution.
|
||||||
try (Transaction tx = program != null ? program.openTransaction("Python command") : null) {
|
try (Transaction tx = program != null ? program.openTransaction("Jython command") : null) {
|
||||||
// Setup Ghidra state to be passed into interpreter
|
// Setup Ghidra state to be passed into interpreter
|
||||||
interactiveTaskMonitor.clearCancelled();
|
interactiveTaskMonitor.clearCancelled();
|
||||||
interactiveScript.setSourceFile(new ResourceFile(new File("python")));
|
interactiveScript.setSourceFile(new ResourceFile(new File("jython")));
|
||||||
PluginTool tool = plugin.getTool();
|
PluginTool tool = plugin.getTool();
|
||||||
interactiveScript.set(
|
interactiveScript.set(
|
||||||
new GhidraState(tool, tool.getProject(), program, plugin.getProgramLocation(),
|
new GhidraState(tool, tool.getProject(), program, plugin.getProgramLocation(),
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
@ -21,37 +21,37 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread responsible for getting interactive lines of python from the plugin.
|
* Thread responsible for getting interactive lines of jython from the plugin.
|
||||||
* This class also kicks off the execution of that line in a new {@link PythonPluginExecutionThread}.
|
* This class also kicks off the execution of that line in a new {@link JythonPluginExecutionThread}.
|
||||||
*/
|
*/
|
||||||
class PythonPluginInputThread extends Thread {
|
class JythonPluginInputThread extends Thread {
|
||||||
|
|
||||||
private static int generationCount = 0;
|
private static int generationCount = 0;
|
||||||
|
|
||||||
private final PythonPlugin plugin;
|
private final JythonPlugin plugin;
|
||||||
private final AtomicBoolean moreInputWanted = new AtomicBoolean(false);
|
private final AtomicBoolean moreInputWanted = new AtomicBoolean(false);
|
||||||
private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
|
private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
|
||||||
private final InputStream consoleStdin;
|
private final InputStream consoleStdin;
|
||||||
private PythonPluginExecutionThread pythonExecutionThread;
|
private JythonPluginExecutionThread jythonExecutionThread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new python input thread that gets a line of python input from the given plugin.
|
* Creates a new jython input thread that gets a line of jython input from the given plugin.
|
||||||
*
|
*
|
||||||
* @param plugin The python plugin to get input from.
|
* @param plugin The jython plugin to get input from.
|
||||||
*/
|
*/
|
||||||
PythonPluginInputThread(PythonPlugin plugin) {
|
JythonPluginInputThread(JythonPlugin plugin) {
|
||||||
super("Python plugin input thread (generation " + ++generationCount + ")");
|
super("Jython plugin input thread (generation " + ++generationCount + ")");
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.consoleStdin = plugin.getConsole().getStdin();
|
this.consoleStdin = plugin.getConsole().getStdin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the last python plugin execution thread that ran.
|
* Gets the last jython plugin execution thread that ran.
|
||||||
*
|
*
|
||||||
* @return The last python plugin execution thread that ran. Could be null if one never ran.
|
* @return The last jython plugin execution thread that ran. Could be null if one never ran.
|
||||||
*/
|
*/
|
||||||
PythonPluginExecutionThread getPythonPluginExecutionThread() {
|
JythonPluginExecutionThread getJythonPluginExecutionThread() {
|
||||||
return pythonExecutionThread;
|
return jythonExecutionThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,13 +61,13 @@ class PythonPluginInputThread extends Thread {
|
||||||
while (!shutdownRequested.get() && (line = reader.readLine()) != null) {
|
while (!shutdownRequested.get() && (line = reader.readLine()) != null) {
|
||||||
|
|
||||||
// Execute the line in a new thread
|
// Execute the line in a new thread
|
||||||
pythonExecutionThread =
|
jythonExecutionThread =
|
||||||
new PythonPluginExecutionThread(plugin, line, moreInputWanted);
|
new JythonPluginExecutionThread(plugin, line, moreInputWanted);
|
||||||
pythonExecutionThread.start();
|
jythonExecutionThread.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Wait for the execution to finish
|
// Wait for the execution to finish
|
||||||
pythonExecutionThread.join();
|
jythonExecutionThread.join();
|
||||||
}
|
}
|
||||||
catch (InterruptedException ie) {
|
catch (InterruptedException ie) {
|
||||||
// Hey we're back... a little earlier than expected, but there must be a reason.
|
// Hey we're back... a little earlier than expected, but there must be a reason.
|
||||||
|
@ -82,7 +82,7 @@ class PythonPluginInputThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
Msg.error(PythonPluginInputThread.class,
|
Msg.error(JythonPluginInputThread.class,
|
||||||
"Internal error reading commands from interpreter console. Please reset the interpreter.",
|
"Internal error reading commands from interpreter console. Please reset the interpreter.",
|
||||||
e);
|
e);
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import ghidra.util.exception.CancelledException;
|
||||||
/**
|
/**
|
||||||
* Launcher entry point for running Ghidra from within Jython.
|
* Launcher entry point for running Ghidra from within Jython.
|
||||||
*/
|
*/
|
||||||
public class PythonRun implements GhidraLaunchable {
|
public class JythonRun implements GhidraLaunchable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch(GhidraApplicationLayout layout, String[] args) {
|
public void launch(GhidraApplicationLayout layout, String[] args) {
|
||||||
|
@ -37,25 +37,25 @@ public class PythonRun implements GhidraLaunchable {
|
||||||
ApplicationConfiguration configuration = new HeadlessGhidraApplicationConfiguration();
|
ApplicationConfiguration configuration = new HeadlessGhidraApplicationConfiguration();
|
||||||
Application.initializeApplication(layout, configuration);
|
Application.initializeApplication(layout, configuration);
|
||||||
|
|
||||||
// Setup python home directory
|
// Setup jython home directory
|
||||||
try {
|
try {
|
||||||
PythonUtils.setupPythonHomeDir();
|
JythonUtils.setupJythonHomeDir();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
Msg.showError(PythonRun.class, null, "Python home directory", e.getMessage());
|
Msg.showError(JythonRun.class, null, "Jython home directory", e.getMessage());
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup python cache directory
|
// Setup jython cache directory
|
||||||
try {
|
try {
|
||||||
PythonUtils.setupPythonCacheDir(configuration.getTaskMonitor());
|
JythonUtils.setupJythonCacheDir(configuration.getTaskMonitor());
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
Msg.showError(PythonRun.class, null, "Python cache directory", e.getMessage());
|
Msg.showError(JythonRun.class, null, "Jython cache directory", e.getMessage());
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
Msg.showError(PythonRun.class, null, "Operation cancelled", e.getMessage());
|
Msg.showError(JythonRun.class, null, "Operation cancelled", e.getMessage());
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
@ -25,11 +25,11 @@ import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Python version of a {@link GhidraScript}.
|
* A Jython version of a {@link GhidraScript}.
|
||||||
*/
|
*/
|
||||||
public class PythonScript extends GhidraScript {
|
public class JythonScript extends GhidraScript {
|
||||||
|
|
||||||
static final String PYTHON_INTERPRETER = "ghidra.python.interpreter";
|
static final String JYTHON_INTERPRETER = "ghidra.jython.interpreter";
|
||||||
|
|
||||||
private AtomicBoolean interpreterRunning = new AtomicBoolean();
|
private AtomicBoolean interpreterRunning = new AtomicBoolean();
|
||||||
|
|
||||||
|
@ -37,10 +37,10 @@ public class PythonScript extends GhidraScript {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// Try to get the interpreter from an existing script state.
|
// Try to get the interpreter from an existing script state.
|
||||||
GhidraPythonInterpreter interpreter =
|
GhidraJythonInterpreter interpreter =
|
||||||
(GhidraPythonInterpreter) state.getEnvironmentVar(PYTHON_INTERPRETER);
|
(GhidraJythonInterpreter) state.getEnvironmentVar(JYTHON_INTERPRETER);
|
||||||
|
|
||||||
// Are we being called from an already running PythonScript with existing state?
|
// Are we being called from an already running JythonScript with existing state?
|
||||||
if (interpreter != null) {
|
if (interpreter != null) {
|
||||||
runInExistingEnvironment(interpreter);
|
runInExistingEnvironment(interpreter);
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,12 @@ public class PythonScript extends GhidraScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runScript(String scriptName, GhidraState scriptState) throws Exception {
|
public void runScript(String scriptName, GhidraState scriptState) throws Exception {
|
||||||
GhidraPythonInterpreter interpreter =
|
GhidraJythonInterpreter interpreter =
|
||||||
(GhidraPythonInterpreter) state.getEnvironmentVar(PYTHON_INTERPRETER);
|
(GhidraJythonInterpreter) state.getEnvironmentVar(JYTHON_INTERPRETER);
|
||||||
if (interpreter == null) {
|
if (interpreter == null) {
|
||||||
interpreter = GhidraPythonInterpreter.get();
|
interpreter = GhidraJythonInterpreter.get();
|
||||||
if (interpreter == null) {
|
if (interpreter == null) {
|
||||||
throw new AssertException("Could not get Ghidra Python interpreter!");
|
throw new AssertException("Could not get Ghidra Jython interpreter!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(scriptName);
|
ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(scriptName);
|
||||||
|
@ -71,10 +71,10 @@ public class PythonScript extends GhidraScript {
|
||||||
updateStateFromVariables();
|
updateStateFromVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ghidraScript instanceof PythonScript) {
|
if (ghidraScript instanceof JythonScript) {
|
||||||
ghidraScript.set(scriptState, monitor, writer);
|
ghidraScript.set(scriptState, monitor, writer);
|
||||||
PythonScript pythonScript = (PythonScript) ghidraScript;
|
JythonScript jythonScript = (JythonScript) ghidraScript;
|
||||||
interpreter.execFile(pythonScript.getSourceFile(), pythonScript);
|
interpreter.execFile(jythonScript.getSourceFile(), jythonScript);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ghidraScript.execute(scriptState, monitor, writer);
|
ghidraScript.execute(scriptState, monitor, writer);
|
||||||
|
@ -93,7 +93,7 @@ public class PythonScript extends GhidraScript {
|
||||||
*
|
*
|
||||||
* @param interpreter The existing interpreter to execute from.
|
* @param interpreter The existing interpreter to execute from.
|
||||||
*/
|
*/
|
||||||
private void runInExistingEnvironment(GhidraPythonInterpreter interpreter) {
|
private void runInExistingEnvironment(GhidraJythonInterpreter interpreter) {
|
||||||
interpreter.execFile(sourceFile, this);
|
interpreter.execFile(sourceFile, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ public class PythonScript extends GhidraScript {
|
||||||
private void runInNewEnvironment() {
|
private void runInNewEnvironment() {
|
||||||
|
|
||||||
// Create new interpreter and stick it in the script's state.
|
// Create new interpreter and stick it in the script's state.
|
||||||
final GhidraPythonInterpreter interpreter = GhidraPythonInterpreter.get();
|
final GhidraJythonInterpreter interpreter = GhidraJythonInterpreter.get();
|
||||||
final PrintWriter stdout = getStdOut();
|
final PrintWriter stdout = getStdOut();
|
||||||
final PrintWriter stderr = getStdErr();
|
final PrintWriter stderr = getStdErr();
|
||||||
interpreter.setOut(stdout);
|
interpreter.setOut(stdout);
|
||||||
|
@ -114,11 +114,11 @@ public class PythonScript extends GhidraScript {
|
||||||
// script will use the same interpreter. It is questionable whether or not we should do
|
// script will use the same interpreter. It is questionable whether or not we should do
|
||||||
// this (the new script will get all of the old script's variables), but changing it now
|
// this (the new script will get all of the old script's variables), but changing it now
|
||||||
// could break people's scripts if they expect this behavior.
|
// could break people's scripts if they expect this behavior.
|
||||||
state.addEnvironmentVar(PYTHON_INTERPRETER, interpreter);
|
state.addEnvironmentVar(JYTHON_INTERPRETER, interpreter);
|
||||||
|
|
||||||
// Execute the script in a new thread.
|
// Execute the script in a new thread.
|
||||||
PythonScriptExecutionThread executionThread =
|
JythonScriptExecutionThread executionThread =
|
||||||
new PythonScriptExecutionThread(this, interpreter, interpreterRunning);
|
new JythonScriptExecutionThread(this, interpreter, interpreterRunning);
|
||||||
interpreterRunning.set(true);
|
interpreterRunning.set(true);
|
||||||
executionThread.start();
|
executionThread.start();
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ public class PythonScript extends GhidraScript {
|
||||||
// Cleanup the interpreter, and remove it from the state (once it's cleaned it cannot be
|
// Cleanup the interpreter, and remove it from the state (once it's cleaned it cannot be
|
||||||
// reused)
|
// reused)
|
||||||
interpreter.cleanup();
|
interpreter.cleanup();
|
||||||
state.removeEnvironmentVar(PYTHON_INTERPRETER);
|
state.removeEnvironmentVar(JYTHON_INTERPRETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PrintWriter getStdOut() {
|
private PrintWriter getStdOut() {
|
||||||
|
@ -175,6 +175,6 @@ public class PythonScript extends GhidraScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCategory() {
|
public String getCategory() {
|
||||||
return "Python";
|
return "Jython";
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,31 +13,31 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.python.core.PyException;
|
import org.python.core.PyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread responsible for executing a python script from a file.
|
* Thread responsible for executing a jython script from a file.
|
||||||
*/
|
*/
|
||||||
class PythonScriptExecutionThread extends Thread {
|
class JythonScriptExecutionThread extends Thread {
|
||||||
|
|
||||||
private PythonScript script;
|
private JythonScript script;
|
||||||
private GhidraPythonInterpreter interpreter;
|
private GhidraJythonInterpreter interpreter;
|
||||||
private AtomicBoolean interpreterRunning;
|
private AtomicBoolean interpreterRunning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new python script execution thread that executes the given python script.
|
* Creates a new jython script execution thread that executes the given jython script.
|
||||||
*
|
*
|
||||||
* @param script The python script to execute.
|
* @param script The jython script to execute.
|
||||||
* @param interpreter The python interpreter to use for execution.
|
* @param interpreter The jython interpreter to use for execution.
|
||||||
* @param interpreterRunning Gets set to indicate whether or not the interpreter is still running the script.
|
* @param interpreterRunning Gets set to indicate whether or not the interpreter is still running the script.
|
||||||
*/
|
*/
|
||||||
PythonScriptExecutionThread(PythonScript script, GhidraPythonInterpreter interpreter,
|
JythonScriptExecutionThread(JythonScript script, GhidraJythonInterpreter interpreter,
|
||||||
AtomicBoolean interpreterRunning) {
|
AtomicBoolean interpreterRunning) {
|
||||||
super("Python script execution thread");
|
super("Jython script execution thread");
|
||||||
|
|
||||||
this.script = script;
|
this.script = script;
|
||||||
this.interpreter = interpreter;
|
this.interpreter = interpreter;
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -21,7 +21,7 @@ import java.util.regex.Pattern;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
|
|
||||||
public class PythonScriptProvider extends GhidraScriptProvider {
|
public class JythonScriptProvider extends GhidraScriptProvider {
|
||||||
|
|
||||||
private static final Pattern BLOCK_COMMENT = Pattern.compile("'''");
|
private static final Pattern BLOCK_COMMENT = Pattern.compile("'''");
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* In Python this is a triple single quote sequence, "'''".
|
* In Jython this is a triple single quote sequence, "'''".
|
||||||
*
|
*
|
||||||
* @return the Pattern for Python block comment openings
|
* @return the Pattern for Jython block comment openings
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Pattern getBlockCommentStart() {
|
public Pattern getBlockCommentStart() {
|
||||||
|
@ -52,9 +52,9 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* In Python this is a triple single quote sequence, "'''".
|
* In Jython this is a triple single quote sequence, "'''".
|
||||||
*
|
*
|
||||||
* @return the Pattern for Python block comment openings
|
* @return the Pattern for Jython block comment openings
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Pattern getBlockCommentEnd() {
|
public Pattern getBlockCommentEnd() {
|
||||||
|
@ -83,7 +83,7 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Python";
|
return "Jython";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,7 +96,7 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||||
throws GhidraScriptLoadException {
|
throws GhidraScriptLoadException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class<?> clazz = Class.forName(PythonScript.class.getName());
|
Class<?> clazz = Class.forName(JythonScript.class.getName());
|
||||||
GhidraScript script = (GhidraScript) clazz.getConstructor().newInstance();
|
GhidraScript script = (GhidraScript) clazz.getConstructor().newInstance();
|
||||||
script.setSourceFile(sourceFile);
|
script.setSourceFile(sourceFile);
|
||||||
return script;
|
return script;
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
@ -25,83 +25,83 @@ import utilities.util.FileUtilities;
|
||||||
/**
|
/**
|
||||||
* Python utility method class.
|
* Python utility method class.
|
||||||
*/
|
*/
|
||||||
public class PythonUtils {
|
public class JythonUtils {
|
||||||
|
|
||||||
public static final String PYTHON_NAME = "jython-2.7.3";
|
public static final String JYTHON_NAME = "jython-2.7.3";
|
||||||
public static final String PYTHON_CACHEDIR = "jython_cachedir";
|
public static final String JYTHON_CACHEDIR = "jython_cachedir";
|
||||||
public static final String PYTHON_SRC = "python-src";
|
public static final String JYTHON_SRC = "jython-src";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the python home directory. This is the directory that has the "Lib" directory in it.
|
* Sets up the jython home directory. This is the directory that has the "Lib" directory in it.
|
||||||
*
|
*
|
||||||
* @return The python home directory.
|
* @return The jython home directory.
|
||||||
* @throws IOException If there was a disk-related problem setting up the home directory.
|
* @throws IOException If there was a disk-related problem setting up the home directory.
|
||||||
*/
|
*/
|
||||||
public static File setupPythonHomeDir() throws IOException {
|
public static File setupJythonHomeDir() throws IOException {
|
||||||
|
|
||||||
File pythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
File jythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
||||||
File pythonHomeDir =
|
File jythonHomeDir =
|
||||||
Application.getModuleDataSubDirectory(pythonModuleDir.getName(), PYTHON_NAME).getFile(
|
Application.getModuleDataSubDirectory(jythonModuleDir.getName(), JYTHON_NAME)
|
||||||
false);
|
.getFile(false);
|
||||||
|
|
||||||
if (!pythonHomeDir.exists()) {
|
if (!jythonHomeDir.exists()) {
|
||||||
throw new IOException("Failed to find the python home directory at: " + pythonHomeDir);
|
throw new IOException("Failed to find the jython home directory at: " + jythonHomeDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.setProperty("python.home", pythonHomeDir.getAbsolutePath());
|
System.setProperty("jython.home", jythonHomeDir.getAbsolutePath());
|
||||||
|
|
||||||
return pythonHomeDir;
|
return jythonHomeDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the python cache directory. This is a temporary space that python source files
|
* Sets up the jython cache directory. This is a temporary space that jython source files
|
||||||
* get compiled to and cached. It should NOT be in the Ghidra installation directory, because
|
* get compiled to and cached. It should NOT be in the Ghidra installation directory, because
|
||||||
* some installations will not have the appropriate directory permissions to create new files in.
|
* some installations will not have the appropriate directory permissions to create new files in.
|
||||||
*
|
*
|
||||||
* @param monitor A monitor to use during the cache directory setup.
|
* @param monitor A monitor to use during the cache directory setup.
|
||||||
* @return The python cache directory.
|
* @return The jython cache directory.
|
||||||
* @throws IOException If there was a disk-related problem setting up the cache directory.
|
* @throws IOException If there was a disk-related problem setting up the cache directory.
|
||||||
* @throws CancelledException If the user cancelled the setup.
|
* @throws CancelledException If the user cancelled the setup.
|
||||||
*/
|
*/
|
||||||
public static File setupPythonCacheDir(TaskMonitor monitor)
|
public static File setupJythonCacheDir(TaskMonitor monitor)
|
||||||
throws CancelledException, IOException {
|
throws CancelledException, IOException {
|
||||||
|
|
||||||
File devDir = new File(Application.getUserSettingsDirectory(), "dev");
|
File devDir = new File(Application.getUserSettingsDirectory(), "dev");
|
||||||
File cacheDir = new File(devDir, PYTHON_CACHEDIR);
|
File cacheDir = new File(devDir, JYTHON_CACHEDIR);
|
||||||
if (!FileUtilities.mkdirs(cacheDir)) {
|
if (!FileUtilities.mkdirs(cacheDir)) {
|
||||||
throw new IOException("Failed to create the python cache directory at: " + cacheDir);
|
throw new IOException("Failed to create the jython cache directory at: " + cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
File pythonSrcDestDir = new File(cacheDir, PYTHON_SRC);
|
File jythonSrcDestDir = new File(cacheDir, JYTHON_SRC);
|
||||||
if (!FileUtilities.createDir(pythonSrcDestDir)) {
|
if (!FileUtilities.createDir(jythonSrcDestDir)) {
|
||||||
throw new IOException(
|
throw new IOException(
|
||||||
"Failed to create the " + PYTHON_SRC + " directory at: " + pythonSrcDestDir);
|
"Failed to create the " + JYTHON_SRC + " directory at: " + jythonSrcDestDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
File pythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
File jythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
||||||
File pythonSrcDir = new File(pythonModuleDir, PYTHON_SRC);
|
File jythonSrcDir = new File(jythonModuleDir, JYTHON_SRC);
|
||||||
if (!pythonSrcDir.exists()) {
|
if (!jythonSrcDir.exists()) {
|
||||||
try {
|
try {
|
||||||
pythonSrcDir = Application.getModuleDataSubDirectory(pythonModuleDir.getName(),
|
jythonSrcDir = Application.getModuleDataSubDirectory(jythonModuleDir.getName(),
|
||||||
PYTHON_SRC).getFile(false);
|
JYTHON_SRC).getFile(false);
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException e) {
|
catch (FileNotFoundException e) {
|
||||||
throw new IOException("Failed to find the module's " + PYTHON_SRC + " directory");
|
throw new IOException("Failed to find the module's " + JYTHON_SRC + " directory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileUtilities.copyDir(pythonSrcDir, pythonSrcDestDir, f -> f.getName().endsWith(".py"),
|
FileUtilities.copyDir(jythonSrcDir, jythonSrcDestDir, f -> f.getName().endsWith(".py"),
|
||||||
monitor);
|
monitor);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new IOException(
|
throw new IOException(
|
||||||
"Failed to copy " + PYTHON_SRC + " files to: " + pythonSrcDestDir);
|
"Failed to copy " + JYTHON_SRC + " files to: " + jythonSrcDestDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.setProperty("python.cachedir.skip", "false");
|
System.setProperty("python.cachedir.skip", "false");
|
||||||
System.setProperty("python.cachedir", cacheDir.getAbsolutePath());
|
System.setProperty("python.cachedir", cacheDir.getAbsolutePath());
|
||||||
System.setProperty("python.path", pythonSrcDestDir.getAbsolutePath());
|
System.setProperty("python.path", jythonSrcDestDir.getAbsolutePath());
|
||||||
|
|
||||||
return cacheDir;
|
return cacheDir;
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
/**
|
/**
|
||||||
* Tests for the Ghidra Python Interpreter's code completion functionality.
|
* Tests for the Ghidra Python Interpreter's code completion functionality.
|
||||||
*/
|
*/
|
||||||
public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTest {
|
public class JythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private String simpleTestProgram = """
|
private String simpleTestProgram = """
|
||||||
my_int = 32
|
my_int = 32
|
||||||
|
@ -68,13 +68,13 @@ public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTes
|
||||||
@Rule
|
@Rule
|
||||||
public TemporaryFolder tempScriptFolder = new TemporaryFolder();
|
public TemporaryFolder tempScriptFolder = new TemporaryFolder();
|
||||||
|
|
||||||
private GhidraPythonInterpreter interpreter;
|
private GhidraJythonInterpreter interpreter;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||||
interpreter = GhidraPythonInterpreter.get();
|
interpreter = GhidraJythonInterpreter.get();
|
||||||
executePythonProgram(simpleTestProgram);
|
executeJythonProgram(simpleTestProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -160,7 +160,7 @@ public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTes
|
||||||
return interpreter.getCommandCompletions(command, false, caretPos);
|
return interpreter.getCommandCompletions(command, false, caretPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executePythonProgram(String code) {
|
private void executeJythonProgram(String code) {
|
||||||
try {
|
try {
|
||||||
File tempFile = tempScriptFolder.newFile();
|
File tempFile = tempScriptFolder.newFile();
|
||||||
FileUtils.writeStringToFile(tempFile, code, Charset.defaultCharset());
|
FileUtils.writeStringToFile(tempFile, code, Charset.defaultCharset());
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -29,16 +29,16 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
/**
|
/**
|
||||||
* Tests the Ghidra python interpreter's functionality.
|
* Tests the Ghidra python interpreter's functionality.
|
||||||
*/
|
*/
|
||||||
public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
public class JythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private ByteArrayOutputStream out;
|
private ByteArrayOutputStream out;
|
||||||
private GhidraPythonInterpreter interpreter;
|
private GhidraJythonInterpreter interpreter;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
out = new ByteArrayOutputStream();
|
out = new ByteArrayOutputStream();
|
||||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||||
interpreter = GhidraPythonInterpreter.get();
|
interpreter = GhidraJythonInterpreter.get();
|
||||||
interpreter.setOut(out);
|
interpreter.setOut(out);
|
||||||
interpreter.setErr(out);
|
interpreter.setErr(out);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
* Tests that the interpreter's "push" method is working by executing a simple line of python.
|
* Tests that the interpreter's "push" method is working by executing a simple line of python.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonPush() {
|
public void testJythonPush() {
|
||||||
final String str = "hi";
|
final String str = "hi";
|
||||||
interpreter.push("print \"" + str + "\"", null);
|
interpreter.push("print \"" + str + "\"", null);
|
||||||
assertEquals(out.toString().trim(), str);
|
assertEquals(out.toString().trim(), str);
|
||||||
|
@ -64,7 +64,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
* Tests that the interpreter's "execFile" method is working by executing a simple file of python.
|
* Tests that the interpreter's "execFile" method is working by executing a simple file of python.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonExecFile() {
|
public void testJythonExecFile() {
|
||||||
interpreter.execFile(new ResourceFile("ghidra_scripts/python_basics.py"), null);
|
interpreter.execFile(new ResourceFile("ghidra_scripts/python_basics.py"), null);
|
||||||
assertTrue(out.toString().contains("Snoopy"));
|
assertTrue(out.toString().contains("Snoopy"));
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
* that we install from there.
|
* that we install from there.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonSiteCustomize() {
|
public void testJythonSiteCustomize() {
|
||||||
interpreter.push("help", null);
|
interpreter.push("help", null);
|
||||||
assertTrue(out.toString().contains("Press 'F1'"));
|
assertTrue(out.toString().contains("Press 'F1'"));
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
* Tests that cleaning the interpreter invalidates it.
|
* Tests that cleaning the interpreter invalidates it.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonCleanupInvalidation() {
|
public void testJythonCleanupInvalidation() {
|
||||||
interpreter.cleanup();
|
interpreter.cleanup();
|
||||||
|
|
||||||
try {
|
try {
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -28,19 +28,19 @@ import ghidra.test.TestEnv;
|
||||||
/**
|
/**
|
||||||
* Tests the Python Plugin functionality.
|
* Tests the Python Plugin functionality.
|
||||||
*/
|
*/
|
||||||
public class PythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
public class JythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
private PythonPlugin plugin;
|
private JythonPlugin plugin;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
env = new TestEnv();
|
env = new TestEnv();
|
||||||
tool = env.getTool();
|
tool = env.getTool();
|
||||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||||
tool.addPlugin(PythonPlugin.class.getName());
|
tool.addPlugin(JythonPlugin.class.getName());
|
||||||
plugin = env.getPlugin(PythonPlugin.class);
|
plugin = env.getPlugin(JythonPlugin.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -53,10 +53,10 @@ public class PythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
* Tests that issuing a reset from the plugin resets the interpreter.
|
* Tests that issuing a reset from the plugin resets the interpreter.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonPluginReset() {
|
public void testJythonPluginReset() {
|
||||||
GhidraPythonInterpreter origInterpreter = plugin.getInterpreter();
|
GhidraJythonInterpreter origInterpreter = plugin.getInterpreter();
|
||||||
plugin.reset();
|
plugin.reset();
|
||||||
GhidraPythonInterpreter newInterpreter = plugin.getInterpreter();
|
GhidraJythonInterpreter newInterpreter = plugin.getInterpreter();
|
||||||
assertNotSame(origInterpreter, newInterpreter);
|
assertNotSame(origInterpreter, newInterpreter);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import ghidra.app.script.GhidraScriptUtil;
|
||||||
import ghidra.app.script.ScriptInfo;
|
import ghidra.app.script.ScriptInfo;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
|
|
||||||
public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
public class JythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
@ -48,7 +48,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetailedPythonScript() {
|
public void testDetailedJythonScript() {
|
||||||
String descLine1 = "This script exists to check that the info on";
|
String descLine1 = "This script exists to check that the info on";
|
||||||
String descLine2 = "a script that has extensive documentation is";
|
String descLine2 = "a script that has extensive documentation is";
|
||||||
String descLine3 = "properly parsed and represented.";
|
String descLine3 = "properly parsed and represented.";
|
||||||
|
@ -99,7 +99,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPythonScriptWithBlockComment() {
|
public void testJythonScriptWithBlockComment() {
|
||||||
String description = "Script with a block comment at the top.";
|
String description = "Script with a block comment at the top.";
|
||||||
String category = "Test";
|
String category = "Test";
|
||||||
ResourceFile scriptFile = null;
|
ResourceFile scriptFile = null;
|
||||||
|
@ -129,7 +129,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPythonScriptWithBlockCommentAndCertifyHeader() {
|
public void testJythonScriptWithBlockCommentAndCertifyHeader() {
|
||||||
String description = "Script with a block comment at the top.";
|
String description = "Script with a block comment at the top.";
|
||||||
String category = "Test";
|
String category = "Test";
|
||||||
ResourceFile scriptFile = null;
|
ResourceFile scriptFile = null;
|
||||||
|
@ -168,7 +168,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPythonScriptWithoutBlockComment() {
|
public void testJythonScriptWithoutBlockComment() {
|
||||||
String description = "Script without a block comment at the top.";
|
String description = "Script without a block comment at the top.";
|
||||||
String category = "Test";
|
String category = "Test";
|
||||||
ResourceFile scriptFile = null;
|
ResourceFile scriptFile = null;
|
||||||
|
@ -194,7 +194,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPythonScriptWithSingleLineBlockComment() {
|
public void testJythonScriptWithSingleLineBlockComment() {
|
||||||
String description = "Script with a block comment at the top.";
|
String description = "Script with a block comment at the top.";
|
||||||
String category = "Test";
|
String category = "Test";
|
||||||
ResourceFile scriptFile = null;
|
ResourceFile scriptFile = null;
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.python;
|
package ghidra.jython;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
/**
|
/**
|
||||||
* Tests the Python script functionality.
|
* Tests the Python script functionality.
|
||||||
*/
|
*/
|
||||||
public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
public class JythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
|
@ -59,19 +59,19 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that Python scripts are running correctly.
|
* Tests that Jython scripts are running correctly.
|
||||||
*
|
*
|
||||||
* @throws Exception If an exception occurred while trying to run the script.
|
* @throws Exception If an exception occurred while trying to run the script.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonScript() throws Exception {
|
public void testJythonScript() throws Exception {
|
||||||
String script = "ghidra_scripts/python_basics.py";
|
String script = "ghidra_scripts/python_basics.py";
|
||||||
try {
|
try {
|
||||||
String output = runPythonScript(Application.getModuleFile("Python", script));
|
String output = runPythonScript(Application.getModuleFile("Jython", script));
|
||||||
assertTrue(output.contains("Snoopy"));
|
assertTrue(output.contains("Snoopy"));
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException e) {
|
catch (FileNotFoundException e) {
|
||||||
fail("Could not find python script: " + script);
|
fail("Could not find jython script: " + script);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
fail("Exception occurred trying to run script: " + e.getMessage());
|
fail("Exception occurred trying to run script: " + e.getMessage());
|
||||||
|
@ -79,18 +79,18 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that Python scripts are running correctly.
|
* Tests that Jython scripts are running correctly.
|
||||||
*
|
*
|
||||||
* @throws Exception If an exception occurred while trying to run the script.
|
* @throws Exception If an exception occurred while trying to run the script.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPythonInterpreterGoneFromState() throws Exception {
|
public void testJythonInterpreterGoneFromState() throws Exception {
|
||||||
String script = "ghidra_scripts/python_basics.py";
|
String script = "ghidra_scripts/python_basics.py";
|
||||||
try {
|
try {
|
||||||
GhidraState state =
|
GhidraState state =
|
||||||
new GhidraState(env.getTool(), env.getProject(), null, null, null, null);
|
new GhidraState(env.getTool(), env.getProject(), null, null, null, null);
|
||||||
runPythonScript(Application.getModuleFile("Python", script), state);
|
runPythonScript(Application.getModuleFile("Jython", script), state);
|
||||||
assertTrue(state.getEnvironmentVar(PythonScript.PYTHON_INTERPRETER) == null);
|
assertTrue(state.getEnvironmentVar(JythonScript.JYTHON_INTERPRETER) == null);
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException e) {
|
catch (FileNotFoundException e) {
|
||||||
fail("Could not find python script: " + script);
|
fail("Could not find python script: " + script);
|
||||||
|
@ -125,9 +125,9 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
runSwing(() -> console.clearMessages());
|
runSwing(() -> console.clearMessages());
|
||||||
|
|
||||||
PythonScriptProvider scriptProvider = new PythonScriptProvider();
|
JythonScriptProvider scriptProvider = new JythonScriptProvider();
|
||||||
PrintWriter writer = new PrintWriter(new ByteArrayOutputStream());
|
PrintWriter writer = new PrintWriter(new ByteArrayOutputStream());
|
||||||
PythonScript script = (PythonScript) scriptProvider.getScriptInstance(scriptFile, writer);
|
JythonScript script = (JythonScript) scriptProvider.getScriptInstance(scriptFile, writer);
|
||||||
script.set(state, TaskMonitor.DUMMY, writer);
|
script.set(state, TaskMonitor.DUMMY, writer);
|
||||||
script.run();
|
script.run();
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
|
|
||||||
[Defaults]
|
|
||||||
|
|
||||||
color.fg.plugin.python.syntax.class = color.palette.blue
|
|
||||||
color.fg.plugin.python.syntax.code = color.palette.darkgreen
|
|
||||||
color.fg.plugin.python.syntax.function = color.palette.green
|
|
||||||
color.fg.plugin.python.syntax.instance = color.palette.purple
|
|
||||||
color.fg.plugin.python.syntax.map = color.palette.steelblue
|
|
||||||
color.fg.plugin.python.syntax.method = color.palette.teal
|
|
||||||
color.fg.plugin.python.syntax.null = color.palette.red
|
|
||||||
color.fg.plugin.python.syntax.number = color.palette.darkgray
|
|
||||||
color.fg.plugin.python.syntax.package = color.palette.darkred
|
|
||||||
color.fg.plugin.python.syntax.sequence = color.palette.saddlebrown
|
|
||||||
color.fg.plugin.python.syntax.special = color.palette.darkgreen
|
|
||||||
|
|
||||||
icon.plugin.python = python.png
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Dark Defaults]
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
#----------------------------------------
|
#----------------------------------------
|
||||||
# Ghidra Python launch
|
# Ghidra Jython launch
|
||||||
#----------------------------------------
|
#----------------------------------------
|
||||||
|
|
||||||
# Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of
|
# Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of
|
||||||
|
@ -31,6 +31,6 @@ VMARG_LIST+="-Djava.awt.headless=true "
|
||||||
SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")"
|
SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")"
|
||||||
SCRIPT_DIR="${SCRIPT_FILE%/*}"
|
SCRIPT_DIR="${SCRIPT_FILE%/*}"
|
||||||
|
|
||||||
# Launch Ghidra Python
|
# Launch Ghidra Jython
|
||||||
# DEBUG_ADDRESS set via environment for launch.sh
|
# DEBUG_ADDRESS set via environment for launch.sh
|
||||||
DEBUG_ADDRESS=${DEBUG_ADDRESS} "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" jdk "Ghidra-Python" "${MAXMEM}" "${VMARG_LIST}" ghidra.python.PythonRun "$@"
|
DEBUG_ADDRESS=${DEBUG_ADDRESS} "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" jdk "Ghidra-Jython" "${MAXMEM}" "${VMARG_LIST}" ghidra.jython.JythonRun "$@"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
:: Ghidra python launch
|
:: Ghidra jython launch
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal
|
||||||
|
@ -24,4 +24,4 @@ set DEBUG_ADDRESS=127.0.0.1:13002
|
||||||
set VMARG_LIST=-XX:ParallelGCThreads=2
|
set VMARG_LIST=-XX:ParallelGCThreads=2
|
||||||
set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2
|
set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2
|
||||||
|
|
||||||
call "%~dp0launch.bat" %LAUNCH_MODE% jdk Ghidra-Python "%MAXMEM%" "%VMARG_LIST%" ghidra.python.PythonRun %*
|
call "%~dp0launch.bat" %LAUNCH_MODE% jdk Ghidra-Jython "%MAXMEM%" "%VMARG_LIST%" ghidra.jython.JythonRun %*
|
||||||
|
|
|
@ -36,7 +36,7 @@ import ghidra.app.plugin.core.osgi.BundleStatusComponentProvider;
|
||||||
import ghidra.app.plugin.core.script.*;
|
import ghidra.app.plugin.core.script.*;
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
import ghidra.app.services.ConsoleService;
|
import ghidra.app.services.ConsoleService;
|
||||||
import ghidra.python.PythonScriptProvider;
|
import ghidra.jython.JythonScriptProvider;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator {
|
public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator {
|
||||||
|
@ -223,7 +223,7 @@ public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator
|
||||||
List<GhidraScriptProvider> items = new ArrayList<>();
|
List<GhidraScriptProvider> items = new ArrayList<>();
|
||||||
JavaScriptProvider javaScriptProvider = new JavaScriptProvider();
|
JavaScriptProvider javaScriptProvider = new JavaScriptProvider();
|
||||||
items.add(javaScriptProvider);
|
items.add(javaScriptProvider);
|
||||||
items.add(new PythonScriptProvider());
|
items.add(new JythonScriptProvider());
|
||||||
final PickProviderDialog pickDialog = new PickProviderDialog(items, javaScriptProvider);
|
final PickProviderDialog pickDialog = new PickProviderDialog(items, javaScriptProvider);
|
||||||
runSwing(() -> tool.showDialog(pickDialog), false);
|
runSwing(() -> tool.showDialog(pickDialog), false);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue