Renaming Pyhidra to PyGhidra

This commit is contained in:
Ryan Kurtz 2024-09-05 10:35:28 -04:00 committed by DC3-TSD
parent 92d0f1dacf
commit 5b81139197
78 changed files with 370 additions and 629 deletions

View File

@ -65,7 +65,7 @@ public class VSCodeProjectScript extends GhidraScript {
writeSettings(installDir, projectDir, classpathSourceMap); writeSettings(installDir, projectDir, classpathSourceMap);
writeLaunch(installDir, projectDir, classpathSourceMap); writeLaunch(installDir, projectDir, classpathSourceMap);
writeSampleScriptJava(projectDir); writeSampleScriptJava(projectDir);
writeSampleScriptPyhidra(projectDir); writeSampleScriptPyGhidra(projectDir);
writeSampleModule(installDir, projectDir); writeSampleModule(installDir, projectDir);
println("Successfully created VSCode project directory at: " + projectDir); println("Successfully created VSCode project directory at: " + projectDir);
@ -228,13 +228,13 @@ public class VSCodeProjectScript extends GhidraScript {
FileUtils.writeStringToFile(scriptFile, sampleScript, StandardCharsets.UTF_8); FileUtils.writeStringToFile(scriptFile, sampleScript, StandardCharsets.UTF_8);
} }
private void writeSampleScriptPyhidra(File projectDir) throws IOException { private void writeSampleScriptPyGhidra(File projectDir) throws IOException {
File scriptsDir = new File(projectDir, "ghidra_scripts"); File scriptsDir = new File(projectDir, "ghidra_scripts");
File scriptFile = new File(scriptsDir, "sample_script.py"); File scriptFile = new File(scriptsDir, "sample_script.py");
String sampleScript = """ String sampleScript = """
# Sample Pyhidra GhidraScript # Sample PyGhidra GhidraScript
# @category Examples # @category Examples
# @runtime Pyhidra # @runtime PyGhidra
from java.util import LinkedList from java.util import LinkedList
java_list = LinkedList([1,2,3]) java_list = LinkedList([1,2,3])

View File

@ -2,7 +2,7 @@
<launchConfiguration type="org.eclipse.jdt.launching.remoteJavaApplication"> <launchConfiguration type="org.eclipse.jdt.launching.remoteJavaApplication">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/> <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Features Pyhidra"/> <listEntry value="/Features PyGhidra"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/> <listEntry value="4"/>
@ -12,6 +12,6 @@
<mapEntry key="hostname" value="localhost"/> <mapEntry key="hostname" value="localhost"/>
<mapEntry key="port" value="18001"/> <mapEntry key="port" value="18001"/>
</mapAttribute> </mapAttribute>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Features Pyhidra"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Features PyGhidra"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_CONNECTOR_ID" value="org.eclipse.jdt.launching.socketAttachConnector"/> <stringAttribute key="org.eclipse.jdt.launching.VM_CONNECTOR_ID" value="org.eclipse.jdt.launching.socketAttachConnector"/>
</launchConfiguration> </launchConfiguration>

View File

@ -5,7 +5,7 @@
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/>
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/>
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/> <stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/>
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_Pyhidra GUI Debug"/> <stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_PyGhidra GUI Debug"/>
<stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/> <stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/>
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/>
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/>

View File

@ -2,7 +2,7 @@
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType"> <launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/> <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/> <listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="2"/> <listEntry value="2"/>
@ -14,11 +14,11 @@
<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute> </listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v&#13;&#10;-g"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v&#13;&#10;-g"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/> <stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/> <stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/> <stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
</launchConfiguration> </launchConfiguration>

View File

@ -5,7 +5,7 @@
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/>
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/>
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/> <stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/>
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_Pyhidra Interpreter Debug"/> <stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_PyGhidra Interpreter Debug"/>
<stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/> <stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/>
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/>
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/> <booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/>

View File

@ -2,7 +2,7 @@
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType"> <launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/> <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/> <listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="2"/> <listEntry value="2"/>
@ -14,11 +14,11 @@
<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute> </listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/> <stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/> <stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/> <stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
</launchConfiguration> </launchConfiguration>

View File

@ -2,7 +2,7 @@
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType"> <launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/> <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/> <listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="2"/> <listEntry value="2"/>
@ -10,13 +10,13 @@
<mapAttribute key="org.eclipse.debug.core.environmentVariables"> <mapAttribute key="org.eclipse.debug.core.environmentVariables">
<mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/> <mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/>
<mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/> <mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/>
<mapEntry key="PYHIDRA_DEBUG" value="1"/> <mapEntry key="PYGHIDRA_DEBUG" value="1"/>
</mapAttribute> </mapAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v&#13;&#10;-g"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v&#13;&#10;-g"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/> <stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/> <stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/> <stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
</launchConfiguration> </launchConfiguration>

View File

@ -2,7 +2,7 @@
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType"> <launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/> <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/> <listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="2"/> <listEntry value="2"/>
@ -10,13 +10,13 @@
<mapAttribute key="org.eclipse.debug.core.environmentVariables"> <mapAttribute key="org.eclipse.debug.core.environmentVariables">
<mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/> <mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/>
<mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/> <mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/>
<mapEntry key="PYHIDRA_DEBUG" value="1"/> <mapEntry key="PYGHIDRA_DEBUG" value="1"/>
</mapAttribute> </mapAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/> <stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/> <stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/> <stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
</launchConfiguration> </launchConfiguration>

View File

@ -22,7 +22,7 @@ apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle" apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle"
apply plugin: 'eclipse' apply plugin: 'eclipse'
eclipse.project.name = 'Features Pyhidra' eclipse.project.name = 'Features PyGhidra'
dependencies { dependencies {
@ -53,28 +53,28 @@ distributePyDep("setuptools-68.0.0-py3-none-any.whl")
task installJPype(type: Exec) { task installJPype(type: Exec) {
dependsOn(":createPythonVirtualEnvironment") dependsOn(":createPythonVirtualEnvironment")
File depsDir = file("${DEPS_DIR}/Pyhidra") File depsDir = file("${DEPS_DIR}/PyGhidra")
File binRepoDir = file("${BIN_REPO}/Ghidra/Features/Pyhidra") File binRepoDir = file("${BIN_REPO}/Ghidra/Features/PyGhidra")
def dir = depsDir.exists() ? depsDir : binRepoDir def dir = depsDir.exists() ? depsDir : binRepoDir
commandLine "$PYTHON3_VENV", "-m", "pip", "install", "--no-index", "-f", "$dir", "JPype1" commandLine "$PYTHON3_VENV", "-m", "pip", "install", "--no-index", "-f", "$dir", "JPype1"
} }
// Install Pyhidra in editable mode to the development virtual environment // Install PyGhidra in editable mode to the development virtual environment
task installEditablePyhidra(type: Exec) { task installEditablePyGhidra(type: Exec) {
dependsOn("installJPype") dependsOn("installJPype")
commandLine "$PYTHON3_VENV", "-m", "pip", "install", "-e", "src/main/py" commandLine "$PYTHON3_VENV", "-m", "pip", "install", "-e", "src/main/py"
} }
rootProject.prepDev.dependsOn installEditablePyhidra rootProject.prepDev.dependsOn installEditablePyGhidra
// Add pyhidraLauncher.py to the release // Add pyghidra_launcher.py to the release
rootProject.assembleDistribution { rootProject.assembleDistribution {
dependsOn(buildPyPackage) dependsOn(buildPyPackage)
def p = this.project def p = this.project
def zipPath = getZipPath(p) def zipPath = getZipPath(p)
from (this.project.projectDir.toString()) { from (this.project.projectDir.toString()) {
include "pyhidraLauncher.py" include "pyghidra_launcher.py"
into { zipPath } into { zipPath }
} }
} }

View File

@ -3,5 +3,5 @@
Module.manifest||GHIDRA||||END| Module.manifest||GHIDRA||||END|
data/python.theme.properties||GHIDRA||||END| data/python.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/Pyhidra/interpreter.html||GHIDRA||||END| src/main/help/help/topics/PyGhidra/interpreter.html||GHIDRA||||END|
src/main/resources/images/python.png||GHIDRA||||END| src/main/resources/images/python.png||GHIDRA||||END|

View File

@ -1,6 +1,6 @@
# Examples of Pyhidra-specific functionality # Examples of PyGhidra-specific functionality
# @category: Examples.Python # @category: Examples.Python
# @runtime Pyhidra # @runtime PyGhidra
# we can import java libraries just as if they were python libraries # we can import java libraries just as if they were python libraries

View File

@ -6,16 +6,16 @@ from pathlib import Path
from typing import List from typing import List
from sys import stderr from sys import stderr
def upgrade(pip_args: List[str], dist_dir: Path, current_pyhidra_version: str) -> bool: def upgrade(pip_args: List[str], dist_dir: Path, current_pyghidra_version: str) -> bool:
from packaging.version import Version # if pyhidra imported, we know we have packaging from packaging.version import Version # if pyghidra imported, we know we have packaging
included_pyhidra: Path = next(dist_dir.glob('pyhidra-*.whl'), None) included_pyghidra: Path = next(dist_dir.glob('pyghidra-*.whl'), None)
if included_pyhidra is None: if included_pyghidra is None:
print('Warning: included pyhidra wheel was not found', file=sys.stderr) print('Warning: included pyghidra wheel was not found', file=sys.stderr)
return return
included_version: Version = Version(included_pyhidra.name.split('-')[1]) included_version: Version = Version(included_pyghidra.name.split('-')[1])
current_version: Version = Version(current_pyhidra_version) current_version: Version = Version(current_pyghidra_version)
if included_version > current_version: if included_version > current_version:
choice: str = input(f'Do you wish to upgrade Pyhidra {current_version} to {included_version} (y/n)? ') choice: str = input(f'Do you wish to upgrade PyGhidra {current_version} to {included_version} (y/n)? ')
if choice.lower() in ('y', 'yes'): if choice.lower() in ('y', 'yes'):
pip_args.append('-U') pip_args.append('-U')
subprocess.check_call(pip_args) subprocess.check_call(pip_args)
@ -25,7 +25,7 @@ def upgrade(pip_args: List[str], dist_dir: Path, current_pyhidra_version: str) -
return False return False
def install(pip_args: List[str], dist_dir: Path) -> bool: def install(pip_args: List[str], dist_dir: Path) -> bool:
choice: str = input('Do you wish to install Pyhidra (y/n)? ') choice: str = input('Do you wish to install PyGhidra (y/n)? ')
if choice.lower() in ('y', 'yes'): if choice.lower() in ('y', 'yes'):
subprocess.check_call(pip_args) subprocess.check_call(pip_args)
return True return True
@ -48,16 +48,16 @@ def main() -> None:
python_cmd: str = sys.executable python_cmd: str = sys.executable
install_dir: Path = Path(args.install_dir) install_dir: Path = Path(args.install_dir)
venv_dir: Path = install_dir / 'build' / 'venv' venv_dir: Path = install_dir / 'build' / 'venv'
pyhidra_dir: Path = install_dir / 'Ghidra' / 'Features' / 'Pyhidra' pyghidra_dir: Path = install_dir / 'Ghidra' / 'Features' / 'PyGhidra'
src_dir: Path = pyhidra_dir / 'src' / 'main' / 'py' src_dir: Path = pyghidra_dir / 'src' / 'main' / 'py'
dist_dir: Path = pyhidra_dir / 'pypkg' / 'dist' dist_dir: Path = pyghidra_dir / 'pypkg' / 'dist'
# If headless, force console mode # If headless, force console mode
if args.headless: if args.headless:
args.console = True args.console = True
if args.dev: if args.dev:
# If in dev mode, launch pyhidra from the source tree using the development virtual environment # If in dev mode, launch PyGhidra from the source tree using the development virtual environment
if not venv_dir.is_dir(): if not venv_dir.is_dir():
print('Virtual environment not found!') print('Virtual environment not found!')
print('Run "gradle prepdev" and try again.') print('Run "gradle prepdev" and try again.')
@ -66,17 +66,17 @@ def main() -> None:
linux_python_cmd = str(venv_dir / 'bin' / 'python3') linux_python_cmd = str(venv_dir / 'bin' / 'python3')
python_cmd = win_python_cmd if os.name == 'nt' else linux_python_cmd python_cmd = win_python_cmd if os.name == 'nt' else linux_python_cmd
else: else:
# If in release mode, offer to install or upgrade pyhidra before launching from user-controlled environment # If in release mode, offer to install or upgrade PyGhidra before launching from user-controlled environment
pip_args: List[str] = [python_cmd, '-m', 'pip', 'install', '--no-index', '-f', str(dist_dir), 'pyhidra'] pip_args: List[str] = [python_cmd, '-m', 'pip', 'install', '--no-index', '-f', str(dist_dir), 'pyghidra']
try: try:
import pyhidra import pyghidra
upgrade(pip_args, dist_dir, pyhidra.__version__) upgrade(pip_args, dist_dir, pyghidra.__version__)
except ImportError: except ImportError:
if not install(pip_args, dist_dir): if not install(pip_args, dist_dir):
return return
# Launch Pyhidra # Launch PyGhidra
py_args: List[str] = [python_cmd, '-m', 'pyhidra.ghidra_launch', '--install-dir', str(install_dir)] py_args: List[str] = [python_cmd, '-m', 'pyghidra.ghidra_launch', '--install-dir', str(install_dir)]
if args.headless: if args.headless:
py_args += ['ghidra.app.util.headless.AnalyzeHeadless'] py_args += ['ghidra.app.util.headless.AnalyzeHeadless']
else: else:
@ -86,6 +86,6 @@ def main() -> None:
else: else:
creation_flags = getattr(subprocess, 'CREATE_NO_WINDOW', 0) creation_flags = getattr(subprocess, 'CREATE_NO_WINDOW', 0)
subprocess.Popen(py_args + remaining, creationflags=creation_flags, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) subprocess.Popen(py_args + remaining, creationflags=creation_flags, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -3,7 +3,7 @@
<tocroot> <tocroot>
<tocref id="Ghidra Functionality"> <tocref id="Ghidra Functionality">
<tocref id="Scripting"> <tocref id="Scripting">
<tocdef id="Pyhidra Interpreter" sortgroup="z" text="Pyhidra Interpreter" target="help/topics/Pyhidra/interpreter.html" /> <tocdef id="PyGhidra Interpreter" sortgroup="z" text="PyGhidra Interpreter" target="help/topics/PyGhidra/interpreter.html" />
</tocref> </tocref>
</tocref> </tocref>
</tocroot> </tocroot>

View File

@ -2,15 +2,15 @@
<HTML> <HTML>
<HEAD> <HEAD>
<TITLE>Pyhidra Interpreter</TITLE> <TITLE>PyGhidra 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="Pyhidra"></A>Pyhidra Interpreter</H1> <H1><A name="PyGhidra"></A>PyGhidra Interpreter</H1>
<P> <P>
The Ghidra <I>Pyhidra Interpreter</I> provides a full general-purpose Python interactive shell The Ghidra <I>PyGhidra Interpreter</I> provides a full general-purpose Python 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 Jpype. API through the magic of Jpype.
</P> </P>
@ -18,7 +18,7 @@
<H2>Environment</H2> <H2>Environment</H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<P> <P>
The Ghidra <I>Pyhidra Interpreter</I> is configured to run in a similar context as a Ghidra The Ghidra <I>PyGhidra 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 Jpype allows you to interact with These variables exist as Java objects behind the scenes, but Jpype allows you to interact with
@ -78,7 +78,7 @@
<H2>Keybindings</H2> <H2>Keybindings</H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<P> <P>
The Ghidra <I>Pyhidra Interpreter</I> supports the following hard-coded keybindings: The Ghidra <I>PyGhidra Interpreter</I> supports the following hard-coded keybindings:
<UL> <UL>
<LI><B>(up):</B>&nbsp;&nbsp;Move backward in command stack</LI> <LI><B>(up):</B>&nbsp;&nbsp;Move backward in command stack</LI>
<LI><B>(down):</B>&nbsp;&nbsp;Move forward in command stack</LI> <LI><B>(down):</B>&nbsp;&nbsp;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>Pyhidra Interpreter</I> should work as expected for Copy and paste from within the Ghidra <I>PyGhidra Interpreter</I> should work as expected for
your given environment: your given environment:
<UL> <UL>
<LI><B>Windows:</B>&nbsp;&nbsp;CTRL+C / CTRL+V</LI> <LI><B>Windows:</B>&nbsp;&nbsp;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>Pyhidra Interpreter</I> The built-in <TT>help()</TT> Python function has been altered by the Ghidra <I>PyGhidra 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>
@ -156,7 +156,7 @@
</P> </P>
</BLOCKQUOTE> </BLOCKQUOTE>
<P align="left" class="providedbyplugin">Provided by: <I>PyhidraPlugin</I></P> <P align="left" class="providedbyplugin">Provided by: <I>PyGhidraPlugin</I></P>
<P>&nbsp;</P> <P>&nbsp;</P>
<BR> <BR>

View File

@ -1,11 +1,11 @@
package ghidra.pyhidra; package ghidra.pyghidra;
import java.util.function.Consumer; import java.util.function.Consumer;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.ProgramPlugin; import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.plugin.core.interpreter.*; import ghidra.app.plugin.core.interpreter.InterpreterPanelService;
import ghidra.app.script.GhidraState; import ghidra.app.script.GhidraState;
import ghidra.framework.plugintool.PluginInfo; import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
@ -13,8 +13,8 @@ import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
import ghidra.pyhidra.interpreter.InterpreterGhidraScript; import ghidra.pyghidra.interpreter.InterpreterGhidraScript;
import ghidra.pyhidra.interpreter.PyhidraInterpreter; import ghidra.pyghidra.interpreter.PyGhidraInterpreter;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
/** /**
@ -25,20 +25,20 @@ import ghidra.util.exception.AssertException;
status = PluginStatus.RELEASED, status = PluginStatus.RELEASED,
packageName = CorePluginPackage.NAME, packageName = CorePluginPackage.NAME,
category = PluginCategoryNames.COMMON, category = PluginCategoryNames.COMMON,
shortDescription = "Pyhidra Interpreter", shortDescription = "PyGhidra Interpreter",
description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.", description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.",
servicesRequired = { InterpreterPanelService.class } servicesRequired = { InterpreterPanelService.class }
) )
//@formatter:on //@formatter:on
public class PyhidraPlugin extends ProgramPlugin { public class PyGhidraPlugin extends ProgramPlugin {
public static final String TITLE = "Pyhidra"; public static final String TITLE = "PyGhidra";
private static Consumer<PyhidraPlugin> initializer = null; private static Consumer<PyGhidraPlugin> initializer = null;
public final InterpreterGhidraScript script = new InterpreterGhidraScript(); public final InterpreterGhidraScript script = new InterpreterGhidraScript();
public PyhidraInterpreter interpreter; public PyGhidraInterpreter interpreter;
public PyhidraPlugin(PluginTool tool) { public PyGhidraPlugin(PluginTool tool) {
super(tool); super(tool);
GhidraState state = new GhidraState(tool, tool.getProject(), null, null, null, null); GhidraState state = new GhidraState(tool, tool.getProject(), null, null, null, null);
// use the copy constructor so this state doesn't fire plugin events // use the copy constructor so this state doesn't fire plugin events
@ -54,16 +54,16 @@ public class PyhidraPlugin extends ProgramPlugin {
* @param initializer the Python side initializer * @param initializer the Python side initializer
* @throws AssertException if the code completer has already been set * @throws AssertException if the code completer has already been set
*/ */
public static void setInitializer(Consumer<PyhidraPlugin> initializer) { public static void setInitializer(Consumer<PyGhidraPlugin> initializer) {
if (PyhidraPlugin.initializer != null) { if (PyGhidraPlugin.initializer != null) {
throw new AssertException("PyhidraPlugin initializer has already been set"); throw new AssertException("PyGhidraPlugin initializer has already been set");
} }
PyhidraPlugin.initializer = initializer; PyGhidraPlugin.initializer = initializer;
} }
@Override @Override
public void init() { public void init() {
interpreter = new PyhidraInterpreter(this, PyhidraPlugin.initializer != null); interpreter = new PyGhidraInterpreter(this, PyGhidraPlugin.initializer != null);
if (initializer != null) { if (initializer != null) {
initializer.accept(this); initializer.accept(this);
} }

View File

@ -1,6 +1,6 @@
package ghidra.pyhidra; package ghidra.pyghidra;
import java.io.*; import java.io.PrintWriter;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -12,15 +12,15 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
import ghidra.pyhidra.PythonFieldExposer.ExposedFields; import ghidra.pyghidra.PythonFieldExposer.ExposedFields;
import ghidra.util.exception.AssertException;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.exception.AssertException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/** /**
* {@link GhidraScript} provider for native python3 scripts * {@link GhidraScript} provider for native python3 scripts
*/ */
public final class PyhidraScriptProvider extends AbstractPythonScriptProvider { public final class PyGhidraScriptProvider extends AbstractPythonScriptProvider {
private static Consumer<GhidraScript> scriptRunner = null; private static Consumer<GhidraScript> scriptRunner = null;
@ -34,37 +34,37 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
* @throws AssertException if the script runner has already been set * @throws AssertException if the script runner has already been set
*/ */
public static void setScriptRunner(Consumer<GhidraScript> scriptRunner) { public static void setScriptRunner(Consumer<GhidraScript> scriptRunner) {
if (PyhidraScriptProvider.scriptRunner != null) { if (PyGhidraScriptProvider.scriptRunner != null) {
throw new AssertException("scriptRunner has already been set"); throw new AssertException("scriptRunner has already been set");
} }
PyhidraScriptProvider.scriptRunner = scriptRunner; PyGhidraScriptProvider.scriptRunner = scriptRunner;
} }
@Override @Override
public String getDescription() { public String getDescription() {
return PyhidraPlugin.TITLE; return PyGhidraPlugin.TITLE;
} }
@Override @Override
public String getRuntimeEnvironmentName() { public String getRuntimeEnvironmentName() {
return PyhidraPlugin.TITLE; return PyGhidraPlugin.TITLE;
} }
@Override @Override
public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter writer) public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter writer)
throws GhidraScriptLoadException { throws GhidraScriptLoadException {
if (scriptRunner == null) { if (scriptRunner == null) {
String msg = "Ghidra was not started with pyhidra. Python is not available"; String msg = "Ghidra was not started with PyGhidra. Python is not available";
throw new GhidraScriptLoadException(msg); throw new GhidraScriptLoadException(msg);
} }
GhidraScript script = SystemUtilities.isInHeadlessMode() ? new PyhidraHeadlessScript() GhidraScript script = SystemUtilities.isInHeadlessMode() ? new PyGhidraHeadlessScript()
: new PyhidraGhidraScript(); : new PyGhidraGhidraScript();
script.setSourceFile(sourceFile); script.setSourceFile(sourceFile);
return script; return script;
} }
@ExposedFields( @ExposedFields(
exposer = PyhidraGhidraScript.ExposedField.class, exposer = PyGhidraGhidraScript.ExposedField.class,
names = { names = {
"currentAddress", "currentLocation", "currentSelection", "currentAddress", "currentLocation", "currentSelection",
"currentHighlight", "currentProgram", "monitor", "currentHighlight", "currentProgram", "monitor",
@ -78,7 +78,7 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
ResourceFile.class, GhidraState.class, PrintWriter.class ResourceFile.class, GhidraState.class, PrintWriter.class
} }
) )
final static class PyhidraGhidraScript extends GhidraScript final static class PyGhidraGhidraScript extends GhidraScript
implements PythonFieldExposer { implements PythonFieldExposer {
@Override @Override
@ -92,13 +92,13 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
*/ */
private static class ExposedField extends PythonFieldExposer.ExposedField { private static class ExposedField extends PythonFieldExposer.ExposedField {
public ExposedField(String name, Class<?> type) { public ExposedField(String name, Class<?> type) {
super(MethodHandles.lookup().in(PyhidraGhidraScript.class), name, type); super(MethodHandles.lookup().in(PyGhidraGhidraScript.class), name, type);
} }
} }
} }
@ExposedFields( @ExposedFields(
exposer = PyhidraHeadlessScript.ExposedField.class, exposer = PyGhidraHeadlessScript.ExposedField.class,
names = { names = {
"currentAddress", "currentLocation", "currentSelection", "currentAddress", "currentLocation", "currentSelection",
"currentHighlight", "currentProgram", "monitor", "currentHighlight", "currentProgram", "monitor",
@ -112,7 +112,7 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
ResourceFile.class, GhidraState.class, PrintWriter.class ResourceFile.class, GhidraState.class, PrintWriter.class
} }
) )
final static class PyhidraHeadlessScript extends HeadlessScript final static class PyGhidraHeadlessScript extends HeadlessScript
implements PythonFieldExposer { implements PythonFieldExposer {
@Override @Override
@ -126,7 +126,7 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
*/ */
private static class ExposedField extends PythonFieldExposer.ExposedField { private static class ExposedField extends PythonFieldExposer.ExposedField {
public ExposedField(String name, Class<?> type) { public ExposedField(String name, Class<?> type) {
super(MethodHandles.lookup().in(PyhidraHeadlessScript.class), name, type); super(MethodHandles.lookup().in(PyGhidraHeadlessScript.class), name, type);
} }
} }
} }

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra; package ghidra.pyghidra;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -21,8 +21,8 @@ import ghidra.util.exception.AssertException;
* This interface is for <b>internal use only</b> and is only public so it can be * This interface is for <b>internal use only</b> and is only public so it can be
* visible to Python to apply the Jpype class customizations. * visible to Python to apply the Jpype class customizations.
*/ */
public sealed interface PythonFieldExposer permits PyhidraScriptProvider.PyhidraGhidraScript, public sealed interface PythonFieldExposer permits PyGhidraScriptProvider.PyGhidraGhidraScript,
PyhidraScriptProvider.PyhidraHeadlessScript { PyGhidraScriptProvider.PyGhidraHeadlessScript {
/** /**
* Gets a mapping of all the explicitly exposed fields of a class. * Gets a mapping of all the explicitly exposed fields of a class.

View File

@ -1,13 +1,13 @@
package ghidra.pyhidra.interpreter; package ghidra.pyghidra.interpreter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import ghidra.pyhidra.PyhidraPlugin;
import docking.ActionContext; import docking.ActionContext;
import docking.action.KeyBindingData; import docking.action.KeyBindingData;
import docking.action.DockingAction; import docking.action.DockingAction;
import docking.action.ToolBarData; import docking.action.ToolBarData;
import ghidra.pyghidra.PyGhidraPlugin;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import resources.ResourceManager; import resources.ResourceManager;
@ -15,10 +15,10 @@ import static docking.DockingUtils.CONTROL_KEY_MODIFIER_MASK;
final class CancelAction extends DockingAction { final class CancelAction extends DockingAction {
private final PyhidraConsole console; private final PyGhidraConsole console;
CancelAction(PyhidraConsole console) { CancelAction(PyGhidraConsole console) {
super("Cancel", PyhidraPlugin.class.getSimpleName()); super("Cancel", PyGhidraPlugin.class.getSimpleName());
this.console = console; this.console = console;
setDescription("Interrupt the interpreter"); setDescription("Interrupt the interpreter");
ImageIcon image = ResourceManager.loadImage("images/dialog-cancel.png"); ImageIcon image = ResourceManager.loadImage("images/dialog-cancel.png");
@ -26,7 +26,7 @@ final class CancelAction extends DockingAction {
setEnabled(true); setEnabled(true);
KeyBindingData key = new KeyBindingData(KeyEvent.VK_I, CONTROL_KEY_MODIFIER_MASK); KeyBindingData key = new KeyBindingData(KeyEvent.VK_I, CONTROL_KEY_MODIFIER_MASK);
setKeyBindingData(key); setKeyBindingData(key);
setHelpLocation(new HelpLocation(PyhidraPlugin.TITLE, "Interrupt_Interpreter")); setHelpLocation(new HelpLocation(PyGhidraPlugin.TITLE, "Interrupt_Interpreter"));
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.interpreter; package ghidra.pyghidra.interpreter;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -10,11 +10,11 @@ import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
/** /**
* Custom {@link GhidraScript} only for use with the pyhidra interpreter console * Custom {@link GhidraScript} only for use with the PyGhidra interpreter console
*/ */
public final class InterpreterGhidraScript extends GhidraScript { public final class InterpreterGhidraScript extends GhidraScript {
// public default constructor for use by PyhidraPlugin // public default constructor for use by PyGhidraPlugin
// the default constructor for FlatProgramAPI has protected visibility // the default constructor for FlatProgramAPI has protected visibility
public InterpreterGhidraScript() { public InterpreterGhidraScript() {
} }

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.interpreter; package ghidra.pyghidra.interpreter;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -14,6 +14,6 @@ final class InterpreterTaskMonitor extends TaskMonitorAdapter {
@Override @Override
public void setMessage(String message) { public void setMessage(String message) {
output.println("<pyhidra-interactive>: " + message); output.println("<pyghidra-interactive>: " + message);
} }
} }

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.interpreter; package ghidra.pyghidra.interpreter;
import java.util.List; import java.util.List;
@ -12,10 +12,10 @@ import ghidra.util.Disposable;
* This interface is for <b>internal use only</b> and is only public so it can be * This interface is for <b>internal use only</b> and is only public so it can be
* implemented in Python. * implemented in Python.
*/ */
public interface PyhidraConsole extends Disposable { public interface PyGhidraConsole extends Disposable {
/** /**
* Generates code completions for the pyhidra interpreter * Generates code completions for the PyGhidra interpreter
* *
* @param cmd The command to get code completions for * @param cmd The command to get code completions for
* @param caretPos The position of the caret in the input string 'cmd'. * @param caretPos The position of the caret in the input string 'cmd'.
@ -26,12 +26,12 @@ public interface PyhidraConsole extends Disposable {
List<CodeCompletion> getCompletions(String cmd, int caretPos); List<CodeCompletion> getCompletions(String cmd, int caretPos);
/** /**
* Restarts the pyhidra console * Restarts the PyGhidra console
*/ */
void restart(); void restart();
/** /**
* Interrupts the code running in the pyhidra console * Interrupts the code running in the PyGhidra console
*/ */
void interrupt(); void interrupt();
} }

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.interpreter; package ghidra.pyghidra.interpreter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.List; import java.util.List;
@ -8,20 +8,20 @@ import ghidra.app.plugin.core.console.CodeCompletion;
import ghidra.app.plugin.core.interpreter.InterpreterConnection; import ghidra.app.plugin.core.interpreter.InterpreterConnection;
import ghidra.app.plugin.core.interpreter.InterpreterConsole; import ghidra.app.plugin.core.interpreter.InterpreterConsole;
import ghidra.app.plugin.core.interpreter.InterpreterPanelService; import ghidra.app.plugin.core.interpreter.InterpreterPanelService;
import ghidra.pyhidra.PyhidraPlugin; import ghidra.pyghidra.PyGhidraPlugin;
import ghidra.util.Disposable; import ghidra.util.Disposable;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import resources.ResourceManager; import resources.ResourceManager;
/** /**
* The pyhidra interpreter connection * The PyGhidra interpreter connection
*/ */
public final class PyhidraInterpreter implements Disposable, InterpreterConnection { public final class PyGhidraInterpreter implements Disposable, InterpreterConnection {
private PyhidraConsole pyhidraConsole = null; private PyGhidraConsole pyghidraConsole = null;
public final InterpreterConsole console; public final InterpreterConsole console;
public PyhidraInterpreter(PyhidraPlugin plugin, boolean isPythonAvailable) { public PyGhidraInterpreter(PyGhidraPlugin plugin, boolean isPythonAvailable) {
InterpreterPanelService service = InterpreterPanelService service =
plugin.getTool().getService(InterpreterPanelService.class); plugin.getTool().getService(InterpreterPanelService.class);
console = service.createInterpreterPanel(this, false); console = service.createInterpreterPanel(this, false);
@ -32,8 +32,8 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
@Override @Override
public void dispose() { public void dispose() {
if (pyhidraConsole != null) { if (pyghidraConsole != null) {
pyhidraConsole.dispose(); pyghidraConsole.dispose();
} }
console.dispose(); console.dispose();
} }
@ -45,7 +45,7 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
@Override @Override
public String getTitle() { public String getTitle() {
return PyhidraPlugin.TITLE; return PyGhidraPlugin.TITLE;
} }
@Override @Override
@ -55,20 +55,20 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
@Override @Override
public List<CodeCompletion> getCompletions(String cmd, int caretPos) { public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
if (pyhidraConsole == null) { if (pyghidraConsole == null) {
return List.of(); return List.of();
} }
return pyhidraConsole.getCompletions(cmd, caretPos); return pyghidraConsole.getCompletions(cmd, caretPos);
} }
private void unavailableCallback() { private void unavailableCallback() {
console.setInputPermitted(false); console.setInputPermitted(false);
PrintWriter out = console.getOutWriter(); PrintWriter out = console.getOutWriter();
out.println("Ghidra was not started with pyhidra. Python is not available."); out.println("Ghidra was not started with PyGhidra. Python is not available.");
} }
/** /**
* Initializes the interpreter with the provided PyhidraConsole. * Initializes the interpreter with the provided PyGhidraConsole.
* *
* This method is for <b>internal use only</b> and is only public so it can be * This method is for <b>internal use only</b> and is only public so it can be
* called from Python. * called from Python.
@ -76,13 +76,13 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
* @param pythonSideConsole the python side console * @param pythonSideConsole the python side console
* @throws AssertException if the interpreter has already been initialized * @throws AssertException if the interpreter has already been initialized
*/ */
public void init(PyhidraConsole pythonSideConsole) { public void init(PyGhidraConsole pythonSideConsole) {
if (pyhidraConsole != null) { if (pyghidraConsole != null) {
throw new AssertException("the interpreter has already been initialized"); throw new AssertException("the interpreter has already been initialized");
} }
pyhidraConsole = pythonSideConsole; pyghidraConsole = pythonSideConsole;
console.addFirstActivationCallback(pyhidraConsole::restart); console.addFirstActivationCallback(pyghidraConsole::restart);
console.addAction(new CancelAction(pyhidraConsole)); console.addAction(new CancelAction(pyghidraConsole));
console.addAction(new ResetAction(pyhidraConsole)); console.addAction(new ResetAction(pyghidraConsole));
} }
} }

View File

@ -1,9 +1,9 @@
package ghidra.pyhidra.interpreter; package ghidra.pyghidra.interpreter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import ghidra.pyhidra.PyhidraPlugin; import ghidra.pyghidra.PyGhidraPlugin;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import docking.ActionContext; import docking.ActionContext;
import docking.action.DockingAction; import docking.action.DockingAction;
@ -15,10 +15,10 @@ import static docking.DockingUtils.CONTROL_KEY_MODIFIER_MASK;
final class ResetAction extends DockingAction { final class ResetAction extends DockingAction {
private final PyhidraConsole console; private final PyGhidraConsole console;
ResetAction(PyhidraConsole console) { ResetAction(PyGhidraConsole console) {
super("Reset", PyhidraPlugin.class.getSimpleName()); super("Reset", PyGhidraPlugin.class.getSimpleName());
this.console = console; this.console = console;
setDescription("Reset the interpreter"); setDescription("Reset the interpreter");
ImageIcon image = ResourceManager.loadImage("images/reload3.png"); ImageIcon image = ResourceManager.loadImage("images/reload3.png");
@ -26,7 +26,7 @@ final class ResetAction extends DockingAction {
setEnabled(true); setEnabled(true);
KeyBindingData key = new KeyBindingData(KeyEvent.VK_D, CONTROL_KEY_MODIFIER_MASK); KeyBindingData key = new KeyBindingData(KeyEvent.VK_D, CONTROL_KEY_MODIFIER_MASK);
setKeyBindingData(key); setKeyBindingData(key);
setHelpLocation(new HelpLocation(PyhidraPlugin.TITLE, "Reset_Interpreter")); setHelpLocation(new HelpLocation(PyGhidraPlugin.TITLE, "Reset_Interpreter"));
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
@ -16,7 +16,7 @@ import java.lang.invoke.MethodHandle;
* } * }
* } * }
* *
* The pyhidra internals expects every {@link JavaProperty} to be an instance of this class. * The PyGhidra internals expects every {@link JavaProperty} to be an instance of this class.
* No checking is required or performed since the {@link JavaProperty} interface and this * No checking is required or performed since the {@link JavaProperty} interface and this
* class are sealed. * class are sealed.
*/ */

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
/** /**
* Property interface for creating a Python property for getters and setters. * Property interface for creating a Python property for getters and setters.

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.property; package ghidra.pyghidra.property;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;

View File

@ -1,9 +1,9 @@
# pyhidra # PyGhidra
Pyhidra is a Python library that provides direct access to the Ghidra API within a native CPython interpreter using [jpype](https://jpype.readthedocs.io/en/latest). As well, Pyhidra contains some conveniences for setting up analysis on a given sample and running a Ghidra script locally. It also contains a Ghidra plugin to allow the use of CPython from the Ghidra user interface. PyGhidra is a Python library that provides direct access to the Ghidra API within a native CPython interpreter using [jpype](https://jpype.readthedocs.io/en/latest). As well, PyGhidra contains some conveniences for setting up analysis on a given sample and running a Ghidra script locally. It also contains a Ghidra plugin to allow the use of CPython from the Ghidra user interface.
Pyhidra was initially developed for use with Dragodis and is designed to be installable without requiring Java or Ghidra. This allows other Python projects PyGhidra was initially developed for use with Dragodis and is designed to be installable without requiring Java or Ghidra. This allows other Python projects
have pyhidra as a dependency and provide optional Ghidra functionality without requiring all users to install Java and Ghidra. It is recommended to recommend that users set the `GHIDRA_INSTALL_DIR` environment variable to simplify locating Ghidra. have PyGhidra as a dependency and provide optional Ghidra functionality without requiring all users to install Java and Ghidra. It is recommended to recommend that users set the `GHIDRA_INSTALL_DIR` environment variable to simplify locating Ghidra.
## Usage ## Usage
@ -18,8 +18,8 @@ which will allow you to directly import `ghidra` and `java`.
*NOTE: No projects or programs get setup in this mode.* *NOTE: No projects or programs get setup in this mode.*
```python ```python
import pyhidra import pyghidra
pyhidra.start() pyghidra.start()
import ghidra import ghidra
from ghidra.app.util.headless import HeadlessAnalyzer from ghidra.app.util.headless import HeadlessAnalyzer
@ -32,12 +32,12 @@ from java.lang import String
### Customizing Java and Ghidra initialization ### Customizing Java and Ghidra initialization
JVM configuration for the classpath and vmargs may be done through a `PyhidraLauncher`. JVM configuration for the classpath and vmargs may be done through a `PyGhidraLauncher`.
```python ```python
from pyhidra.launcher import HeadlessPyhidraLauncher from pyghidra.launcher import HeadlessPyGhidraLauncher
launcher = HeadlessPyhidraLauncher() launcher = HeadlessPyGhidraLauncher()
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar") launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true") launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
launcher.start() launcher.start()
@ -45,10 +45,10 @@ launcher.start()
### Registering an Entry Point ### Registering an Entry Point
The `PyhidraLauncher` can also be configured through the use of a registered entry point on your own python project. The `PyGhidraLauncher` can also be configured through the use of a registered entry point on your own python project.
This is useful for installing your own Ghidra plugin which uses pyhidra and self-compiles. This is useful for installing your own Ghidra plugin which uses PyGhidra and self-compiles.
First create an [entry_point](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) for `pyhidra.setup` First create an [entry_point](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) for `pyghidra.setup`
pointing to a single argument function which accepts the launcher instance. pointing to a single argument function which accepts the launcher instance.
```python ```python
@ -58,7 +58,7 @@ from setuptools import setup
setup( setup(
# ..., # ...,
entry_points={ entry_points={
'pyhidra.setup': [ 'pyghidra.setup': [
'acme_plugin = acme.ghidra_plugin.install:setup', 'acme_plugin = acme.ghidra_plugin.install:setup',
] ]
} }
@ -67,25 +67,25 @@ setup(
Then we create the target function. Then we create the target function.
This function will be called every time a user starts a pyhidra launcher. This function will be called every time a user starts a PyGhidra launcher.
In the same fashion, another entry point `pyhidra.pre_launch` may be registered and will be called after Ghidra and all In the same fashion, another entry point `pyghidra.pre_launch` may be registered and will be called after Ghidra and all
plugins have been loaded. plugins have been loaded.
```python ```python
# acme/ghidra_plugin/install.py # acme/ghidra_plugin/install.py
from pathlib import Path from pathlib import Path
import pyhidra import pyghidra
def setup(launcher): def setup(launcher):
""" """
Run by pyhidra launcher to install our plugin. Run by PyGhidra launcher to install our plugin.
""" """
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar") launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true") launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
# Install our plugin. # Install our plugin.
source_path = Path(__file__).parent / "java" / "plugin" # path to uncompiled .java code source_path = Path(__file__).parent / "java" / "plugin" # path to uncompiled .java code
details = pyhidra.ExtensionDetails( details = pyghidra.ExtensionDetails(
name="acme_plugin", name="acme_plugin",
description="My Cool Plugin", description="My Cool Plugin",
author="acme", author="acme",
@ -97,15 +97,15 @@ def setup(launcher):
### Analyze a File ### Analyze a File
To have pyhidra setup a binary file for you, use the `open_program()` function. To have PyGhidra setup a binary file for you, use the `open_program()` function.
This will setup a Ghidra project and import the given binary file as a program for you. This will setup a Ghidra project and import the given binary file as a program for you.
Again, this will also allow you to import `ghidra` and `java` to perform more advanced processing. Again, this will also allow you to import `ghidra` and `java` to perform more advanced processing.
```python ```python
import pyhidra import pyghidra
with pyhidra.open_program("binary_file.exe") as flat_api: with pyghidra.open_program("binary_file.exe") as flat_api:
program = flat_api.getCurrentProgram() program = flat_api.getCurrentProgram()
listing = program.getListing() listing = program.getListing()
print(listing.getCodeUnitAt(flat_api.toAddr(0x1234))) print(listing.getCodeUnitAt(flat_api.toAddr(0x1234)))
@ -117,12 +117,12 @@ with pyhidra.open_program("binary_file.exe") as flat_api:
decomp_api.dispose() decomp_api.dispose()
``` ```
By default, pyhidra will run analysis for you. If you would like to do this yourself, set `analyze` to `False`. By default, PyGhidra will run analysis for you. If you would like to do this yourself, set `analyze` to `False`.
```python ```python
import pyhidra import pyghidra
with pyhidra.open_program("binary_file.exe", analyze=False) as flat_api: with pyghidra.open_program("binary_file.exe", analyze=False) as flat_api:
from ghidra.program.util import GhidraProgramUtilities from ghidra.program.util import GhidraProgramUtilities
program = flat_api.getCurrentProgram() program = flat_api.getCurrentProgram()
@ -135,16 +135,16 @@ The `open_program()` function can also accept optional arguments to control the
(Helpful for opening up a sample in an already existing project.) (Helpful for opening up a sample in an already existing project.)
```python ```python
import pyhidra import pyghidra
with pyhidra.open_program("binary_file.exe", project_name="EXAM_231", project_location=r"C:\exams\231") as flat_api: with pyghidra.open_program("binary_file.exe", project_name="EXAM_231", project_location=r"C:\exams\231") as flat_api:
... ...
``` ```
### Run a Script ### Run a Script
Pyhidra can also be used to run an existing Ghidra Python script directly in your native python interpreter PyGhidra can also be used to run an existing Ghidra Python script directly in your native python interpreter
using the `run_script()` command. using the `run_script()` command.
However, while you can technically run an existing Ghidra script unmodified, you may However, while you can technically run an existing Ghidra script unmodified, you may
run into issues due to differences between Jython 2 and CPython 3. run into issues due to differences between Jython 2 and CPython 3.
@ -152,21 +152,21 @@ Therefore, some modification to the script may be needed.
```python ```python
import pyhidra import pyghidra
pyhidra.run_script(r"C:\input.exe", r"C:\some_ghidra_script.py") pyghidra.run_script(r"C:\input.exe", r"C:\some_ghidra_script.py")
``` ```
This can also be done on the command line using `pyhidra`. This can also be done on the command line using `pyghidra`.
```console ```console
> pyhidra C:\input.exe C:\some_ghidra_script.py <CLI ARGS PASSED TO SCRIPT> > pyghidra C:\input.exe C:\some_ghidra_script.py <CLI ARGS PASSED TO SCRIPT>
``` ```
### Handling Package Name Conflicts ### Handling Package Name Conflicts
There may be some Python modules and Java packages with the same import path. When this occurs the Python module takes precedence. There may be some Python modules and Java packages with the same import path. When this occurs the Python module takes precedence.
While jpype has its own mechanism for handling this situation, pyhidra automatically makes the Java package accessible by allowing While jpype has its own mechanism for handling this situation, PyGhidra automatically makes the Java package accessible by allowing
it to be imported with an underscore appended to the package name. it to be imported with an underscore appended to the package name.
```python ```python

View File

@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[project] [project]
name = "pyhidra" name = "pyghidra"
dynamic = ["version", "readme"] dynamic = ["version", "readme"]
description = "Native CPython for Ghidra" description = "Native CPython for Ghidra"
license = {text = "Apache-2.0"} license = {text = "Apache-2.0"}
@ -39,16 +39,16 @@ testing = [
] ]
[project.scripts] [project.scripts]
pyhidra = "pyhidra.__main__:main" pyghidra = "pyghidra.__main__:main"
[project.gui-scripts] [project.gui-scripts]
pyhidraw = "pyhidra.gui:_gui" pyghidraw = "pyghidra.gui:_gui"
[project.urls] [project.urls]
Repository = "https://github.com/NationalSecurityAgency/ghidra" Repository = "https://github.com/NationalSecurityAgency/ghidra"
[tool.setuptools.dynamic] [tool.setuptools.dynamic]
version = {attr = "pyhidra.__version__"} version = {attr = "pyghidra.__version__"}
readme = {file = ["README.md"], content-type = "text/markdown"} readme = {file = ["README.md"], content-type = "text/markdown"}
[tool.pytest.ini_options] [tool.pytest.ini_options]

View File

@ -41,13 +41,13 @@ debug_callback = _debug_callback
# Expose API # Expose API
from .core import run_script, start, started, open_program from .core import run_script, start, started, open_program
from .launcher import DeferredPyhidraLauncher, GuiPyhidraLauncher, HeadlessPyhidraLauncher from .launcher import DeferredPyGhidraLauncher, GuiPyGhidraLauncher, HeadlessPyGhidraLauncher
from .script import get_current_interpreter from .script import get_current_interpreter
from .version import ApplicationInfo, ExtensionDetails from .version import ApplicationInfo, ExtensionDetails
__all__ = [ __all__ = [
"debug_callback", "get_current_interpreter", "open_program", "run_script", "start", "debug_callback", "get_current_interpreter", "open_program", "run_script", "start",
"started", "ApplicationInfo", "DeferredPyhidraLauncher", "ExtensionDetails", "started", "ApplicationInfo", "DeferredPyGhidraLauncher", "ExtensionDetails",
"GuiPyhidraLauncher", "HeadlessPyhidraLauncher" "GuiPyGhidraLauncher", "HeadlessPyGhidraLauncher"
] ]

View File

@ -5,13 +5,13 @@ import logging
import sys import sys
from pathlib import Path from pathlib import Path
import pyhidra import pyghidra
import pyhidra.core import pyghidra.core
import pyhidra.gui import pyghidra.gui
# NOTE: this must be "pyhidra" and not __name__ # NOTE: this must be "pyghidra" and not __name__
logger = logging.getLogger("pyhidra") logger = logging.getLogger("pyghidra")
def _interpreter(interpreter_globals: dict): def _interpreter(interpreter_globals: dict):
@ -24,7 +24,7 @@ def _interpreter(interpreter_globals: dict):
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
class PyhidraArgs(argparse.Namespace): class PyGhidraArgs(argparse.Namespace):
""" """
Custom namespace for holding the command line arguments Custom namespace for holding the command line arguments
""" """
@ -60,18 +60,18 @@ class PyhidraArgs(argparse.Namespace):
vmargs = self.jvm_args vmargs = self.jvm_args
if self.gui: if self.gui:
pyhidra.gui.gui(self.install_dir, vmargs) pyghidra.gui.gui(self.install_dir, vmargs)
return return
# not in gui mode so it is easier to start Ghidra now # not in gui mode so it is easier to start Ghidra now
launcher = pyhidra.HeadlessPyhidraLauncher( launcher = pyghidra.HeadlessPyGhidraLauncher(
verbose=self.verbose, install_dir=self.install_dir) verbose=self.verbose, install_dir=self.install_dir)
launcher.vm_args = vmargs + launcher.vm_args launcher.vm_args = vmargs + launcher.vm_args
launcher.start() launcher.start()
if self.script_path is not None: if self.script_path is not None:
try: try:
pyhidra.run_script( pyghidra.run_script(
self.binary_path, self.binary_path,
self.script_path, self.script_path,
project_location=self.project_path, project_location=self.project_path,
@ -92,7 +92,7 @@ class PyhidraArgs(argparse.Namespace):
self.verbose, self.verbose,
not self.skip_analysis not self.skip_analysis
) )
with pyhidra.core._flat_api(*args, install_dir=self.install_dir) as api: with pyghidra.core._flat_api(*args, install_dir=self.install_dir) as api:
_interpreter(api) _interpreter(api)
else: else:
_interpreter(globals()) _interpreter(globals())
@ -129,7 +129,7 @@ class PathAction(argparse.Action):
self.nargs = '*' self.nargs = '*'
self.type = str self.type = str
def __call__(self, parser, namespace: PyhidraArgs, values, option_string=None): def __call__(self, parser, namespace: PyGhidraArgs, values, option_string=None):
if not values: if not values:
return return
@ -168,7 +168,7 @@ class PathAction(argparse.Action):
def _get_parser(): def _get_parser():
parser = argparse.ArgumentParser(prog="pyhidra") parser = argparse.ArgumentParser(prog="pyghidra")
parser.add_argument( parser.add_argument(
"-v", "-v",
"--verbose", "--verbose",
@ -215,7 +215,7 @@ def _get_parser():
action=PathAction, action=PathAction,
help=( help=(
"Headless script path. The script must have a .py extension. " "Headless script path. The script must have a .py extension. "
"If a script is not provided, pyhidra will drop into a repl." "If a script is not provided, pyghidra will drop into a repl."
) )
) )
parser.add_argument( parser.add_argument(
@ -258,7 +258,7 @@ def _get_parser():
def main(): def main():
""" """
pyhidra module main function pyghidra module main function
""" """
handler = logging.StreamHandler() handler = logging.StreamHandler()
formatter = logging.Formatter("%(filename)s:%(lineno)d %(message)s") formatter = logging.Formatter("%(filename)s:%(lineno)d %(message)s")
@ -266,7 +266,7 @@ def main():
logger.addHandler(handler) logger.addHandler(handler)
parser = _get_parser() parser = _get_parser()
parser.parse_args(namespace=PyhidraArgs(parser)).func() parser.parse_args(namespace=PyGhidraArgs(parser)).func()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -2,18 +2,18 @@ import contextlib
from pathlib import Path from pathlib import Path
from typing import Union, TYPE_CHECKING, Tuple, ContextManager, List, Optional from typing import Union, TYPE_CHECKING, Tuple, ContextManager, List, Optional
from pyhidra.converters import * # pylint: disable=wildcard-import, unused-wildcard-import from pyghidra.converters import * # pylint: disable=wildcard-import, unused-wildcard-import
if TYPE_CHECKING: if TYPE_CHECKING:
from pyhidra.launcher import PyhidraLauncher from pyghidra.launcher import PyGhidraLauncher
from ghidra.base.project import GhidraProject from ghidra.base.project import GhidraProject
from ghidra.program.flatapi import FlatProgramAPI from ghidra.program.flatapi import FlatProgramAPI
from ghidra.program.model.lang import CompilerSpec, Language, LanguageService from ghidra.program.model.lang import CompilerSpec, Language, LanguageService
from ghidra.program.model.listing import Program from ghidra.program.model.listing import Program
def start(verbose=False, *, install_dir: Path = None) -> "PyhidraLauncher": def start(verbose=False, *, install_dir: Path = None) -> "PyGhidraLauncher":
""" """
Starts the JVM and fully initializes Ghidra in Headless mode. Starts the JVM and fully initializes Ghidra in Headless mode.
@ -22,18 +22,18 @@ def start(verbose=False, *, install_dir: Path = None) -> "PyhidraLauncher":
(Defaults to the GHIDRA_INSTALL_DIR environment variable) (Defaults to the GHIDRA_INSTALL_DIR environment variable)
:return: The PhyidraLauncher used to start the JVM :return: The PhyidraLauncher used to start the JVM
""" """
from pyhidra.launcher import HeadlessPyhidraLauncher from pyghidra.launcher import HeadlessPyGhidraLauncher
launcher = HeadlessPyhidraLauncher(verbose=verbose, install_dir=install_dir) launcher = HeadlessPyGhidraLauncher(verbose=verbose, install_dir=install_dir)
launcher.start() launcher.start()
return launcher return launcher
def started() -> bool: def started() -> bool:
""" """
Whether the PyhidraLauncher has already started. Whether the PyGhidraLauncher has already started.
""" """
from pyhidra.launcher import PyhidraLauncher from pyghidra.launcher import PyGhidraLauncher
return PyhidraLauncher.has_launched() return PyGhidraLauncher.has_launched()
def _get_language(id: str) -> "Language": def _get_language(id: str) -> "Language":
@ -137,7 +137,7 @@ def _setup_project(
def _setup_script(project: "GhidraProject", program: "Program"): def _setup_script(project: "GhidraProject", program: "Program"):
from pyhidra.script import PyGhidraScript from pyghidra.script import PyGhidraScript
from ghidra.app.script import GhidraState from ghidra.app.script import GhidraState
from ghidra.program.util import ProgramLocation from ghidra.program.util import ProgramLocation
from ghidra.util.task import TaskMonitor from ghidra.util.task import TaskMonitor
@ -205,10 +205,10 @@ def open_program(
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`. :raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
""" """
from pyhidra.launcher import PyhidraLauncher, HeadlessPyhidraLauncher from pyghidra.launcher import PyGhidraLauncher, HeadlessPyGhidraLauncher
if not PyhidraLauncher.has_launched(): if not PyGhidraLauncher.has_launched():
HeadlessPyhidraLauncher().start() HeadlessPyGhidraLauncher().start()
from ghidra.app.script import GhidraScriptUtil from ghidra.app.script import GhidraScriptUtil
from ghidra.program.flatapi import FlatProgramAPI from ghidra.program.flatapi import FlatProgramAPI
@ -273,10 +273,10 @@ def _flat_api(
:raises ValueError: If the provided language, compiler or loader is invalid. :raises ValueError: If the provided language, compiler or loader is invalid.
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`. :raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
""" """
from pyhidra.launcher import PyhidraLauncher, HeadlessPyhidraLauncher from pyghidra.launcher import PyGhidraLauncher, HeadlessPyGhidraLauncher
if not PyhidraLauncher.has_launched(): if not PyGhidraLauncher.has_launched():
HeadlessPyhidraLauncher(verbose=verbose, install_dir=install_dir).start() HeadlessPyGhidraLauncher(verbose=verbose, install_dir=install_dir).start()
project, program = None, None project, program = None, None
if binary_path or project_location: if binary_path or project_location:

View File

@ -4,10 +4,10 @@ from pathlib import Path
import sys import sys
import threading import threading
from .launcher import PyhidraLauncher, _run_mac_app from .launcher import PyGhidraLauncher, _run_mac_app
class GhidraLauncher(PyhidraLauncher): class GhidraLauncher(PyGhidraLauncher):
def __init__(self, verbose=False, class_name=str, gui=False, *, install_dir: Path = None): def __init__(self, verbose=False, class_name=str, gui=False, *, install_dir: Path = None):
super().__init__(verbose=verbose, install_dir=install_dir) super().__init__(verbose=verbose, install_dir=install_dir)

View File

@ -50,14 +50,14 @@ class _Helper:
self.msg += " # Perform headless processing\n" self.msg += " # Perform headless processing\n"
self.msg += " headless.processLocal(...)\n\n" self.msg += " headless.processLocal(...)\n\n"
else: else:
# PyhidraPlugin scenario # PyGhidraPlugin scenario
self.msg = "Press 'F1' for usage instructions" self.msg = "Press 'F1' for usage instructions"
def __call__(self, param=None): def __call__(self, param=None):
def get_class_and_method(param): def get_class_and_method(param):
if param is None and not SystemUtilities.isInHeadlessMode(): if param is None and not SystemUtilities.isInHeadlessMode():
# Enable help() in PyhidraPlugin scenario to show help for GhidraScript # Enable help() in PyGhidraPlugin scenario to show help for GhidraScript
return "ghidra.app.script.GhidraScript", None return "ghidra.app.script.GhidraScript", None
class_name = None class_name = None
method_name = None method_name = None

View File

@ -8,7 +8,7 @@ import traceback
from typing import List, NoReturn from typing import List, NoReturn
import warnings import warnings
import pyhidra import pyghidra
class _GuiOutput(io.StringIO): class _GuiOutput(io.StringIO):
@ -44,7 +44,7 @@ def _gui_mac() -> NoReturn:
path = Path(sys.base_exec_prefix) / "Resources/Python.app/Contents/MacOS/Python" path = Path(sys.base_exec_prefix) / "Resources/Python.app/Contents/MacOS/Python"
if path.exists(): if path.exists():
# the python launcher app will correctly start the venv if sys.executable is in a venv # the python launcher app will correctly start the venv if sys.executable is in a venv
argv = [sys.executable, "-m", "pyhidra", "-g"] argv = [sys.executable, "-m", "pyghidra", "-g"]
if install_dir is not None: if install_dir is not None:
argv += ["--install-dir", str(install_dir)] argv += ["--install-dir", str(install_dir)]
actions = ((os.POSIX_SPAWN_CLOSE, 0), (os.POSIX_SPAWN_CLOSE, 1), (os.POSIX_SPAWN_CLOSE, 2)) actions = ((os.POSIX_SPAWN_CLOSE, 0), (os.POSIX_SPAWN_CLOSE, 1), (os.POSIX_SPAWN_CLOSE, 2))
@ -55,7 +55,7 @@ def _gui_mac() -> NoReturn:
def _parse_args(): def _parse_args():
parser = _GuiArgumentParser(prog="pyhidraw") parser = _GuiArgumentParser(prog="pyghidraw")
parser.add_argument( parser.add_argument(
"--install-dir", "--install-dir",
type=Path, type=Path,
@ -133,7 +133,7 @@ def gui(install_dir: Path = None, vm_args: List[str] = None):
(Defaults to the GHIDRA_INSTALL_DIR environment variable) (Defaults to the GHIDRA_INSTALL_DIR environment variable)
:param vm_args: Additional vm arguments to be passed ot the JVM. :param vm_args: Additional vm arguments to be passed ot the JVM.
""" """
launcher = pyhidra.GuiPyhidraLauncher(install_dir=install_dir) launcher = pyghidra.GuiPyGhidraLauncher(install_dir=install_dir)
if vm_args: if vm_args:
launcher.vm_args += vm_args launcher.vm_args += vm_args
launcher.start() launcher.start()
@ -141,8 +141,8 @@ def gui(install_dir: Path = None, vm_args: List[str] = None):
def get_current_interpreter(): def get_current_interpreter():
warnings.warn( warnings.warn(
"get_current_interpreter has been moved. Please use pyhidra.get_current_interpreter", "get_current_interpreter has been moved. Please use pyghidra.get_current_interpreter",
DeprecationWarning DeprecationWarning
) )
return pyhidra.get_current_interpreter() return pyghidra.get_current_interpreter()

View File

@ -9,8 +9,8 @@ import types
from code import InteractiveConsole from code import InteractiveConsole
from ghidra.framework import Application from ghidra.framework import Application
from ghidra.pyhidra import PyhidraScriptProvider, PyhidraPlugin from ghidra.pyghidra import PyGhidraScriptProvider, PyGhidraPlugin
from ghidra.pyhidra.interpreter import PyhidraConsole from ghidra.pyghidra.interpreter import PyGhidraConsole
from java.io import BufferedReader, InputStreamReader from java.io import BufferedReader, InputStreamReader
from java.lang import String from java.lang import String
from java.lang import Thread as JThread from java.lang import Thread as JThread
@ -18,8 +18,8 @@ from java.util import Collections
from java.util.function import Consumer from java.util.function import Consumer
from jpype import JClass, JImplements, JOverride from jpype import JClass, JImplements, JOverride
from pyhidra.internal.plugin.completions import PythonCodeCompleter from pyghidra.internal.plugin.completions import PythonCodeCompleter
from pyhidra.script import PyGhidraScript from pyghidra.script import PyGhidraScript
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -125,15 +125,15 @@ class ConsoleState(enum.Enum):
RESET = enum.auto() RESET = enum.auto()
@JImplements(PyhidraConsole) @JImplements(PyGhidraConsole)
class PyConsole(InteractiveConsole): class PyConsole(InteractiveConsole):
""" """
Pyhidra Interactive Console PyGhidra Interactive Console
""" """
_WORD_PATTERN = re.compile(r".*?([\w\.]+)\Z") # get the last word, including '.', from the right _WORD_PATTERN = re.compile(r".*?([\w\.]+)\Z") # get the last word, including '.', from the right
def __init__(self, py_plugin: PyhidraPlugin): def __init__(self, py_plugin: PyGhidraPlugin):
super().__init__(locals=PyGhidraScript(py_plugin.script)) super().__init__(locals=PyGhidraScript(py_plugin.script))
appVersion = Application.getApplicationVersion() appVersion = Application.getApplicationVersion()
appName = Application.getApplicationReleaseName() appName = Application.getApplicationReleaseName()
@ -314,11 +314,11 @@ class PyConsole(InteractiveConsole):
return Collections.emptyList() return Collections.emptyList()
def _init_plugin(plugin: PyhidraPlugin): def _init_plugin(plugin: PyGhidraPlugin):
console = PyConsole(plugin) console = PyConsole(plugin)
plugin.interpreter.init(console) plugin.interpreter.init(console)
def setup_plugin(): def setup_plugin():
PyhidraPlugin.setInitializer(Consumer @ _init_plugin) PyGhidraPlugin.setInitializer(Consumer @ _init_plugin)
PyhidraScriptProvider.setScriptRunner(Consumer @ _run_script) PyGhidraScriptProvider.setScriptRunner(Consumer @ _run_script)

View File

@ -76,7 +76,7 @@ def _load_entry_points(group: str, *args):
logger.error(f"Failed to run {group} entry point {name} with error: {e}") logger.error(f"Failed to run {group} entry point {name} with error: {e}")
class _PyhidraImportLoader: class _PyGhidraImportLoader:
""" (internal) Finder hook for importlib to handle Python mod conflicts. """ """ (internal) Finder hook for importlib to handle Python mod conflicts. """
def find_spec(self, name, path, target=None): def find_spec(self, name, path, target=None):
@ -101,7 +101,7 @@ def _plugin_lock():
File lock for processing plugins File lock for processing plugins
""" """
from java.io import RandomAccessFile from java.io import RandomAccessFile
path = Path(tempfile.gettempdir()) / "pyhidra_plugin_lock" path = Path(tempfile.gettempdir()) / "pyghidra_plugin_lock"
try: try:
# Python doesn't have a file lock except for unix systems # Python doesn't have a file lock except for unix systems
# so use the one available in Java instead of adding on # so use the one available in Java instead of adding on
@ -117,19 +117,19 @@ def _plugin_lock():
path.unlink() path.unlink()
except: except:
# if it fails it's ok # if it fails it's ok
# another pyhidra process has the lock # another pyghidra process has the lock
# it will be removed by said process when done # it will be removed by said process when done
pass pass
class PyhidraLauncher: class PyGhidraLauncher:
""" """
Base pyhidra launcher Base pyghidra launcher
""" """
def __init__(self, verbose=False, *, install_dir: Path = None): def __init__(self, verbose=False, *, install_dir: Path = None):
""" """
Initializes a new `PyhidraLauncher`. Initializes a new `PyGhidraLauncher`.
:param verbose: True to enable verbose output when starting Ghidra. :param verbose: True to enable verbose output when starting Ghidra.
:param install_dir: Ghidra installation directory. :param install_dir: Ghidra installation directory.
@ -296,10 +296,10 @@ class PyhidraLauncher:
# dev mode # dev mode
return install_dir return install_dir
path = install_dir / "Ghidra" / "Features" / "Pyhidra" / "lib" / "Pyhidra.jar" path = install_dir / "Ghidra" / "Features" / "PyGhidra" / "lib" / "PyGhidra.jar"
if not path.exists(): if not path.exists():
msg = "The Ghidra installation does not contain the Pyhidra module\n" + \ msg = "The Ghidra installation does not contain the PyGhidra module\n" + \
f"{path} does not exist" f"{path} does not exist"
cls._report_fatal_error("Incorrect Ghidra installation directory", msg, ValueError(msg)) cls._report_fatal_error("Incorrect Ghidra installation directory", msg, ValueError(msg))
@ -344,12 +344,12 @@ class PyhidraLauncher:
Run setup entry points, start the JVM and prepare ghidra imports Run setup entry points, start the JVM and prepare ghidra imports
""" """
# Before starting up, give launcher to installed entry points so they can do their thing. # Before starting up, give launcher to installed entry points so they can do their thing.
_load_entry_points("pyhidra.setup", self) _load_entry_points("pyghidra.setup", self)
# Merge classpath # Merge classpath
jpype_kwargs['classpath'] = self.class_path + jpype_kwargs.get('classpath', []) jpype_kwargs['classpath'] = self.class_path + jpype_kwargs.get('classpath', [])
# force convert strings (required by pyhidra) # force convert strings (required by pyghidra)
jpype_kwargs['convertStrings'] = True jpype_kwargs['convertStrings'] = True
# set the JAVA_HOME environment variable to the correct one so jpype uses it # set the JAVA_HOME environment variable to the correct one so jpype uses it
@ -357,7 +357,7 @@ class PyhidraLauncher:
jpype_kwargs['ignoreUnrecognized'] = True jpype_kwargs['ignoreUnrecognized'] = True
if os.getenv("PYHIDRA_DEBUG"): if os.getenv("PYGHIDRA_DEBUG"):
debug = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:18001" debug = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:18001"
self.vm_args.insert(0, debug) self.vm_args.insert(0, debug)
@ -368,7 +368,7 @@ class PyhidraLauncher:
) )
# Install hook into python importlib # Install hook into python importlib
sys.meta_path.append(_PyhidraImportLoader()) sys.meta_path.append(_PyGhidraImportLoader())
imports.registerDomain("ghidra") imports.registerDomain("ghidra")
@ -384,11 +384,11 @@ class PyhidraLauncher:
# remove any installed pyhidra extension # remove any old installed pyhidra extension
# if left in place Ghidra will fail to start with a confusing # if left in place Ghidra will fail to start with a confusing
# and unrelated error about the InterpreterConsole class not being found # and unrelated error about the InterpreterConsole class not being found
# this is only needed for those using a DEV build of Ghidra # this is only needed for those using a DEV build of Ghidra
# who also have pyhidra installed. # who also have and old version of pyhidra installed.
# however, this took an unnecessary amount of time to debug # however, this took an unnecessary amount of time to debug
self.uninstall_plugin("pyhidra") self.uninstall_plugin("pyhidra")
@ -404,7 +404,7 @@ class PyhidraLauncher:
self._layout = GhidraLauncher.initializeGhidraEnvironment() self._layout = GhidraLauncher.initializeGhidraEnvironment()
# import it at the end so interfaces in our java code may be implemented # import it at the end so interfaces in our java code may be implemented
from pyhidra.internal.plugin.plugin import setup_plugin from pyghidra.internal.plugin.plugin import setup_plugin
setup_plugin() setup_plugin()
# Add extra class paths # Add extra class paths
@ -432,7 +432,7 @@ class PyhidraLauncher:
# import properties to register the property customizer # import properties to register the property customizer
from . import properties as _ from . import properties as _
_load_entry_points("pyhidra.pre_launch") _load_entry_points("pyghidra.pre_launch")
def start(self, **jpype_kwargs): def start(self, **jpype_kwargs):
""" """
@ -548,9 +548,9 @@ class PyhidraLauncher:
return Application.isInitialized() return Application.isInitialized()
class DeferredPyhidraLauncher(PyhidraLauncher): class DeferredPyGhidraLauncher(PyGhidraLauncher):
""" """
PyhidraLauncher which allows full Ghidra initialization to be deferred. PyGhidraLauncher which allows full Ghidra initialization to be deferred.
initialize_ghidra must be called before all Ghidra classes are fully available. initialize_ghidra must be called before all Ghidra classes are fully available.
""" """
@ -571,9 +571,9 @@ class DeferredPyhidraLauncher(PyhidraLauncher):
GhidraRun().launch(self._layout, self.args) GhidraRun().launch(self._layout, self.args)
class HeadlessPyhidraLauncher(PyhidraLauncher): class HeadlessPyGhidraLauncher(PyGhidraLauncher):
""" """
Headless pyhidra launcher Headless pyghidra launcher
""" """
def _launch(self): def _launch(self):
@ -583,7 +583,7 @@ class HeadlessPyhidraLauncher(PyhidraLauncher):
Application.initializeApplication(self._layout, config) Application.initializeApplication(self._layout, config)
class _PyhidraStdOut: class _PyGhidraStdOut:
def __init__(self, stream): def __init__(self, stream):
self._stream = stream self._stream = stream
@ -615,9 +615,9 @@ class _PyhidraStdOut:
return self._stream.write(s) return self._stream.write(s)
class GuiPyhidraLauncher(PyhidraLauncher): class GuiPyGhidraLauncher(PyGhidraLauncher):
""" """
GUI pyhidra launcher GUI pyghidra launcher
""" """
@classmethod @classmethod
@ -647,8 +647,8 @@ class GuiPyhidraLauncher(PyhidraLauncher):
appid = ctypes.c_wchar_p(self.app_info.name) appid = ctypes.c_wchar_p(self.app_info.name)
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid) ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid)
stdout = _PyhidraStdOut(sys.stdout) stdout = _PyGhidraStdOut(sys.stdout)
stderr = _PyhidraStdOut(sys.stderr) stderr = _PyGhidraStdOut(sys.stderr)
with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(stderr): with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(stderr):
Thread(lambda: Ghidra.main(["ghidra.GhidraRun", *self.args])).start() Thread(lambda: Ghidra.main(["ghidra.GhidraRun", *self.args])).start()
is_exiting = threading.Event() is_exiting = threading.Event()

View File

@ -14,10 +14,10 @@ class _JavaObject:
if isinstance(self, jpype.JException): if isinstance(self, jpype.JException):
# don't process any exceptions # don't process any exceptions
return return
exposer = jpype.JClass("ghidra.pyhidra.PythonFieldExposer") exposer = jpype.JClass("ghidra.pyghidra.PythonFieldExposer")
if exposer.class_.isAssignableFrom(self.class_): if exposer.class_.isAssignableFrom(self.class_):
return return
utils = jpype.JClass("ghidra.pyhidra.property.PropertyUtils") utils = jpype.JClass("ghidra.pyghidra.property.PropertyUtils")
for prop in utils.getProperties(self.class_): for prop in utils.getProperties(self.class_):
field = prop.field field = prop.field
if keyword.iskeyword(field): if keyword.iskeyword(field):

View File

@ -12,7 +12,7 @@ from jpype import JClass, JImplementationFor
from typing import List from typing import List
from pyhidra import debug_callback from pyghidra import debug_callback
_NO_ATTRIBUTE = object() _NO_ATTRIBUTE = object()
@ -70,12 +70,12 @@ class _JavaProperty(property):
#pylint: disable=too-few-public-methods #pylint: disable=too-few-public-methods
@JImplementationFor("ghidra.pyhidra.PythonFieldExposer") @JImplementationFor("ghidra.pyghidra.PythonFieldExposer")
class _PythonFieldExposer: class _PythonFieldExposer:
#pylint: disable=no-member #pylint: disable=no-member
def __jclass_init__(self): def __jclass_init__(self):
exposer = JClass("ghidra.pyhidra.PythonFieldExposer") exposer = JClass("ghidra.pyghidra.PythonFieldExposer")
if self.class_ == exposer: if self.class_ == exposer:
return return
try: try:
@ -135,8 +135,8 @@ class PyGhidraScript(dict):
def __init__(self, jobj=None): def __init__(self, jobj=None):
super().__init__() super().__init__()
if jobj is None: if jobj is None:
from ghidra.pyhidra import PyhidraScriptProvider from ghidra.pyghidra import PyGhidraScriptProvider
jobj = PyhidraScriptProvider().getScriptInstance(None, None) jobj = PyGhidraScriptProvider().getScriptInstance(None, None)
self._script = jobj self._script = jobj
global _headless_interpreter global _headless_interpreter
@ -258,7 +258,7 @@ class PyGhidraScript(dict):
def get_current_interpreter(): def get_current_interpreter():
""" """
Gets the underlying GhidraScript for the focused Pyhidra InteractiveConsole. Gets the underlying GhidraScript for the focused PyGhidra InteractiveConsole.
This will always return None unless it is being access from a function This will always return None unless it is being access from a function
called from within the interactive console. called from within the interactive console.
@ -274,8 +274,8 @@ def get_current_interpreter():
if SystemUtilities.isInHeadlessMode(): if SystemUtilities.isInHeadlessMode():
if _headless_interpreter is None: if _headless_interpreter is None:
# one hasn't been created yet so make one now # one hasn't been created yet so make one now
PyhidraScriptProvider = JClass("ghidra.pyhidra.PyhidraScriptProvider") PyGhidraScriptProvider = JClass("ghidra.pyghidra.PyGhidraScriptProvider")
_headless_interpreter = PyhidraScriptProvider.PyhidraHeadlessScript() _headless_interpreter = PyGhidraScriptProvider.PyGhidraHeadlessScript()
return _headless_interpreter return _headless_interpreter
project = AppInfo.getActiveProject() project = AppInfo.getActiveProject()
@ -293,7 +293,7 @@ def get_current_interpreter():
return None return None
for plugin in tool.getManagedPlugins(): for plugin in tool.getManagedPlugins():
if plugin.name == 'PyhidraPlugin': if plugin.name == 'PyGhidraPlugin':
return plugin.script return plugin.script
except ImportError: except ImportError:

View File

@ -1,4 +1,4 @@
package ghidra.pyhidra.test; package ghidra.pyghidra.test;
/** /**
* This is a bad class that will fail to compile. * This is a bad class that will fail to compile.

View File

@ -1,9 +1,9 @@
package ghidra.pyhidra.test; package ghidra.pyghidra.test;
import ghidra.app.util.recognizer.Recognizer; import ghidra.app.util.recognizer.Recognizer;
/** /**
* Simple ExtensionPoint class for pyhidra plugin test. * Simple ExtensionPoint class for PyGhidra plugin test.
* *
* This can be any ExtensionPoint. Recognizer was chosen here * This can be any ExtensionPoint. Recognizer was chosen here
* because it has a small number of methods and hasn't changed in a long time. * because it has a small number of methods and hasn't changed in a long time.

View File

@ -2,9 +2,9 @@ from pathlib import Path
from typing import List, Tuple from typing import List, Tuple
import pytest import pytest
from pyhidra.__main__ import _get_parser, PyhidraArgs from pyghidra.__main__ import _get_parser, PyGhidraArgs
from pyhidra.ghidra_launch import ParsedArgs from pyghidra.ghidra_launch import ParsedArgs
from pyhidra.ghidra_launch import get_parser as get_ghidra_launcher_parser from pyghidra.ghidra_launch import get_parser as get_ghidra_launcher_parser
PROJECT_NAME = "stub_name" PROJECT_NAME = "stub_name"
@ -20,9 +20,9 @@ def exe_file(shared_datadir: Path):
class TestArgParser: class TestArgParser:
def parse(self, *args) -> PyhidraArgs: def parse(self, *args) -> PyGhidraArgs:
parser = _get_parser() parser = _get_parser()
parser_args = PyhidraArgs(parser) parser_args = PyGhidraArgs(parser)
args = [str(arg) for arg in args] args = [str(arg) for arg in args]
parser.parse_args(args, namespace=parser_args) parser.parse_args(args, namespace=parser_args)
return parser_args return parser_args

View File

@ -4,7 +4,7 @@ import textwrap
import importlib import importlib
import sys import sys
import jpype import jpype
import pyhidra import pyghidra
import pytest import pytest
EXE_NAME = "strings.exe" EXE_NAME = "strings.exe"
@ -23,7 +23,7 @@ def class_file(shared_datadir: Path):
def test_invalid_jpype_keyword_arg(): def test_invalid_jpype_keyword_arg():
assert not jpype.isJVMStarted() assert not jpype.isJVMStarted()
launcher = pyhidra.launcher.HeadlessPyhidraLauncher() launcher = pyghidra.launcher.HeadlessPyGhidraLauncher()
with pytest.raises(TypeError) as ex: with pytest.raises(TypeError) as ex:
launcher.start(someBogusKeywordArg=True) launcher.start(someBogusKeywordArg=True)
assert "startJVM() got an unexpected keyword argument 'someBogusKeywordArg'" in str(ex.value) assert "startJVM() got an unexpected keyword argument 'someBogusKeywordArg'" in str(ex.value)
@ -32,7 +32,7 @@ def test_invalid_jpype_keyword_arg():
def test_invalid_vm_arg_succeed(): def test_invalid_vm_arg_succeed():
assert not jpype.isJVMStarted() assert not jpype.isJVMStarted()
launcher = pyhidra.launcher.HeadlessPyhidraLauncher() launcher = pyghidra.launcher.HeadlessPyGhidraLauncher()
launcher.add_vmargs('-XX:SomeBogusJvmArg') launcher.add_vmargs('-XX:SomeBogusJvmArg')
launcher.start(ignoreUnrecognized=True) launcher.start(ignoreUnrecognized=True)
@ -40,7 +40,7 @@ def test_invalid_vm_arg_succeed():
def test_run_script(capsys, shared_datadir: Path): def test_run_script(capsys, shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
script_path = shared_datadir / "example_script.py" script_path = shared_datadir / "example_script.py"
pyhidra.run_script(strings_exe, script_path, script_args=["my", "--commands"], analyze=False) pyghidra.run_script(strings_exe, script_path, script_args=["my", "--commands"], analyze=False)
captured = capsys.readouterr() captured = capsys.readouterr()
assert captured.err == "" assert captured.err == ""
@ -56,7 +56,7 @@ def test_run_script(capsys, shared_datadir: Path):
def test_open_program(shared_datadir: Path): def test_open_program(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pyhidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE, compiler=TEST_COMPILER) as flat_api: with pyghidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE, compiler=TEST_COMPILER) as flat_api:
assert flat_api.currentProgram.name == strings_exe.name assert flat_api.currentProgram.name == strings_exe.name
assert flat_api.getCurrentProgram().listing assert flat_api.getCurrentProgram().listing
assert flat_api.getCurrentProgram().changeable assert flat_api.getCurrentProgram().changeable
@ -65,7 +65,7 @@ def test_open_program(shared_datadir: Path):
def test_bad_language(shared_datadir: Path): def test_bad_language(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pytest.raises(ValueError): with pytest.raises(ValueError):
with pyhidra.open_program( with pyghidra.open_program(
strings_exe, strings_exe,
analyze=False, analyze=False,
language="invalid" language="invalid"
@ -76,7 +76,7 @@ def test_bad_language(shared_datadir: Path):
def test_bad_compiler(shared_datadir: Path): def test_bad_compiler(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pytest.raises(ValueError): with pytest.raises(ValueError):
with pyhidra.open_program( with pyghidra.open_program(
strings_exe, strings_exe,
analyze=False, analyze=False,
language=TEST_LANGUAGE, language=TEST_LANGUAGE,
@ -87,19 +87,19 @@ def test_bad_compiler(shared_datadir: Path):
def test_no_compiler(shared_datadir: Path): def test_no_compiler(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pyhidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE) as flat_api: with pyghidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE) as flat_api:
pass pass
def test_no_language_with_compiler(shared_datadir: Path): def test_no_language_with_compiler(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pyhidra.open_program(strings_exe, analyze=False, compiler=TEST_COMPILER) as flat_api: with pyghidra.open_program(strings_exe, analyze=False, compiler=TEST_COMPILER) as flat_api:
pass pass
def test_loader(shared_datadir: Path): def test_loader(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pyhidra.open_program( with pyghidra.open_program(
strings_exe, strings_exe,
analyze=False, analyze=False,
language="DATA:LE:64:default", language="DATA:LE:64:default",
@ -112,7 +112,7 @@ def test_loader(shared_datadir: Path):
def test_invalid_loader(shared_datadir: Path): def test_invalid_loader(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pytest.raises(ValueError): with pytest.raises(ValueError):
with pyhidra.open_program( with pyghidra.open_program(
strings_exe, strings_exe,
analyze=False, analyze=False,
language="DATA:LE:64:default", language="DATA:LE:64:default",
@ -125,7 +125,7 @@ def test_invalid_loader(shared_datadir: Path):
def test_invalid_loader_type(shared_datadir: Path): def test_invalid_loader_type(shared_datadir: Path):
strings_exe = shared_datadir / EXE_NAME strings_exe = shared_datadir / EXE_NAME
with pytest.raises(TypeError): with pytest.raises(TypeError):
with pyhidra.open_program( with pyghidra.open_program(
strings_exe, strings_exe,
analyze=False, analyze=False,
language="DATA:LE:64:default", language="DATA:LE:64:default",
@ -136,7 +136,7 @@ def test_invalid_loader_type(shared_datadir: Path):
def test_no_project(capsys, shared_datadir: Path): def test_no_project(capsys, shared_datadir: Path):
pyhidra.run_script(None, shared_datadir / "projectless_script.py") pyghidra.run_script(None, shared_datadir / "projectless_script.py")
captured = capsys.readouterr() captured = capsys.readouterr()
assert captured.out.rstrip() == "projectless_script executed successfully" assert captured.out.rstrip() == "projectless_script executed successfully"
@ -145,14 +145,14 @@ def test_no_program(capsys, shared_datadir: Path):
script_path = shared_datadir / "programless_script.py" script_path = shared_datadir / "programless_script.py"
project_path = shared_datadir / "programless_ghidra" project_path = shared_datadir / "programless_ghidra"
pyhidra.run_script(None, script_path, project_path, "programless") pyghidra.run_script(None, script_path, project_path, "programless")
captured = capsys.readouterr() captured = capsys.readouterr()
assert captured.out.rstrip() == "programless_script executed successfully" assert captured.out.rstrip() == "programless_script executed successfully"
def test_import_script(capsys, shared_datadir: Path): def test_import_script(capsys, shared_datadir: Path):
script_path = shared_datadir / "import_test_script.py" script_path = shared_datadir / "import_test_script.py"
pyhidra.run_script(None, script_path) pyghidra.run_script(None, script_path)
captured = capsys.readouterr() captured = capsys.readouterr()
assert captured.out.rstrip() == "imported successfully" assert captured.out.rstrip() == "imported successfully"
@ -176,16 +176,16 @@ def test_import_ghidra_base_java_packages():
def wrap_mod(mod): def wrap_mod(mod):
return mod + '_' return mod + '_'
launcher = pyhidra.start() launcher = pyghidra.start()
# Test to ensure _PyhidraImportLoader is last loader # Test to ensure _PyGhidraImportLoader is last loader
assert isinstance(sys.meta_path[-1], pyhidra.launcher._PyhidraImportLoader) assert isinstance(sys.meta_path[-1], pyghidra.launcher._PyGhidraImportLoader)
packages = get_runtime_top_level_java_packages(launcher) packages = get_runtime_top_level_java_packages(launcher)
assert len(packages) > 0 assert len(packages) > 0
# Test full coverage for Java base packages (_JImportLoader or _PyhidraImportLoader) # Test full coverage for Java base packages (_JImportLoader or _PyGhidraImportLoader)
for mod in packages: for mod in packages:
# check spec using standard import machinery "import mod" # check spec using standard import machinery "import mod"
spec = importlib.util.find_spec(mod) spec = importlib.util.find_spec(mod)
@ -195,13 +195,13 @@ def test_import_ghidra_base_java_packages():
assert spec is not None assert spec is not None
assert isinstance(spec.loader, jpype.imports._JImportLoader) or isinstance( assert isinstance(spec.loader, jpype.imports._JImportLoader) or isinstance(
spec.loader, pyhidra.launcher._PyhidraImportLoader) spec.loader, pyghidra.launcher._PyGhidraImportLoader)
# Test all Java base packages are available with '_' # Test all Java base packages are available with '_'
for mod in packages: for mod in packages:
spec_ = importlib.util.find_spec(wrap_mod(mod)) spec_ = importlib.util.find_spec(wrap_mod(mod))
assert spec_ is not None assert spec_ is not None
assert isinstance(spec_.loader, pyhidra.launcher._PyhidraImportLoader) assert isinstance(spec_.loader, pyghidra.launcher._PyGhidraImportLoader)
# Test standard import # Test standard import
import ghidra import ghidra
@ -209,7 +209,7 @@ def test_import_ghidra_base_java_packages():
# Test import with conflict # Test import with conflict
import pdb_ import pdb_
assert isinstance(pdb_.__loader__, pyhidra.launcher._PyhidraImportLoader) assert isinstance(pdb_.__loader__, pyghidra.launcher._PyGhidraImportLoader)
# Test "from" import with conflict # Test "from" import with conflict
from pdb_ import PdbPlugin from pdb_ import PdbPlugin

View File

@ -5,7 +5,7 @@ from pathlib import Path
import typing import typing
import jpype import jpype
import pyhidra import pyghidra
import pytest import pytest
@ -13,8 +13,8 @@ import pytest
pytestmark = pytest.mark.plugin pytestmark = pytest.mark.plugin
SETUP_KEY = "pyhidra.setup" SETUP_KEY = "pyghidra.setup"
PRE_LAUNCH_KEY = "pyhidra.pre_launch" PRE_LAUNCH_KEY = "pyghidra.pre_launch"
NAME_KEY = "names" NAME_KEY = "names"
@ -30,10 +30,10 @@ class PluginTest:
ran_setup = False ran_setup = False
ran_prelaunch = False ran_prelaunch = False
details: pyhidra.ExtensionDetails = None details: pyghidra.ExtensionDetails = None
def __init_subclass__(cls) -> None: def __init_subclass__(cls) -> None:
cls.details = pyhidra.ExtensionDetails( cls.details = pyghidra.ExtensionDetails(
name=cls.__name__, name=cls.__name__,
description="Test Plugin", description="Test Plugin",
author="" author=""
@ -43,7 +43,7 @@ class PluginTest:
_prelaunch = cls.prelaunch _prelaunch = cls.prelaunch
@functools.wraps(_setup) @functools.wraps(_setup)
def setup(launcher: pyhidra.HeadlessPyhidraLauncher): def setup(launcher: pyghidra.HeadlessPyGhidraLauncher):
_setup(launcher) _setup(launcher)
cls.ran_setup = True cls.ran_setup = True
@ -62,7 +62,7 @@ class PluginTest:
@classmethod @classmethod
@abc.abstractmethod @abc.abstractmethod
def setup(cls, launcher: pyhidra.HeadlessPyhidraLauncher): def setup(cls, launcher: pyghidra.HeadlessPyGhidraLauncher):
... ...
@classmethod @classmethod
@ -110,7 +110,7 @@ def with_ghidra():
""" """
_monkey_patch_entry_points() _monkey_patch_entry_points()
try: try:
launcher = pyhidra.HeadlessPyhidraLauncher() launcher = pyghidra.HeadlessPyGhidraLauncher()
launcher.start() launcher.start()
yield # can't yield None yield # can't yield None
finally: finally:
@ -128,29 +128,29 @@ def with_ghidra():
class TestValidPlugin(PluginTest): class TestValidPlugin(PluginTest):
@classmethod @classmethod
def setup(cls, launcher: pyhidra.HeadlessPyhidraLauncher): def setup(cls, launcher: pyghidra.HeadlessPyGhidraLauncher):
source_path = Path(__file__).parent / "data" / "good_plugin" source_path = Path(__file__).parent / "data" / "good_plugin"
launcher.install_plugin(source_path, cls.details) launcher.install_plugin(source_path, cls.details)
@classmethod @classmethod
def prelaunch(cls): def prelaunch(cls):
DummyTestRecognizer = jpype.JClass("ghidra.pyhidra.test.DummyTestRecognizer") DummyTestRecognizer = jpype.JClass("ghidra.pyghidra.test.DummyTestRecognizer")
DummyTestRecognizer.preLaunchInitialized = True DummyTestRecognizer.preLaunchInitialized = True
@classmethod @classmethod
def test_extension_point(cls): def test_extension_point(cls):
from ghidra.app.util.recognizer import Recognizer from ghidra.app.util.recognizer import Recognizer
from ghidra.util.classfinder import ClassSearcher from ghidra.util.classfinder import ClassSearcher
DummyTestRecognizer = jpype.JClass("ghidra.pyhidra.test.DummyTestRecognizer") DummyTestRecognizer = jpype.JClass("ghidra.pyghidra.test.DummyTestRecognizer")
assert DummyTestRecognizer in ClassSearcher.getClasses(Recognizer) assert DummyTestRecognizer in ClassSearcher.getClasses(Recognizer)
class TestBadPlugin(PluginTest): class TestBadPlugin(PluginTest):
launcher: pyhidra.HeadlessPyhidraLauncher = None launcher: pyghidra.HeadlessPyGhidraLauncher = None
@classmethod @classmethod
def setup(cls, launcher: pyhidra.HeadlessPyhidraLauncher): def setup(cls, launcher: pyghidra.HeadlessPyGhidraLauncher):
source_path = Path(__file__).parent / "data" / "bad_plugin" source_path = Path(__file__).parent / "data" / "bad_plugin"
launcher.install_plugin(source_path, cls.details) launcher.install_plugin(source_path, cls.details)
cls.launcher = launcher cls.launcher = launcher

View File

@ -13,11 +13,10 @@
* 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.pyhidra; package ghidra.pyghidra;
import static org.junit.Assert.*; import org.junit.After;
import org.junit.Before;
import org.junit.*;
import ghidra.app.plugin.core.osgi.BundleHost; import ghidra.app.plugin.core.osgi.BundleHost;
import ghidra.app.script.GhidraScriptUtil; import ghidra.app.script.GhidraScriptUtil;
@ -28,7 +27,7 @@ import ghidra.test.TestEnv;
/** /**
* Tests the Python Plugin functionality. * Tests the Python Plugin functionality.
*/ */
public class PyhidraPluginTest extends AbstractGhidraHeadedIntegrationTest { public class PyGhidraPluginTest extends AbstractGhidraHeadedIntegrationTest {
private TestEnv env; private TestEnv env;
@ -37,8 +36,8 @@ public class PyhidraPluginTest extends AbstractGhidraHeadedIntegrationTest {
env = new TestEnv(); env = new TestEnv();
PluginTool tool = env.getTool(); PluginTool tool = env.getTool();
GhidraScriptUtil.initialize(new BundleHost(), null); GhidraScriptUtil.initialize(new BundleHost(), null);
tool.addPlugin(PyhidraPlugin.class.getName()); tool.addPlugin(PyGhidraPlugin.class.getName());
env.getPlugin(PyhidraPlugin.class); env.getPlugin(PyGhidraPlugin.class);
} }
@After @After

View File

@ -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.pyhidra; package ghidra.pyghidra;
import static org.junit.Assert.*; import static org.junit.Assert.*;

View File

@ -1,18 +0,0 @@
package ghidra.pyhidra;
import org.junit.Test;
import ghidra.pyhidra.PythonFieldExposer.ExposedField;
import static org.junit.Assert.assertTrue;
import java.util.Map;;
public class PythonFieldExposerTest {
@Test
public void test() {
Map<String, ExposedField> fields = PythonFieldExposer.getProperties(PyhidraScriptProvider.PyhidraGhidraScript.class);
assertTrue(fields.containsKey("currentProgram"));
}
}

View File

@ -1,240 +0,0 @@
package ghidra.pyhidra.property;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import static org.junit.Assert.assertArrayEquals;
@RunWith(Parameterized.class)
public class PropertyUtilsTest {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return convertData(PropertyUtilsTest.class.getNestMembers());
}
private final Class<?> cls;
public PropertyUtilsTest(String name, Class<?> cls) {
this.cls = cls;
}
private TestResult[] getExpected() {
return Arrays.stream(cls.getAnnotationsByType(ExpectedResult.class))
.map(TestResult::new)
.toArray(TestResult[]::new);
}
@Test
public void test() {
TestResult[] expected = getExpected();
TestResult[] properties = getProperties(cls);
assertArrayEquals(expected, properties);
}
private static TestResult[] getProperties(Class<?> cls) {
return Arrays.stream(PropertyUtils.getProperties(cls))
.map(AbstractJavaProperty.class::cast)
.map(TestResult::new)
.toArray(TestResult[]::new);
}
private static List<Object[]> convertData(Class<?>[] classes) {
List<Object[]> result = new ArrayList<>(classes.length);
for (Class<?> cls : classes) {
if (cls.isRecord() || cls.isAnnotation()) {
continue;
}
result.add(new Object[] { cls.getSimpleName(), cls });
}
return result;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(ExpectedResults.class)
private static @interface ExpectedResult {
String field();
boolean getter();
boolean setter();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
private static @interface ExpectedResults {
ExpectedResult[] value();
}
private static record TestResult(String field, boolean getter, boolean setter) {
TestResult(AbstractJavaProperty<?> property) {
this(property.field, property.hasGetter(), property.hasValidSetter());
}
TestResult(ExpectedResult result) {
this(result.field(), result.getter(), result.setter());
}
}
@ExpectedResult(field = "length", getter = true, setter = false)
public static class TestGetter {
public int getLength() {
return 0;
}
}
@ExpectedResult(field = "length", getter = false, setter = true)
public static class TestSetter {
public void setLength(int i) {
}
}
@ExpectedResult(field = "length", getter = true, setter = true)
public static class TestProperty {
public int getLength() {
return 0;
}
public void setLength(int i) {
}
}
@ExpectedResult(field = "length", getter = true, setter = true)
public static class TestMultiSetter {
public int getLength() {
return 0;
}
public void setLength(int i) {
}
public void setLength(short s) {
}
}
@ExpectedResult(field = "length", getter = true, setter = true)
public static class TestBoxedMultiSetter {
public int getLength() {
return 0;
}
public void setLength(int i) {
}
public void setLength(Integer i) {
}
}
public static class TestMultiSetterNoGetter {
public void setLength(int i) {
}
public void setLength(short s) {
}
}
@ExpectedResult(field = "valid", getter = true, setter = false)
public static class TestIsGetter {
public boolean isValid() {
return true;
}
}
@ExpectedResult(field = "valid", getter = true, setter = true)
public static class TestIsProperty {
public boolean isValid() {
return true;
}
public void setValid(boolean valid) {
}
}
@ExpectedResult(field = "valid", getter = true, setter = false)
public static class TestIsBoxedGetter {
public Boolean isValid() {
return true;
}
}
@ExpectedResult(field = "valid", getter = true, setter = true)
public static class TestIsBoxedProperty {
public Boolean isValid() {
return true;
}
public void setValid(boolean valid) {
}
}
public static class TestBadIsGetter {
public int isValid() {
return 1;
}
}
public static class TestIsGetterName {
public boolean isvalid() {
return true;
}
}
public static class TestBadGetterName {
public int getlength() {
return 0;
}
}
public static class TestBadSetterName {
public void setlength(int i) {
}
}
public static class TestBadIsTooShortName {
public boolean i() {
return true;
}
}
public static class TestBadGetTooShortName {
public int ge() {
return 0;
}
}
public static class TestBadSetTooShortName {
public int se() {
return 0;
}
}
public static class TestBadIsNoName {
public boolean is() {
return true;
}
}
public static class TestBadGetNoName {
public int get() {
return 0;
}
}
public static class TestBadSetNoName {
public int set() {
return 0;
}
}
}

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#---------------------------------------- #----------------------------------------
# Pyhidra launch # PyGhidra launch
#---------------------------------------- #----------------------------------------
# Resolve symbolic link if present and get the directory this script lives in. # Resolve symbolic link if present and get the directory this script lives in.
@ -28,6 +28,6 @@ if [ ! -d "${INSTALL_DIR}/Ghidra" ]; then
INSTALL_DIR="${SCRIPT_DIR}/../../../.." INSTALL_DIR="${SCRIPT_DIR}/../../../.."
fi fi
PYHIDRA_LAUNCHER="${INSTALL_DIR}/Ghidra/Features/Pyhidra/pyhidraLauncher.py" PYGHIDRA_LAUNCHER="${INSTALL_DIR}/Ghidra/Features/PyGhidra/pyghidra_launcher.py"
python3 "${PYHIDRA_LAUNCHER}" "${INSTALL_DIR}" ${DEV_ARG} ${VMARG_LIST} "$@" python3 "${PYGHIDRA_LAUNCHER}" "${INSTALL_DIR}" ${DEV_ARG} ${VMARG_LIST} "$@"

View File

@ -1,4 +1,4 @@
:: Pyhidra launch :: PyGhidra launch
@echo off @echo off
setlocal enabledelayedexpansion setlocal enabledelayedexpansion
@ -32,9 +32,9 @@ if not exist "%INSTALL_DIR%\Ghidra" (
set "INSTALL_DIR=%SCRIPT_DIR%\..\..\..\.." set "INSTALL_DIR=%SCRIPT_DIR%\..\..\..\.."
) )
set "PYHIDRA_LAUNCHER=%INSTALL_DIR%\Ghidra\Features\Pyhidra\pyhidraLauncher.py set "PYGHIDRA_LAUNCHER=%INSTALL_DIR%\Ghidra\Features\PyGhidra\pyghidra_launcher.py
%PYTHON% "%PYHIDRA_LAUNCHER%" "%INSTALL_DIR%" %DEV_ARG% %VMARG_LIST% %* %PYTHON% "%PYGHIDRA_LAUNCHER%" "%INSTALL_DIR%" %DEV_ARG% %VMARG_LIST% %*
:exit1 :exit1
if not %ERRORLEVEL% == 0 ( if not %ERRORLEVEL% == 0 (

View File

@ -53,8 +53,8 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
Map.entry("java.math.BigDecimal", "decimal.Decimal"))); Map.entry("java.math.BigDecimal", "decimal.Decimal")));
// FIXME: list and set aren't automatically converted to java.util.List and java.util.Set :( // FIXME: list and set aren't automatically converted to java.util.List and java.util.Set :(
// if wanted they could be setup to be converted automatically by pyhidra // if wanted they could be setup to be converted automatically by PyGhidra
// however, when passed as a parameter and modified, the original underlyng python container // however, when passed as a parameter and modified, the original underlying python container
// wouldn't be modified. To make it work as expected, a python implementation for // wouldn't be modified. To make it work as expected, a python implementation for
// java.util.List and java.util.Set would need to be created using jpype.JImplements, // java.util.List and java.util.Set would need to be created using jpype.JImplements,
// that would wrap the list/set before passing it to Java instead of copying the contents // that would wrap the list/set before passing it to Java instead of copying the contents

View File

@ -40,7 +40,7 @@ future releases.
<li><a href="#RunServer">Ghidra Server</a></li> <li><a href="#RunServer">Ghidra Server</a></li>
<li><a href="#RunHeadless">Headless (Batch) Mode</a></li> <li><a href="#RunHeadless">Headless (Batch) Mode</a></li>
<li><a href="#RunJar">Single Jar Mode</a></li> <li><a href="#RunJar">Single Jar Mode</a></li>
<li><a href="#RunPyhidra">Pyhidra</a></li> <li><a href="#RunPyGhidra">PyGhidra</a></li>
</ul> </ul>
<li><a href="#Extensions">Extensions</a></li> <li><a href="#Extensions">Extensions</a></li>
<ul> <ul>
@ -102,7 +102,7 @@ Ghidra team if you have a specific need.</p></blockquote>
<li>Python3 (3.9 to 3.12)</li> <li>Python3 (3.9 to 3.12)</li>
<ul> <ul>
<li>Python 3.7 to 3.12 for <a href="#DebuggerPython">Debugger support</a></li> <li>Python 3.7 to 3.12 for <a href="#DebuggerPython">Debugger support</a></li>
<li>Python 3.9 to 3.12 for <a href="#RunPyhidra">Pyhidra support</a></li> <li>Python 3.9 to 3.12 for <a href="#RunPyGhidra">PyGhidra support</a></li>
<li>This is available from <a href="https://python.org">Python.org</a> or most operating system's <li>This is available from <a href="https://python.org">Python.org</a> or most operating system's
app stores or software repositories. For Linux it is recommended that the system's package app stores or software repositories. For Linux it is recommended that the system's package
repository be used to install a suitable version of Python.</li> repository be used to install a suitable version of Python.</li>
@ -445,8 +445,8 @@ another Java application.</p>
<p>A single ghidra.jar file can be created using the <p>A single ghidra.jar file can be created using the
<i>&lt;GhidraInstallDir&gt;</i>/support/buildGhidraJar script.</p> <i>&lt;GhidraInstallDir&gt;</i>/support/buildGhidraJar script.</p>
<h3><a name="RunPyhidra"></a>Pyhidra Mode</h3> <h3><a name="RunPyGhidra"></a>PyGhidra Mode</h3>
<p>Ghidra has integrated the the popular Pyhidra extension to enable native CPython 3 support out of <p>Ghidra has integrated the the popular PyGhidra extension to enable native CPython 3 support out of
the box. To enable this support, Ghidra must be launched from a Python environment using special the box. To enable this support, Ghidra must be launched from a Python environment using special
launch scripts.</p> launch scripts.</p>
<ol> <ol>
@ -454,20 +454,20 @@ launch scripts.</p>
Navigate to <i>&lt;GhidraInstallDir&gt;</i>/support/ Navigate to <i>&lt;GhidraInstallDir&gt;</i>/support/
</li> </li>
<li> <li>
<p>Run <i>pyhidraRun.bat</i> (Windows) or <i>pyhidraRun</i> (Linux or macOS)</p> <p>Run <i>pyghidraRun.bat</i> (Windows) or <i>pyghidraRun</i> (Linux or macOS)</p>
<p>If the <b>pyhidra</b> Python module has not yet been installed, the script will offer to <p>If the <b>pyghidra</b> Python module has not yet been installed, the script will offer to
install it for you, along with its dependencies. If you prefer to install it manually, execute: install it for you, along with its dependencies. If you prefer to install it manually, execute:
<pre>python3 -m pip install --no-index -f <i>&lt;GhidraInstallDir&gt;</i>/Ghidra/Features/Pyhidra/pypkg/dist pyhidra</pre> <pre>python3 -m pip install --no-index -f <i>&lt;GhidraInstallDir&gt;</i>/Ghidra/Features/PyGhidra/pypkg/dist pyghidra</pre>
<b>NOTE: </b>You may also install and run Pyhidra from within a <b>NOTE: </b>You may also install and run PyGhidra from within a
<a href="https://docs.python.org/3/tutorial/venv.html">virtual environment</a> if you desire. <a href="https://docs.python.org/3/tutorial/venv.html">virtual environment</a> if you desire.
<p>If Ghidra failed to launch, see the <a href="#Troubleshooting">Troubleshooting</a> section. <p>If Ghidra failed to launch, see the <a href="#Troubleshooting">Troubleshooting</a> section.
</p> </p>
</li> </li>
</ol> </ol>
<p>Once Pyhidra has been installed, you are free to use it like any other Python module. You may <p>Once PyGhidra has been installed, you are free to use it like any other Python module. You may
import it from other Python scripts, or launch Pyhidra using the <i>pyhidra</i> or <i>pyhidraw</i> import it from other Python scripts, or launch PyGhidra using the <i>pyghidra</i> or <i>pyghidraw</i>
commands. For more information on using Pyhidra, see the commands. For more information on using PyGhidra, see the
<i>&lt;GhidraInstallDir&gt;</i>/Ghidra/Features/Pyhidra/Pyhidra_README.html file.</p> <i>&lt;GhidraInstallDir&gt;</i>/Ghidra/Features/PyGhidra/PyGhidra_README.html file.</p>
<p>(<a href="#top">Back to Top</a>)</p> <p>(<a href="#top">Back to Top</a>)</p>

View File

@ -182,7 +182,7 @@ ext.deps = [
name: "setuptools-68.0.0-py3-none-any.whl", name: "setuptools-68.0.0-py3-none-any.whl",
url: "https://files.pythonhosted.org/packages/c7/42/be1c7bbdd83e1bfb160c94b9cafd8e25efc7400346cf7ccdbdb452c467fa/setuptools-68.0.0-py3-none-any.whl", url: "https://files.pythonhosted.org/packages/c7/42/be1c7bbdd83e1bfb160c94b9cafd8e25efc7400346cf7ccdbdb452c467fa/setuptools-68.0.0-py3-none-any.whl",
sha256: "11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f", sha256: "11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f",
destination: [file("${DEPS_DIR}/Debugger-rmi-trace/"), file("${DEPS_DIR}/Pyhidra/")] destination: [file("${DEPS_DIR}/Debugger-rmi-trace/"), file("${DEPS_DIR}/PyGhidra/")]
], ],
[ [
name: "wheel-0.37.1-py2.py3-none-any.whl", name: "wheel-0.37.1-py2.py3-none-any.whl",
@ -218,79 +218,79 @@ ext.deps = [
name: "JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", name: "JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
url: "https://files.pythonhosted.org/packages/5d/cf/7b89469bcede4b2fd69c2db7d1d61e8759393cfeec46f7b0c84f5006a691/JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", url: "https://files.pythonhosted.org/packages/5d/cf/7b89469bcede4b2fd69c2db7d1d61e8759393cfeec46f7b0c84f5006a691/JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
sha256: "f7aa1469d75f9b310f709b61bb2faa4cef4cbd4d670531ad1d1bb53e29cfda05", sha256: "f7aa1469d75f9b310f709b61bb2faa4cef4cbd4d670531ad1d1bb53e29cfda05",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp39-cp39-win_amd64.whl", name: "JPype1-1.5.0-cp39-cp39-win_amd64.whl",
url: "https://files.pythonhosted.org/packages/b9/fd/d38a8e401b089adce04c48021ddcb366891d1932db2f7653054feb470ae6/JPype1-1.5.0-cp39-cp39-win_amd64.whl", url: "https://files.pythonhosted.org/packages/b9/fd/d38a8e401b089adce04c48021ddcb366891d1932db2f7653054feb470ae6/JPype1-1.5.0-cp39-cp39-win_amd64.whl",
sha256: "6bfdc101c56cab0b6b16e974fd8cbb0b3f7f14178286b8b55413c5d82d5f2bea", sha256: "6bfdc101c56cab0b6b16e974fd8cbb0b3f7f14178286b8b55413c5d82d5f2bea",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", name: "JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl",
url: "https://files.pythonhosted.org/packages/84/9c/80d5edf6d610f82d0658b6402cdf3f8cdd6a7d4f36afb2149da90e0cad47/JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", url: "https://files.pythonhosted.org/packages/84/9c/80d5edf6d610f82d0658b6402cdf3f8cdd6a7d4f36afb2149da90e0cad47/JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl",
sha256: "7b6b1af3f9e0033080e3532c2686a224cd14706f36c14ef36160a2a1db751a17", sha256: "7b6b1af3f9e0033080e3532c2686a224cd14706f36c14ef36160a2a1db751a17",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", name: "JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
url: "https://files.pythonhosted.org/packages/74/98/d6517002355b0585d0e66f7b0283c7f6e2271c898a886e1ebac09836b100/JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", url: "https://files.pythonhosted.org/packages/74/98/d6517002355b0585d0e66f7b0283c7f6e2271c898a886e1ebac09836b100/JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
sha256: "a02b2f05621c119d35f4acc501b4261eeb48a4af7cc13d9afc2e9eb316c4bd29", sha256: "a02b2f05621c119d35f4acc501b4261eeb48a4af7cc13d9afc2e9eb316c4bd29",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp310-cp310-win_amd64.whl", name: "JPype1-1.5.0-cp310-cp310-win_amd64.whl",
url: "https://files.pythonhosted.org/packages/da/5f/253c1c1dba6f7f457b6c3aa2ea9c517287d49764e0ee1042d5818c36e781/JPype1-1.5.0-cp310-cp310-win_amd64.whl", url: "https://files.pythonhosted.org/packages/da/5f/253c1c1dba6f7f457b6c3aa2ea9c517287d49764e0ee1042d5818c36e781/JPype1-1.5.0-cp310-cp310-win_amd64.whl",
sha256: "0b40c76e075d4fed2c83340bb30b7b95bbc396fd370c564c6b608faab00ea4ef", sha256: "0b40c76e075d4fed2c83340bb30b7b95bbc396fd370c564c6b608faab00ea4ef",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", name: "JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",
url: "https://files.pythonhosted.org/packages/98/37/0049866cbfecb879b46d8e9f9b70944624ab17152a282ad5cf60909054ec/JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", url: "https://files.pythonhosted.org/packages/98/37/0049866cbfecb879b46d8e9f9b70944624ab17152a282ad5cf60909054ec/JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",
sha256: "85a31b30b482eaf788b21af421e0750aa0be7758307314178143a76632b0ad04", sha256: "85a31b30b482eaf788b21af421e0750aa0be7758307314178143a76632b0ad04",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", name: "JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
url: "https://files.pythonhosted.org/packages/17/1e/7728ae8fb41e8fbf3a7309f8936d07b0b1622f2860733df0e7ec30b1ce76/JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", url: "https://files.pythonhosted.org/packages/17/1e/7728ae8fb41e8fbf3a7309f8936d07b0b1622f2860733df0e7ec30b1ce76/JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
sha256: "5ef976e0f3b2e9604469f449f30bb2031941a159a0637f4c16adb2c5076f3e81", sha256: "5ef976e0f3b2e9604469f449f30bb2031941a159a0637f4c16adb2c5076f3e81",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp311-cp311-win_amd64.whl", name: "JPype1-1.5.0-cp311-cp311-win_amd64.whl",
url: "https://files.pythonhosted.org/packages/1f/19/144f3a767b563ba5c6d4aa534ea1f3fad9a5067c3917df4458a6e1afe0ef/JPype1-1.5.0-cp311-cp311-win_amd64.whl", url: "https://files.pythonhosted.org/packages/1f/19/144f3a767b563ba5c6d4aa534ea1f3fad9a5067c3917df4458a6e1afe0ef/JPype1-1.5.0-cp311-cp311-win_amd64.whl",
sha256: "2bc987205ff8d2d8e36dfbef05430e0638e85d4fee1166ba58ebfa6f7a67cdf8", sha256: "2bc987205ff8d2d8e36dfbef05430e0638e85d4fee1166ba58ebfa6f7a67cdf8",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl", name: "JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl",
url: "https://files.pythonhosted.org/packages/30/0d/9ac6f0e59427fc5ebf4547c2fdbb38e347b46c2dc20b430490236d037ed8/JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl", url: "https://files.pythonhosted.org/packages/30/0d/9ac6f0e59427fc5ebf4547c2fdbb38e347b46c2dc20b430490236d037ed8/JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl",
sha256: "8714bfaf09d6877160bc7ac97812016ccb09f6d7ba5ea2a9f519178aefcca93f", sha256: "8714bfaf09d6877160bc7ac97812016ccb09f6d7ba5ea2a9f519178aefcca93f",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", name: "JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
url: "https://files.pythonhosted.org/packages/7d/ed/549766039d17550da6e3fa59ed776a021b400324d7766358d3b6e33d8b28/JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", url: "https://files.pythonhosted.org/packages/7d/ed/549766039d17550da6e3fa59ed776a021b400324d7766358d3b6e33d8b28/JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
sha256: "8649b526eccb4047881ad60bdb1974eb71a09cdb7f8bda17c96fdc0f9a3f2d1e", sha256: "8649b526eccb4047881ad60bdb1974eb71a09cdb7f8bda17c96fdc0f9a3f2d1e",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0-cp312-cp312-win_amd64.whl", name: "JPype1-1.5.0-cp312-cp312-win_amd64.whl",
url: "https://files.pythonhosted.org/packages/20/47/9606af72e21703e5fca5e29e5bd5e345506977b6ba492c549648adef47ef/JPype1-1.5.0-cp312-cp312-win_amd64.whl", url: "https://files.pythonhosted.org/packages/20/47/9606af72e21703e5fca5e29e5bd5e345506977b6ba492c549648adef47ef/JPype1-1.5.0-cp312-cp312-win_amd64.whl",
sha256: "9aafc00b00bf8c1b624081e5d4ab87f7752e6c7ee6a141cfc332250b05c6d42f", sha256: "9aafc00b00bf8c1b624081e5d4ab87f7752e6c7ee6a141cfc332250b05c6d42f",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "JPype1-1.5.0.tar.gz", name: "JPype1-1.5.0.tar.gz",
url: "https://files.pythonhosted.org/packages/25/42/8ca50a0e27e3053829545829e7bcba071cbfa4d5d8fd7fc5d1d988f325b1/JPype1-1.5.0.tar.gz", url: "https://files.pythonhosted.org/packages/25/42/8ca50a0e27e3053829545829e7bcba071cbfa4d5d8fd7fc5d1d988f325b1/JPype1-1.5.0.tar.gz",
sha256: "425a6e1966afdd5848b60c2688bcaeb7e40ba504a686f1114589668e0631e878", sha256: "425a6e1966afdd5848b60c2688bcaeb7e40ba504a686f1114589668e0631e878",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
], ],
[ [
name: "packaging-23.2-py3-none-any.whl", name: "packaging-23.2-py3-none-any.whl",
url: "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", url: "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl",
sha256: "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7", sha256: "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7",
destination: file("${DEPS_DIR}/Pyhidra/") destination: file("${DEPS_DIR}/PyGhidra/")
] ]
] ]