diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/kernel-dbgeng.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/kernel-dbgeng.bat index f454e638b0..6d6ae710d8 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/kernel-dbgeng.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/kernel-dbgeng.bat @@ -9,6 +9,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#win_kernel +::@depends Debugger-rmi-trace ::@enum Connection:str Remote Local EXDI ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." :: Use env instead of args, because "all args except first" is terrible to implement in batch diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-attach.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-attach.bat index fa79e59322..25d76146a4 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-attach.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-attach.bat @@ -9,6 +9,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#attach +::@depends Debugger-rmi-trace ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." ::@env OPT_TARGET_PID:int=0 "Process id" "The target process id" ::@env OPT_ATTACH_FLAGS:int=0 "Attach flags" "Attach flags" diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-ext.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-ext.bat index 9f4330ad91..c7da69c98e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-ext.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-ext.bat @@ -10,6 +10,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#ext +::@depends Debugger-rmi-trace ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." :: Use env instead of args, because "all args except first" is terrible to implement in batch ::@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image" diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-trace.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-trace.bat index fa1e4708d9..52bbee6ec7 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-trace.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng-trace.bat @@ -9,6 +9,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#ttd +::@depends Debugger-rmi-trace ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." :: Use env instead of args, because "all args except first" is terrible to implement in batch ::@env OPT_TARGET_TRACE:file="" "Trace (.run)" "The target trace image" diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.bat index f2a17af3e9..66d83627fd 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.bat @@ -10,6 +10,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#local +::@depends Debugger-rmi-trace ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." :: Use env instead of args, because "all args except first" is terrible to implement in batch ::@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image" diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/remote-dbgeng.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/remote-dbgeng.bat index d54cd208d3..927286a3c1 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/remote-dbgeng.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/remote-dbgeng.bat @@ -9,6 +9,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#remote +::@depends Debugger-rmi-trace ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." ::@env OPT_CONNECT_STRING:str="" "Connection" "Connection-string arguments (a la .server)" ::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)." diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/svrcx-dbgeng.bat b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/svrcx-dbgeng.bat index f87bae0516..c8136cf3f0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/svrcx-dbgeng.bat +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/svrcx-dbgeng.bat @@ -10,6 +10,7 @@ ::@menu-group dbgeng ::@icon icon.debugger ::@help dbgeng#svrcx +::@depends Debugger-rmi-trace ::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH." :: Use env instead of args, because "all args except first" is terrible to implement in batch ::@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image" diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py index d7fea8022d..5e19000364 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py index c9b2a112ae..f4c9eb6231 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py index 35377eacb6..61d43273cf 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py index dea35669d4..412522001d 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py index 7e44f339fc..99b878b101 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py index 8748f57a93..657883c4de 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/standalone_listener.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/standalone_listener.py index 33ab3f4854..daa58fb020 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/standalone_listener.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/standalone_listener.py @@ -21,10 +21,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py index 4c8e40a75f..f99f94654b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py @@ -19,10 +19,11 @@ import sys def append_paths(): - sys.path.append("../../../Debugger-rmi-trace/data/support") + sys.path.append( + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") from gmodutils import ghidra_module_pypath - sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace")) - sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng")) + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py index bb2c2bd762..38003dfc0e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py @@ -18,7 +18,7 @@ try: import pybag except Exception as e: from ghidratrace.setuputils import prompt_and_mitigate_dependencies - prompt_and_mitigate_dependencies("Debug/Debugger-agent-dbgeng") + prompt_and_mitigate_dependencies("") # NOTE: libraries must precede EVERYTHING, esp pybag and DbgMod from . import libraries, util, commands, methods, hooks diff --git a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh index f4d1a362b2..ae9ca68063 100755 --- a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh +++ b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh @@ -25,6 +25,7 @@ #@menu-group drgn #@icon icon.debugger #@help drgn#core +#@depends Debugger-rmi-trace #@env OPT_TARGET_IMG:file!="" "Core dump" "The target core dump" export OPT_TARGET_KIND="coredump" diff --git a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/kernel-drgn.sh b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/kernel-drgn.sh index 22d5538b32..cb0e2f7ce9 100755 --- a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/kernel-drgn.sh +++ b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/kernel-drgn.sh @@ -25,6 +25,7 @@ #@menu-group drgn #@icon icon.debugger #@help drgn#linux_kernel +#@depends Debugger-rmi-trace export OPT_TARGET_KIND="kernel" sudo -E drgn ../support/local-drgn.py diff --git a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/local-drgn.sh b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/local-drgn.sh index 432f42c7d4..c28859be13 100755 --- a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/local-drgn.sh +++ b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/local-drgn.sh @@ -25,6 +25,7 @@ #@menu-group drgn #@icon icon.debugger #@help drgn#attach +#@depends Debugger-rmi-trace #@env OPT_TARGET_PID:int=44068 "PID" "The target's process id" export OPT_TARGET_KIND="user" diff --git a/Ghidra/Debug/Debugger-agent-drgn/data/support/local-drgn.py b/Ghidra/Debug/Debugger-agent-drgn/data/support/local-drgn.py index 2d5e97afa8..028dff6495 100644 --- a/Ghidra/Debug/Debugger-agent-drgn/data/support/local-drgn.py +++ b/Ghidra/Debug/Debugger-agent-drgn/data/support/local-drgn.py @@ -22,25 +22,18 @@ import sys import drgn.cli -home = os.getenv('GHIDRA_HOME') -if os.path.isdir(f'{home}/ghidra/.git'): +def append_paths(): sys.path.append( - f'{home}/ghidra/Ghidra/Debug/Debugger-agent-drgn/build/pypkg/src') - sys.path.append( - f'{home}/ghidra/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src') -elif os.path.isdir(f'{home}/.git'): - sys.path.append( - f'{home}/Ghidra/Debug/Debugger-agent-drgn/build/pypkg/src') - sys.path.append( - f'{home}/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src') -else: - sys.path.append( - f'{home}/Ghidra/Debug/Debugger-agent-drgn/pypkg/src') - sys.path.append(f'{home}/Ghidra/Debug/Debugger-rmi-trace/pypkg/src') + f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support") + from gmodutils import ghidra_module_pypath + sys.path.append(ghidra_module_pypath("Debugger-rmi-trace")) + sys.path.append(ghidra_module_pypath()) def main(): + append_paths() + from ghidradrgn import commands as cmd cmd.ghidra_trace_connect(address=os.getenv('GHIDRA_TRACE_RMI_ADDR')) cmd.ghidra_trace_create(start_trace=True) @@ -49,9 +42,7 @@ def main(): cmd.ghidra_trace_txcommit() cmd.ghidra_trace_activate() drgn.cli.run_interactive(cmd.prog) - + if __name__ == '__main__': main() - - diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.ps1 b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.ps1 index 3b43315a3c..dae154df94 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.ps1 +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.ps1 @@ -10,6 +10,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#local +#@depends Debugger-rmi-trace #@enum StartCmd:str run start starti #@enum Endian:str auto big little #@arg :file "Image" "The target binary executable image" @@ -21,8 +22,8 @@ . ..\support\gdbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathGdb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Gdb-Usermode-Args ` diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.sh index b4a922456d..c2945d3f4c 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-gdb.sh @@ -26,6 +26,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#local +#@depends Debugger-rmi-trace #@enum StartCmd:str run start starti #@enum Endian:str auto big little #@arg :file "Image" "The target binary executable image, empty for no target" @@ -39,8 +40,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-rr.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-rr.sh index 8c5a256204..ca8684b05a 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-rr.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/local-rr.sh @@ -25,6 +25,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#rr +#@depends Debugger-rmi-trace #@enum StartCmd:str run start starti #@enum Endian:str auto big little #@arg :file "Trace Dir" "The target trace directory (e.g. .local/share/rr/trace)" @@ -36,8 +37,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_trace="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh index 2837b9a080..c43a4b159f 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh @@ -27,6 +27,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#qemu +#@depends Debugger-rmi-trace #@enum Endian:str auto big little #@arg :file! "Image" "The target binary executable image" #@args "Arguments" "Command-line arguments to pass to the target" @@ -42,8 +43,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.ps1 b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.ps1 index 299d93a1a3..78febcb6b8 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.ps1 +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.ps1 @@ -11,6 +11,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#qemu +#@depends Debugger-rmi-trace #@enum Endian:str auto big little #@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image" #@env GHIDRA_LANG_EXTTOOL_qemu_system:file="" "QEMU command" "The path to qemu-system for the target architecture." @@ -23,8 +24,8 @@ . ..\support\gdbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathGdb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH" $qemuargs = @("`"$Env:GHIDRA_LANG_EXTTOOL_qemu_system`"") diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.sh index 82515d32ee..e9b490bbf9 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-sys-gdb.sh @@ -27,6 +27,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#qemu +#@depends Debugger-rmi-trace #@enum Endian:str auto big little #@arg :file! "Image" "The target binary executable image" #@env GHIDRA_LANG_EXTTOOL_qemu_system:file="" "QEMU command" "The path to qemu-system for the target architecture." @@ -41,8 +42,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.ps1 b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.ps1 index fab6f3cc16..bdb3eb3125 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.ps1 +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.ps1 @@ -10,6 +10,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#remote +#@depends Debugger-rmi-trace #@enum TargetType:str remote extended-remote #@enum Endian:str auto big little #@arg :file "Image" "The target binary executable image (a copy on the local system)" @@ -22,8 +23,8 @@ . ..\support\gdbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathGdb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Gdb-Remote-Args ` diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.sh index 703701afc8..2378da4e75 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/remote-gdb.sh @@ -26,6 +26,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#remote +#@depends Debugger-rmi-trace #@enum TargetType:str remote extended-remote #@enum Endian:str auto big little #@arg :file "Image" "The target binary executable image (a copy on the local system)" @@ -38,8 +39,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.ps1 b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.ps1 index cc6474cde5..ba4fbd1fbe 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.ps1 +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.ps1 @@ -1,4 +1,3 @@ -#@timeout 60000 #@title gdb via ssh #@image-opt arg:1 #@desc @@ -11,6 +10,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#ssh +#@depends Debugger-rmi-trace #@enum StartCmd:str run start starti #@enum Endian:str auto big little #@arg :str "Image" "The target binary executable image on the remote system" @@ -61,7 +61,7 @@ finished, try launching again. if ($answer) { Write-Host "Copying Wheels to $Env:OPT_HOST" - Mitigate-Scp-PyModules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-gdb" + Mitigate-Scp-PyModules "Debugger-rmi-trace" "" Write-Host "Installing Wheels into GDB's embedded Python" $arglist = Compute-Gdb-PipInstall-Args "'-f'" "os.environ['HOME']" "'ghidragdb>=$version'" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh index 070feab61d..8befb88948 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -#@timeout 60000 #@title gdb via ssh #@image-opt arg:1 #@desc @@ -27,6 +26,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#ssh +#@depends Debugger-rmi-trace #@enum StartCmd:str run start starti #@enum Endian:str auto big little #@arg :str "Image" "The target binary executable image on the remote system" @@ -93,7 +93,7 @@ finished, try launching again. " "Would you like to install 'ghidragdb>=$version'?"; then echo "Copying Wheels to $OPT_HOST" - mitigate-scp-pymodules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-gdb" + mitigate-scp-pymodules "Debugger-rmi-trace" "" echo "Installing Wheels into GDB's embedded Python" do-installation diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.ps1 b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.ps1 index 12c5b08060..41b7c0dcff 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.ps1 +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.ps1 @@ -1,4 +1,3 @@ -#@timeout 60000 #@title gdb + gdbserver via ssh #@image-opt arg:1 #@desc @@ -11,6 +10,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#gdbserver_ssh +#@depends Debugger-rmi-trace #@enum Endian:str auto big little #@arg :str! "Image" "The target binary executable image on the remote system" #@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target" @@ -25,8 +25,8 @@ . ..\support\gdbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathGdb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Gdb-Remote-Args ` diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.sh index 978a5a016e..1692276674 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdbserver.sh @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -#@timeout 60000 #@title gdb + gdbserver via ssh #@image-opt arg:1 #@desc @@ -27,6 +26,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#gdbserver_ssh +#@depends Debugger-rmi-trace #@enum Endian:str auto big little #@arg :str! "Image" "The target binary executable image on the remote system" #@args "Arguments" "Command-line arguments to pass to the target" @@ -41,8 +41,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/wine-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/wine-gdb.sh index af4e57e470..d7a8532595 100755 --- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/wine-gdb.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/wine-gdb.sh @@ -26,6 +26,7 @@ #@menu-group gdb #@icon icon.debugger #@help gdb#wine +#@depends Debugger-rmi-trace #@enum Endian:str auto big little #@arg :file! "Image" "The target binary executable image" #@args "Arguments" "Command-line arguments to pass to the target" @@ -39,8 +40,8 @@ . ../support/gdbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathGdb=$(ghidra-module-pypath) export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.ps1 b/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.ps1 index 32f8962900..254920af23 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.ps1 +++ b/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.ps1 @@ -1,5 +1,5 @@ -. ..\..\..\Debugger-rmi-trace\data\support\setuputils.ps1 +. $Env:MODULE_Debugger_rmi_trace_HOME\data\support\setuputils.ps1 function Add-Gdb-Init-Args { param([ref]$ArgList) @@ -48,7 +48,7 @@ function Add-Gdb-Tail-Args { param([ref]$ArgList) $ArgList.Value+=("-ex", "`"set confirm on`"") - $ArgList.Value+=("-ex", "`"set pagination on`"") +# $ArgList.Value+=("-ex", "`"set pagination on`"") } function Compute-Gdb-Usermode-Args { diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.sh b/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.sh index d2bc3fc3d3..e449b890b6 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.sh +++ b/Ghidra/Debug/Debugger-agent-gdb/data/support/gdbsetuputils.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -. ../../../Debugger-rmi-trace/data/support/setuputils.sh +. $MODULE_Debugger_rmi_trace_HOME/data/support/setuputils.sh add-gdb-init-args() { args+=(-q) @@ -64,7 +64,7 @@ add-gdb-start-if-image() { add-gdb-tail-args() { args+=(-ex "set confirm on") - args+=(-ex "set pagination on") +# args+=(-ex "set pagination on") } compute-gdb-usermode-args() { diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.ps1 b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.ps1 index 4cb31d104b..b0127c7bf6 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.ps1 +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.ps1 @@ -10,6 +10,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#android +#@depends Debugger-rmi-trace #@enum StartCmd:str "process launch" "process launch --stop-at-entry" #@arg :file "Image" "The target binary executable image" #@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target" @@ -21,8 +22,8 @@ . ..\support\lldbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathLldb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Lldb-Platform-Args ` diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.sh index daf34d3716..8b1f6ea9d0 100755 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.sh +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/android-lldb.sh @@ -26,6 +26,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#android +#@depends Debugger-rmi-trace #@enum StartCmd:str "process launch" "process launch --stop-at-entry" #@arg :file "Image" "The target binary executable image" #@args "Arguments" "Command-line arguments to pass to the target" @@ -37,8 +38,8 @@ . ../support/lldbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathLldb=$(ghidra-module-pypath) export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.ps1 b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.ps1 index faf22b61eb..77c4e0a2d6 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.ps1 +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.ps1 @@ -9,14 +9,15 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#macos_kernel +#@depends Debugger-rmi-trace #@env OPT_HOST:str="localhost" "Host" "The hostname of the target" #@env OPT_ARCH:str="" "Architecture" "Target architecture override" #@env OPT_LLDB_PATH:file="lldb" "lldb command" "The path to lldb on the local system. Omit the full path to resolve using the system PATH." . ..\support\lldbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathLldb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Lldb-Remote-Args ` diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.sh index b92a45325c..a72176ac55 100755 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.sh +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/kernel-lldb.sh @@ -25,14 +25,15 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#macos_kernel +#@depends Debugger-rmi-trace #@env OPT_HOST:str="localhost" "Host" "The hostname of the target" #@env OPT_ARCH:str="" "Architecture" "Target architecture override" #@env OPT_LLDB_PATH:file="lldb" "lldb command" "The path to lldb on the local system. Omit the full path to resolve using the system PATH." . ../support/lldbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathLldb=$(ghidra-module-pypath) export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH function launch-lldb() { diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.ps1 b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.ps1 index 51ce6b9bd7..2a597bd85f 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.ps1 +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.ps1 @@ -10,6 +10,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#local +#@depends Debugger-rmi-trace #@enum StartCmd:str "process launch" "process launch --stop-at-entry" #@arg :file "Image" "The target binary executable image" #@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target" @@ -18,8 +19,8 @@ . ..\support\lldbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathLldb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Lldb-Usermode-Args ` diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.sh index 4e98d7c489..b9715b2b5b 100755 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.sh +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/local-lldb.sh @@ -26,6 +26,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#local +#@depends Debugger-rmi-trace #@enum StartCmd:str "process launch" "process launch --stop-at-entry" #@arg :file "Image" "The target binary executable image" #@args "Arguments" "Command-line arguments to pass to the target" @@ -36,8 +37,8 @@ . ../support/lldbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathLldb=$(ghidra-module-pypath) export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.ps1 b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.ps1 index a4fd41666d..c5bb55f90d 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.ps1 +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.ps1 @@ -10,6 +10,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#remote +#@depends Debugger-rmi-trace #@arg :file "Image" "The target binary executable image (a copy on the local system)" #@env OPT_HOST:str="localhost" "Host" "The hostname of the target" #@env OPT_PORT:str="9999" "Port" "The host's listening port" @@ -18,8 +19,8 @@ . ..\support\lldbsetuputils.ps1 -$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace" -$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb" +$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace" +$pypathLldb = Ghidra-Module-PyPath $Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH" $arglist = Compute-Lldb-Remote-Args ` diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.sh index 8994d60684..08e7c307d6 100755 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.sh +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/remote-lldb.sh @@ -26,6 +26,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#remote +#@depends Debugger-rmi-trace #@arg :file "Image" "The target binary executable image (a copy on the local system)" #@env OPT_HOST:str="localhost" "Host" "The hostname of the target" #@env OPT_PORT:str="9999" "Port" "The host's listening port" @@ -34,8 +35,8 @@ . ../support/lldbsetuputils.sh -pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace") -pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb") +pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace") +pypathLldb=$(ghidra-module-pypath) export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH target_image="$1" diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.ps1 b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.ps1 index 4ddc7bf771..bc8854d173 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.ps1 +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.ps1 @@ -1,4 +1,3 @@ -#@timeout 60000 #@title lldb via ssh #@image-opt arg:1 #@desc @@ -11,6 +10,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#ssh +#@depends Debugger-rmi-trace #@enum StartCmd:str "process launch" "process launch --stop-at-entry" #@enum Endian:str auto big little #@arg :str "Image" "The target binary executable image on the remote system" @@ -60,7 +60,7 @@ finished, try launching again. if ($answer) { Write-Host "Copying Wheels to $Env:OPT_HOST" - Mitigate-Scp-PyModules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-lldb" + Mitigate-Scp-PyModules "Debugger-rmi-trace" "" Write-Host "Installing Wheels into LLDB's embedded Python" $arglist = Compute-Lldb-PipInstall-Args "'-f'" "os.environ['HOME']" "'ghidralldb>=$version'" diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh index 48a1b033fd..65e59634a0 100755 --- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh +++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -#@timeout 60000 #@title lldb via ssh #@image-opt arg:1 #@desc @@ -27,6 +26,7 @@ #@menu-group lldb #@icon icon.debugger #@help lldb#ssh +#@depends Debugger-rmi-trace #@enum StartCmd:str "process launch" "process launch --stop-at-entry" #@enum Endian:str auto big little #@arg :str "Image" "The target binary executable image on the remote system" @@ -92,7 +92,7 @@ finished, try launching again. " "Would you like to install 'ghidralldb>=$version'?"; then echo "Copying Wheels to $OPT_HOST" - mitigate-scp-pymodules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-lldb" + mitigate-scp-pymodules "Debugger-rmi-trace" "" echo "Installing Wheels into LLDB's embedded Python" do-installation diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.ps1 b/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.ps1 index f83e8d42e4..387af9d972 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.ps1 +++ b/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.ps1 @@ -1,5 +1,5 @@ -. ..\..\..\Debugger-rmi-trace\data\support\setuputils.ps1 +. $Env:MODULE_Debugger_rmi_trace_HOME\data\support\setuputils.ps1 function Add-Lldb-Init-Args { param([ref]$ArgList) diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.sh b/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.sh index 9a68e26066..a05a4663c0 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.sh +++ b/Ghidra/Debug/Debugger-agent-lldb/data/support/lldbsetuputils.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -. ../../../Debugger-rmi-trace/data/support/setuputils.sh +. $MODULE_Debugger_rmi_trace_HOME/data/support/setuputils.sh add-lldb-init-args() { args+=(-o "version") diff --git a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/JavaTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/JavaTraceRmiLaunchOffer.java index 170736ff31..74b3e89f09 100644 --- a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/JavaTraceRmiLaunchOffer.java +++ b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/JavaTraceRmiLaunchOffer.java @@ -86,8 +86,9 @@ public class JavaTraceRmiLaunchOffer extends AbstractScriptTraceRmiLaunchOffer { } @Override - protected void launchBackEnd(TaskMonitor monitor, Map sessions, - Map> args, SocketAddress address) throws Exception { + protected TraceRmiBackEnd launchBackEnd(TaskMonitor monitor, + Map sessions, Map> args, + SocketAddress address) throws Exception { List commandLine = new ArrayList<>(); Map env = new HashMap<>(System.getenv()); prepareSubprocess(commandLine, env, args, address); @@ -101,18 +102,28 @@ public class JavaTraceRmiLaunchOffer extends AbstractScriptTraceRmiLaunchOffer { sessions.put(ns.name(), ns); } + TraceRmiBackEnd result = new TraceRmiBackEnd(); if (hasKeyReally(env, "OPT_JSHELL_PATH")) { String classPath = computeClassPath(env); commandLine.add(0, "--startup"); commandLine.add(0, "--class-path=" + classPath); commandLine.add(0, env.get("OPT_JSHELL_PATH")); - sessions.put("Shell", - runInTerminal(commandLine, env, script.getParentFile(), sessions.values())); + PtyTerminalSession session = + runInTerminal(commandLine, env, script.getParentFile(), sessions.values()); + sessions.put("Shell", session); + session.terminal().addTerminalListener(result); } else { - JdiClientThread thread = new JdiClientThread(env); + JdiClientThread thread = new JdiClientThread(env) { + @Override + public void run() { + super.run(); + result.terminated(0); + } + }; thread.start(); } + return result; } private String computeClassPath(Map env) { diff --git a/Ghidra/Debug/Debugger-rmi-trace/data/debugger-launchers/raw-python3.sh b/Ghidra/Debug/Debugger-rmi-trace/data/debugger-launchers/raw-python3.sh index 26b0e36d65..4424c40a53 100755 --- a/Ghidra/Debug/Debugger-rmi-trace/data/debugger-launchers/raw-python3.sh +++ b/Ghidra/Debug/Debugger-rmi-trace/data/debugger-launchers/raw-python3.sh @@ -30,14 +30,9 @@ #@env OPT_LANG:str="DATA:LE:64:default" "Ghidra Language" "The Ghidra LanguageID for the trace" #@env OPT_COMP:str="pointer64" "Ghidra Compiler" "The Ghidra CompilerSpecID for the trace" -if [ -d ${GHIDRA_HOME}/ghidra/.git ] -then - export PYTHONPATH=$GHIDRA_HOME/ghidra/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH -elif [ -d ${GHIDRA_HOME}/.git ] -then - export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH -else - export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/pypkg/src:$PYTHONPATH -fi +. ../support/setuputils.sh + +pypathTrace=$(ghidra-module-pypath) +export PYTHONPATH=$pypathTrace:$PYTHONPATH "$OPT_PYTHON_EXE" -i ../support/raw-python3.py diff --git a/Ghidra/Debug/Debugger-rmi-trace/data/support/gmodutils.py b/Ghidra/Debug/Debugger-rmi-trace/data/support/gmodutils.py index 3bc33646a2..8712957bd3 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/data/support/gmodutils.py +++ b/Ghidra/Debug/Debugger-rmi-trace/data/support/gmodutils.py @@ -28,19 +28,17 @@ This file CANNOT be assumed to be available on a remote target. For that, consider ghidratrace.setuputils. """ import os - -home = os.getenv('GHIDRA_HOME') +from typing import Optional -def ghidra_module_pypath(name: str) -> str: - installed = f'{home}/Ghidra/{name}/pypkg/src' +def ghidra_module_pypath(name: Optional[str]=None) -> str: + mod_home_name = 'MODULE_HOME' if name is None else f'MODULE_{name.replace("-","_")}_HOME' + mod_home = os.getenv(mod_home_name) + installed = f'{mod_home}/pypkg/src' if os.path.isdir(installed): return installed - dev1 = f'{home}/Ghidra/{name}/build/pypkg/src' - if os.path.isdir(dev1): - return dev1 - dev2 = f'{home}/ghidra/Ghidra/{name}/build/pypkg/src' - if os.path.isdir(dev2): - return dev2 + dev = f'{mod_home}/build/pypkg/src' + if os.path.isdir(dev): + return dev raise Exception( f"Cannot find Python source for {name}. Try gradle assemblePyPackage?") diff --git a/Ghidra/Debug/Debugger-rmi-trace/data/support/raw-python3.py b/Ghidra/Debug/Debugger-rmi-trace/data/support/raw-python3.py index db0f8f2bdc..2cfde98d99 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/data/support/raw-python3.py +++ b/Ghidra/Debug/Debugger-rmi-trace/data/support/raw-python3.py @@ -1,17 +1,17 @@ ## ### -# IP: GHIDRA -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# IP: GHIDRA +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. ## from concurrent.futures import ThreadPoolExecutor import os @@ -33,4 +33,4 @@ client = Client( print(f"Connected to {client.description} at {host}:{port}") trace = client.create_trace("noname", os.getenv( - "OPT_LANG"), os.getenv("OPT_COMP")) + "OPT_LANG"), os.getenv("OPT_COMP"), extra=None) diff --git a/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.ps1 b/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.ps1 index b4e050f88d..54dfc552fc 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.ps1 +++ b/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.ps1 @@ -1,11 +1,7 @@ function Find-App-Properties { - [IO.FileInfo] $simple = "$Env:GHIDRA_HOME\Ghidra\applications.properties" - if ($simple.Exists) { - return $simple - } - [IO.FileInfo] $dev2 = "$Env:GHIDRA_HOME\ghidra\Ghidra\application.properties" - if ($dev2.Exists) { - return $dev2 + [IO.FileInfo] $props = "$Env:GHIDRA_HOME\application.properties" + if ($props.Exists) { + return $props } throw "Cannot find application.properties" } @@ -17,33 +13,39 @@ function Get-Ghidra-Version { } function Ghidra-Module-PyPath { - [IO.DirectoryInfo] $installed = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\pypkg\src" + if ($args.Count -eq 0 -or $args[0] -eq "") { + $modhomename = 'MODULE_HOME' + } else { + $modhomename = "MODULE_$($args[0])_HOME" -replace '-', '_' + } + $modhomeitem = Get-ChildItem Env:$modhomename + $modhome = $modhomeitem.Value + [IO.DirectoryInfo] $installed = "$modhome\pypkg\src" if ($installed.Exists) { return "$installed" } - [IO.DirectoryInfo] $dev1 = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\build\pypkg\src" - if ($dev1.Exists) { - return "$dev1" - } - [IO.DirectoryInfo] $dev2 = "$Env:GHIDRA_HOME\ghidra\Ghidra\$($args[0])\build\pypkg\src" - if ($dev2.Exists) { - return "$dev2" + [IO.DirectoryInfo] $dev = "$modhome\build\pypkg\src" + if ($dev.Exists) { + return "$dev" } throw "Cannot find Python source for $($args[0]). Try gradle assemblePyPackage?" } function Ghidra-Module-PyDist { - [IO.DirectoryInfo] $installed = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\pypkg\dist" + if ($args.Count -eq 0 -or $args[0] -eq "") { + $modhomename = 'MODULE_HOME' + } else { + $modhomename = "MODULE_$($args[0])_HOME" -replace '-', '_' + } + $modhomeitem = Get-ChildItem Env:$modhomename + $modhome = $modhomeitem.Value + [IO.DirectoryInfo] $installed = "$modhome\pypkg\dist" if ($installed.Exists) { return "$installed" } - [IO.DirectoryInfo] $dev1 = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\build\pypkg\dist" - if ($dev1.Exists) { - return "$dev1" - } - [IO.DirectoryInfo] $dev2 = "$Env:GHIDRA_HOME\ghidra\Ghidra\$($args[0])\build\pypkg\dist" - if ($dev2.Exists) { - return "$dev2" + [IO.DirectoryInfo] $dev = "$modhome\build\pypkg\dist" + if ($dev.Exists) { + return "$dev" } throw "Cannot find Python package for $($args[0]). Try gradle buildPyPackage?" } diff --git a/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh b/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh index 747b0d453e..4ea39f702d 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh +++ b/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh @@ -14,14 +14,9 @@ # limitations under the License. ## find-app-properties() { - local simple="$GHIDRA_HOME/Ghidra/application.properties" - if [ -f "$simple" ]; then - echo $simple - return 0 - fi - local dev2="$GHIDRA_HOME/ghidra/Ghidra/application.properties" - if [ -f "$dev2" ]; then - echo $dev2 + local props="$GHIDRA_HOME/application.properties" + if [ -f "$props" ]; then + echo $props return 0 fi echo >&2 "Cannot find application.properties" @@ -45,19 +40,21 @@ get-ghidra-version() { } ghidra-module-pypath() { - installed="$GHIDRA_HOME/Ghidra/$1/pypkg/src" + local modhomename + if [ -z "$1" ] || [ "$1" == "" ]; then + modhomename='MODULE_HOME' + else + modhomename="MODULE_${1//-/_}_HOME" + fi + local modhome="${!modhomename}" + local installed="$modhome/pypkg/src" if [ -d "$installed" ]; then echo $installed return 0 fi - dev1="$GHIDRA_HOME/Ghidra/$1/build/pypkg/src" - if [ -d "$dev1" ]; then - echo $dev1 - return 0 - fi - dev2="$GHIDRA_HOME/ghidra/Ghidra/$1/build/pypkg/src" - if [ -d "$dev2" ]; then - echo $dev2 + local dev="$modhome/build/pypkg/src" + if [ -d "$dev" ]; then + echo $dev return 0 fi echo >&2 "Cannot find Python source for $1. Try gradle assemblePyPackage?" @@ -65,19 +62,21 @@ ghidra-module-pypath() { } ghidra-module-pydist() { - installed="$GHIDRA_HOME/Ghidra/$1/pypkg/dist" + local modhomename + if [ -z "$1" ] || [ "$1" == "" ]; then + modhomename='MODULE_HOME' + else + modhomename="MODULE_${1//-/_}_HOME" + fi + local modhome="${!modhomename}" + local installed="$modhome/pypkg/dist" if [ -d "$installed" ]; then echo $installed return 0 fi - dev1="$GHIDRA_HOME/Ghidra/$1/build/pypkg/dist" - if [ -d "$dev1" ]; then - echo $dev1 - return 0 - fi - dev2="$GHIDRA_HOME/ghidra/Ghidra/$1/build/pypkg/dist" - if [ -d "$dev2" ]; then - echo $dev2 + local dev="$modhome/build/pypkg/dist" + if [ -d "$dev" ]; then + echo $dev return 0 fi echo >&2 "Cannot find Python package for $1. Try gradle buildPyPackage?" diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java index d3851415aa..8d49c75436 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java @@ -98,12 +98,13 @@ public abstract class AbstractScriptTraceRmiLaunchOffer extends AbstractTraceRmi protected void prepareSubprocess(List commandLine, Map env, Map> args, SocketAddress address) { ScriptAttributesParser.processArguments(commandLine, env, script, attrs.parameters(), args, - address); + attrs.dependencies(), address); } @Override - protected void launchBackEnd(TaskMonitor monitor, Map sessions, - Map> args, SocketAddress address) throws Exception { + protected TraceRmiBackEnd launchBackEnd(TaskMonitor monitor, + Map sessions, Map> args, + SocketAddress address) throws Exception { List commandLine = new ArrayList<>(); Map env = new HashMap<>(System.getenv()); prepareSubprocess(commandLine, env, args, address); @@ -112,7 +113,8 @@ public abstract class AbstractScriptTraceRmiLaunchOffer extends AbstractTraceRmi if (imageParameter != null) { ValStr valStr = args.get(imageParameter.name()); if (valStr != null && !valStr.str().contains(program.getName())) { - Msg.warn(this, "Possible mismatch for " + program.getName() + ": " + valStr.str()); + Msg.warn(this, + "Possible mismatch for " + program.getName() + ": " + valStr.str()); } } env.put("GHIDRA_LANGUAGE_ID", program.getLanguageID().toString()); @@ -127,8 +129,12 @@ public abstract class AbstractScriptTraceRmiLaunchOffer extends AbstractTraceRmi sessions.put(ent.getKey(), ns); } - sessions.put("Shell", - runInTerminal(commandLine, env, script.getParentFile(), sessions.values())); + PtyTerminalSession session = + runInTerminal(commandLine, env, script.getParentFile(), sessions.values()); + sessions.put("Shell", session); + TraceRmiBackEnd result = new TraceRmiBackEnd(); + session.terminal().addTerminalListener(result); + return result; } @Override diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java index 63f3015f45..d002477d46 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java @@ -17,16 +17,18 @@ package ghidra.app.plugin.core.debug.gui.tracermi.launcher; import java.io.File; import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; +import java.net.*; import java.nio.charset.Charset; import java.nio.file.Paths; +import java.time.Duration; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.*; import javax.swing.Icon; +import org.apache.commons.lang3.exception.ExceptionUtils; + import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.action.ByModuleAutoMapSpec; import ghidra.app.plugin.core.debug.gui.tracermi.launcher.LaunchFailureDialog.ErrPromptResponse; @@ -59,12 +61,14 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer public static final String PREFIX_PARAM_EXTTOOL = "env:GHIDRA_LANG_EXTTOOL_"; public static final int DEFAULT_TIMEOUT_MILLIS = 10000; + public static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = + (int) Duration.ofMinutes(10).toMillis(); protected record PtyTerminalSession(Terminal terminal, Pty pty, PtySession session, Thread waiter) implements TerminalSession { @Override public void terminate() throws IOException { - terminal.terminated(); + terminal.terminated(-1); session.destroyForcibly(); pty.close(); waiter.interrupt(); @@ -80,7 +84,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer implements TerminalSession { @Override public void terminate() throws IOException { - terminal.terminated(); + terminal.terminated(-1); pty.close(); } @@ -135,7 +139,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer } protected int getConnectionTimeoutMillis() { - return getTimeoutMillis(); + return DEFAULT_CONNECTION_TIMEOUT_MILLIS; } @Override @@ -415,8 +419,9 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer param.display())); } catch (Exception e) { - Msg.warn(this, "Could not load saved launcher arg '%s' (%s) - %s".formatted(param.name(), - param.display(), e.getMessage())); + Msg.warn(this, + "Could not load saved launcher arg '%s' (%s) - %s".formatted(param.name(), + param.display(), e.getMessage())); } } return args; @@ -490,8 +495,8 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer Thread waiter = new Thread(() -> { try { - session.waitExited(); - terminal.terminated(); + int exitcode = session.waitExited(); + terminal.terminated(exitcode); pty.close(); for (TerminalSession ss : subordinates) { @@ -538,10 +543,43 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer return terminalSession; } - protected abstract void launchBackEnd(TaskMonitor monitor, + protected abstract TraceRmiBackEnd launchBackEnd(TaskMonitor monitor, Map sessions, Map> args, SocketAddress address) throws Exception; + protected TraceRmiHandler acceptOrSessionEnds(DefaultTraceRmiAcceptor acceptor, + TraceRmiBackEnd backEnd) + throws SocketException, CancelledException, EarlyTerminationException { + acceptor.setTimeout(getConnectionTimeoutMillis()); + CompletableFuture futureConnection = CompletableFuture.supplyAsync(() -> { + try { + return acceptor.accept(); + } + catch (CancelledException | IOException e) { + return ExceptionUtils.rethrow(e); + } + }); + // Because of accept timeout, should be a finite wait + try { + CompletableFuture.anyOf(backEnd, futureConnection).get(); + if (backEnd.isDone()) { + throw new EarlyTerminationException( + "The back-end exited (code=%s) before receiving a connection" + .formatted(backEnd.getNow(null))); + } + return futureConnection.get(); + } + catch (ExecutionException e) { + switch (e.getCause()) { + case CancelledException ce -> throw ce; + default -> throw new AssertionError(e); + } + } + catch (InterruptedException e) { + throw new AssertionError(e); + } + } + public static class NoStaticMappingException extends Exception { public NoStaticMappingException(String message) { super(message); @@ -553,6 +591,17 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer } } + public static class EarlyTerminationException extends Exception { + public EarlyTerminationException(String message) { + super(message); + } + + @Override + public String toString() { + return getMessage(); + } + } + protected AutoMapSpec getAutoMapSpec() { DebuggerAutoMappingService auto = tool.getService(DebuggerAutoMappingService.class); return auto == null ? ByModuleAutoMapSpec.instance() : auto.getAutoMapSpec(); @@ -660,12 +709,16 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer monitor.increment(); monitor.setMessage("Launching back-end"); - launchBackEnd(monitor, sessions, args, acceptor.getAddress()); + TraceRmiBackEnd backEnd = + launchBackEnd(monitor, sessions, args, acceptor.getAddress()); monitor.increment(); + /** + * LATER: We might be able to disable timeouts, now that we know if the back-end + * terminates early + */ monitor.setMessage("Waiting for connection"); - acceptor.setTimeout(getConnectionTimeoutMillis()); - connection = acceptor.accept(); + connection = acceptOrSessionEnds(acceptor, backEnd); connection.registerTerminals(sessions.values()); monitor.increment(); diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptAttributesParser.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptAttributesParser.java index d449a2d1c9..6c2c46d6c1 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptAttributesParser.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptAttributesParser.java @@ -25,6 +25,7 @@ import java.util.Map.Entry; import javax.swing.Icon; +import generic.jar.ResourceFile; import generic.theme.GIcon; import generic.theme.Gui; import ghidra.debug.api.ValStr; @@ -40,12 +41,15 @@ import ghidra.util.*; */ public abstract class ScriptAttributesParser { public static final String ENV_GHIDRA_HOME = "GHIDRA_HOME"; + public static final String ENV_MODULE_HOME = "MODULE_HOME"; + public static final String ENV_MODULE_HOME_PAT = "MODULE_%s_HOME"; public static final String ENV_GHIDRA_TRACE_RMI_ADDR = "GHIDRA_TRACE_RMI_ADDR"; public static final String ENV_GHIDRA_TRACE_RMI_HOST = "GHIDRA_TRACE_RMI_HOST"; public static final String ENV_GHIDRA_TRACE_RMI_PORT = "GHIDRA_TRACE_RMI_PORT"; public static final String AT_ARG = "@arg"; public static final String AT_ARGS = "@args"; + public static final String AT_DEPENDS = "@depends"; public static final String AT_DESC = "@desc"; public static final String AT_ENUM = "@enum"; public static final String AT_ENV = "@env"; @@ -341,8 +345,8 @@ public abstract class ScriptAttributesParser { public record ScriptAttributes(String title, String description, List menuPath, String menuGroup, String menuOrder, Icon icon, HelpLocation helpLocation, - Map> parameters, Map extraTtys, - int timeoutMillis, LaunchParameter imageOpt) { + Map> parameters, Set dependencies, + Map extraTtys, int timeoutMillis, LaunchParameter imageOpt) { } /** @@ -355,14 +359,35 @@ public abstract class ScriptAttributesParser { * @param script the script file * @param parameters the descriptions of the parameters * @param args the arguments to process + * @param dependencies a set of module names this script needs * @param address the address of the listening TraceRmi socket */ public static void processArguments(List commandLine, Map env, File script, Map> parameters, Map> args, - SocketAddress address) { + Set dependencies, SocketAddress address) { commandLine.add(script.getAbsolutePath()); - env.put(ENV_GHIDRA_HOME, Application.getInstallationDirectory().getAbsolutePath()); + + env.put(ENV_GHIDRA_HOME, Application.getApplicationRootDirectory().getAbsolutePath()); + ResourceFile myModule = + Application.getModuleContainingResourceFile(new ResourceFile(script)); + if (myModule == null) { + Msg.warn(ScriptAttributes.class, "Launch script is not contained in a module"); + } + else { + env.put(ENV_MODULE_HOME, myModule.getAbsolutePath()); + } + for (String dep : dependencies) { + ResourceFile module = Application.getModuleRootDir(dep); + if (module == null) { + Msg.warn(ScriptAttributes.class, "Could not find module " + dep); + } + else { + env.put(ENV_MODULE_HOME_PAT.formatted(dep.replace('-', '_')), + module.getAbsolutePath()); + } + } + if (address != null) { env.put(ENV_GHIDRA_TRACE_RMI_ADDR, sockToString(address)); if (address instanceof InetSocketAddress tcp) { @@ -402,8 +427,9 @@ public abstract class ScriptAttributesParser { private List menuPath; private final Map> userTypes = new HashMap<>(); private final Map> parameters = new LinkedHashMap<>(); + private final Set dependencies = new LinkedHashSet<>(); private final Map extraTtys = new LinkedHashMap<>(); - private int timeoutMillis = AbstractTraceRmiLaunchOffer.DEFAULT_TIMEOUT_MILLIS; + private int timeoutMillis = AbstractTraceRmiLaunchOffer.DEFAULT_CONNECTION_TIMEOUT_MILLIS; private String imageOptKey; /** @@ -493,6 +519,7 @@ public abstract class ScriptAttributesParser { switch (parts[0].trim()) { case AT_ARG -> parseArg(loc, parts[1], ++argc); case AT_ARGS -> parseArgs(loc, parts[1]); + case AT_DEPENDS -> parseDepends(loc, parts[1]); case AT_DESC -> parseDesc(loc, parts[1]); case AT_ENUM -> parseEnum(loc, parts[1]); case AT_ENV -> parseEnv(loc, parts[1]); @@ -549,6 +576,13 @@ public abstract class ScriptAttributesParser { } } + protected void parseDepends(Location loc, String str) { + String moduleName = str.trim(); + if (!dependencies.add(moduleName)) { + reportWarning("%s: Duplicate %s %s. Ignored.".formatted(loc, AT_DEPENDS, str)); + } + } + protected void parseDesc(Location loc, String str) { if (description == null) { description = new StringBuilder(); @@ -796,9 +830,11 @@ public abstract class ScriptAttributesParser { AT_IMAGE_OPT, imageOptKey)); } } + // NOTE: Don't use copyOf, or else we lose ordering return new ScriptAttributes(title, getDescription(), List.copyOf(menuPath), menuGroup, menuOrder, new GIcon(iconId), helpLocation, Collections.unmodifiableMap(new LinkedHashMap<>(parameters)), + Collections.unmodifiableSet(new LinkedHashSet<>(dependencies)), Collections.unmodifiableMap(new LinkedHashMap<>(extraTtys)), timeoutMillis, imageOpt); } diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TraceRmiBackEnd.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TraceRmiBackEnd.java new file mode 100644 index 0000000000..928484bdee --- /dev/null +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TraceRmiBackEnd.java @@ -0,0 +1,27 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.tracermi.launcher; + +import java.util.concurrent.CompletableFuture; + +import ghidra.app.plugin.core.terminal.TerminalListener; + +public class TraceRmiBackEnd extends CompletableFuture implements TerminalListener { + @Override + public void terminated(int exitcode) { + complete(exitcode); + } +} diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml index 06acacc3e3..0bc242fd69 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/pyproject.toml @@ -17,7 +17,7 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "protobuf >= 6.31.0", + "protobuf>=6.31.0", ] [project.urls] diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py index d0792aaf36..23a3b25165 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py @@ -18,7 +18,7 @@ try: from . import trace_rmi_pb2 as bufs except Exception as e: from .setuputils import prompt_and_mitigate_dependencies - prompt_and_mitigate_dependencies("Debug/Debugger-rmi-trace") + prompt_and_mitigate_dependencies("Debugger-rmi-trace") from collections import deque from concurrent.futures import Executor, Future diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/setuputils.py b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/setuputils.py index 63e268dd7c..dda58eefba 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/setuputils.py +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/setuputils.py @@ -23,22 +23,18 @@ whether remote or local, the PYTHONPATH should already include this module, and so we place the setup logic here. """ import os -from typing import List, Sequence +from typing import List, Optional, Sequence -home = os.getenv('GHIDRA_HOME') - - -def ghidra_module_src(name: str) -> str: - installed = f'{home}/Ghidra/{name}/pypkg' +def ghidra_module_src(name: Optional[str]=None) -> str: + mod_home_name = 'MODULE_HOME' if name is None else f'MODULE_{name.replace("-","_")}_HOME' + mod_home = os.getenv(mod_home_name) + installed = f'{mod_home}/pypkg' if os.path.isdir(installed): return installed - dev1 = f'{home}/Ghidra/{name}/src/main/py' - if os.path.isdir(dev1): - return dev1 - dev2 = f'{home}/ghidra/Ghidra/{name}/src/main/py' - if os.path.isdir(dev2): - return dev2 + dev = f'{mod_home}/src/main/py' + if os.path.isdir(dev): + return dev raise Exception(f""" Cannot find Python source for {name}. If this is a remote system, we shouldn't even be here. Chances are, @@ -63,9 +59,9 @@ def get_module_dependencies(name: str) -> List[str]: elif seen_deps and l == ']': return [r for r in result if not 'ghidra' in r] elif seen_deps: - if l.endswith(','): # Last one may not have , + if l.endswith(','): # Last one may not have , l = l[:-1].strip() - result.append(l[1:-1]) # Remove 's or "s + result.append(l[1:-1]) # Remove 's or "s raise Exception("Could not parse pyproject.toml") @@ -93,15 +89,29 @@ def mitigate_by_pip_install(*args: str) -> None: runpy.run_module("pip", run_name="__main__") +def compute_suggestion(*args: str) -> None: + def maybe_quote(a): + if '>' in a or '<' in a or ' ' in a: + return f"'{a}'" + return a + wquotes = ' '.join(maybe_quote(a) for a in args) + return f"python -m pip install --force-reinstall {wquotes}" + + def prompt_and_mitigate_dependencies(name: str) -> None: deps = get_module_dependencies(name) deps_str = ' '.join(f"'{d}'" for d in deps) - answer = prompt_mitigation(""" + suggestion = compute_suggestion(*deps) + answer = prompt_mitigation(f""" It appears dependencies are missing or have the wrong version. This can happen if you forgot to install the required packages. This can also happen if you installed the packages to a different Python environment than is being used right now. +The following command should resolve the issue: + + {suggestion} + This script is about to offer automatic resolution. If you'd like to resolve this manually, answer no to the next question and then see Ghidra's help by pressing F1 in the dialog of launch parameters. @@ -121,4 +131,3 @@ finished, close this terminal, and try launching again. if answer: mitigate_by_pip_install('-f', '../../pypkg/dist', *deps) - diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/DefaultTerminal.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/DefaultTerminal.java index d55e69c4ef..9012adb7dc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/DefaultTerminal.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/DefaultTerminal.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -41,8 +41,8 @@ public class DefaultTerminal implements Terminal { } @Override - public void terminated() { - provider.terminated(); + public void terminated(int exitcode) { + provider.terminated(exitcode); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalListener.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalListener.java index 2c281e328b..46d8834944 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalListener.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalListener.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -38,4 +38,12 @@ public interface TerminalListener { */ default void retitled(String title) { } + + /** + * The terminal session was terminated + * + * @param exitcode the exit code of the session leader, or -1 if not applicable + */ + default void terminated(int exitcode) { + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java index e233aa605b..0f7ad43bdb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java @@ -39,7 +39,9 @@ import ghidra.app.plugin.core.terminal.TerminalFinder.TextTerminalFinder; import ghidra.app.plugin.core.terminal.vt.*; import ghidra.app.plugin.core.terminal.vt.VtHandler.*; import ghidra.app.services.ClipboardService; -import ghidra.util.*; +import ghidra.util.ColorUtils; +import ghidra.util.Swing; +import ghidra.util.datastruct.ListenerSet; /** * A VT100 terminal emulator in a panel. @@ -180,7 +182,8 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel protected TerminalClipboardProvider clipboardProvider; protected String selectedText; - protected final ArrayList terminalListeners = new ArrayList<>(); + protected final ListenerSet terminalListeners = + new ListenerSet(TerminalListener.class, false); protected VtOutput outputCb; protected final TerminalAwtEventEncoder eventEncoder; @@ -363,25 +366,15 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel } protected void notifyTerminalResized(short cols, short rows) { - for (TerminalListener l : terminalListeners) { - try { - l.resized(cols, rows); - } - catch (Throwable t) { - Msg.showError(this, null, "Error", t.getMessage(), t); - } - } + terminalListeners.invoke().resized(cols, rows); } protected void notifyTerminalRetitled(String title) { - for (TerminalListener l : terminalListeners) { - try { - l.retitled(title); - } - catch (Throwable t) { - Msg.showError(this, null, "Error", t.getMessage(), t); - } - } + terminalListeners.invoke().retitled(title); + } + + protected void notifyTerminalTerminated(int exitcode) { + terminalListeners.invoke().terminated(exitcode); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java index 824816bdd8..bee2e95dd4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java @@ -53,7 +53,7 @@ import ghidra.util.Swing; * This also provides UI actions for searching the terminal's contents. */ public class TerminalProvider extends ComponentProviderAdapter { - // TODO: A separate color? + // Should I use a separate color id? private static final Color COLOR_TERMINATED = new GColor("color.border.provider.disconnected"); protected class FindDialog extends DialogComponentProvider { @@ -433,10 +433,13 @@ public class TerminalProvider extends ComponentProviderAdapter { *

* The title and sub title are adjusted and all terminal listeners are removed. If/when the * window is closed, it is removed from the tool. + * + * @param exitcode the exit code of the session leader, or -1 if not applicable */ - public void terminated() { + public void terminated(int exitcode) { Swing.runIfSwingOrRunLater(() -> { terminated = true; + panel.terminalListeners.invoke().terminated(exitcode); removeLocalAction(actionTerminate); panel.terminalListeners.clear(); panel.setOutputCallback(buf -> { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/services/Terminal.java b/Ghidra/Features/Base/src/main/java/ghidra/app/services/Terminal.java index c092ca248e..1a05a3e74d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/services/Terminal.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/services/Terminal.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -201,8 +201,10 @@ public interface Terminal extends AutoCloseable { *

* The title and sub title are adjust and all listeners are removed. If/when the terminal is * closed, it is permanently removed from the tool. + * + * @param exitcode the exit code of the session leader, or -1 if not applicable */ - void terminated(); + void terminated(int exitcode); /** * Allow the user to terminate the session forcefully diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java new file mode 100644 index 0000000000..b4d41f4bcc --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java @@ -0,0 +1,182 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; + +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +import org.junit.Before; + +import generic.Unique; +import generic.jar.ResourceFile; +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerIntegrationTest; +import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesPlugin; +import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.NoStaticMappingException; +import ghidra.app.plugin.core.debug.gui.tracermi.launcher.TraceRmiLauncherServicePlugin; +import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin; +import ghidra.app.services.DebuggerAutoMappingService; +import ghidra.app.services.TraceRmiLauncherService; +import ghidra.debug.api.ValStr; +import ghidra.debug.api.tracermi.TraceRmiLaunchOffer; +import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.*; +import ghidra.framework.Application; +import ghidra.framework.OperatingSystem; +import ghidra.framework.plugintool.AutoConfigState.PathIsFile; +import ghidra.util.SystemUtilities; + +public abstract class AbstractRmiConnectorsTest + extends AbstractGhidraHeadedDebuggerIntegrationTest { + protected TraceRmiLauncherService launchService; + protected DebuggerAutoMappingService autoMappingService; + + protected String getPythonCmd() { + return "python"; + } + + protected abstract List getPipLinkModules(); + + protected void unpip(String... specs) throws Exception { + List args = new ArrayList<>(); + args.addAll(List.of(getPythonCmd(), "-m", "pip", "uninstall", "-y")); + args.addAll(List.of(specs)); + int result = new ProcessBuilder().command(args).inheritIO().start().waitFor(); + assertEquals("pip failed", 0, result); + } + + protected void pipOob(String... specs) throws Exception { + List args = new ArrayList<>(); + args.addAll(List.of(getPythonCmd(), "-m", "pip", "install")); + args.addAll(List.of(specs)); + int result = new ProcessBuilder().command(args).inheritIO().start().waitFor(); + assertEquals("pip failed", 0, result); + } + + protected void pip(String... specs) throws Exception { + List args = new ArrayList<>(); + args.addAll(List.of(getPythonCmd(), "-m", "pip", "install", "--no-index")); + for (ResourceFile root : Application.getApplicationRootDirectories()) { + if (root.getAbsolutePath().contains("ghidra.bin")) { + for (; root != null; root = root.getParentFile()) { + if (root.getName().equals("ghidra.bin")) { + args.addAll(List.of("-f", root.getAbsolutePath() + "/ExternalPyWheels")); + } + } + } + } + for (ResourceFile module : getPipLinkModules()) { + args.addAll(List.of("-f", module.getAbsolutePath() + "/build/pypkg/dist")); + } + args.addAll(List.of(specs)); + int result = new ProcessBuilder().command(args).inheritIO().start().waitFor(); + assertEquals("pip failed", 0, result); + } + + protected PathIsFile chooseImage() { + if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) { + return new PathIsFile(Path.of("C:\\Windows\\notepad.exe")); + } + return new PathIsFile(Path.of("/bin/ls")); + } + + protected PathIsFile findQemu(String bin) { + if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) { + return new PathIsFile(Path.of("C:\\msys64\\ucrt64\bin\\").resolve(bin)); + } + return new PathIsFile(Path.of(bin)); + } + + protected PathIsFile createArmElfImage() throws Exception { + assumeTrue(OperatingSystem.LINUX == OperatingSystem.CURRENT_OPERATING_SYSTEM); + Path tempSrc = Files.createTempFile("hw", ".c"); + Path tempObj = Files.createTempFile("hw", ".o"); + Path tempImg = Files.createTempFile("hw", ""); + try (OutputStream os = new FileOutputStream(tempSrc.toFile())) { + os.write(""" + int main() { + return 0; + } + """.getBytes()); + } + new ProcessBuilder().command( + "arm-linux-eabi-gcc", "-c", + "-o", tempObj.toAbsolutePath().toString(), + tempSrc.toAbsolutePath().toString()).inheritIO().start().waitFor(); + new ProcessBuilder().command( + "arm-linux-eabi-ld", + "-o", tempImg.toAbsolutePath().toString(), + tempObj.toAbsolutePath().toString()).inheritIO().start().waitFor(); + return new PathIsFile(tempImg); + } + + protected PathIsFile createDummyQemuImage() throws Exception { + Path temp = Files.createTempFile("qemudummy", ".bin"); + try (OutputStream os = new FileOutputStream(temp.toFile())) { + os.write(new byte[4096]); + } + return new PathIsFile(temp); + } + + protected LaunchResult doLaunch(String title, Map args) { + TraceRmiLaunchOffer offer = Unique.assertOne( + launchService.getOffers(program).stream().filter(o -> o.getTitle().equals(title))); + return offer.launchProgram(monitor, new LaunchConfigurator() { + @Override + public Map> configureLauncher(TraceRmiLaunchOffer offer, + Map> arguments, RelPrompt relPrompt) { + Map> newArgs = new HashMap<>(arguments); + for (Map.Entry ent : args.entrySet()) { + newArgs.put(ent.getKey(), ValStr.from(ent.getValue())); + } + return newArgs; + } + + @Override + public PromptMode getPromptMode() { + return title.contains("ssh") && + OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS + ? PromptMode.ALWAYS + : PromptMode.NEVER; + } + }); + } + + protected void checkResult(LaunchResult result) { + if (result.exception() != null && + !(result.exception() instanceof NoStaticMappingException)) { + throw new AssertionError(result); + } + } + + @Before + public void setUpRmiConnectorsTest() throws Exception { + // Check manual + assumeFalse(SystemUtilities.isInTestingBatchMode()); + + addPlugin(tool, DebuggerStaticMappingServicePlugin.class); + addPlugin(tool, DebuggerModulesPlugin.class); + autoMappingService = + Objects.requireNonNull(tool.getService(DebuggerAutoMappingService.class)); + launchService = addPlugin(tool, TraceRmiLauncherServicePlugin.class); + } + +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java new file mode 100644 index 0000000000..26e1712eec --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java @@ -0,0 +1,93 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.dbgeng.rmi; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; + +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import agent.AbstractRmiConnectorsTest; +import generic.jar.ResourceFile; +import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.EarlyTerminationException; +import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.LaunchResult; +import ghidra.framework.Application; +import ghidra.framework.plugintool.AutoConfigState.PathIsFile; + +public class DbgEngConnectorsTest extends AbstractRmiConnectorsTest { + + @Override + protected String getPythonCmd() { + return "C:\\Python313\\python"; + } + + @Override + protected List getPipLinkModules() { + return List.of( + Application.getModuleRootDir("Debugger-rmi-trace"), + Application.getModuleRootDir("Debugger-agent-dbgeng")); + } + + @Before + public void setUpDbgEng() throws Exception { + // Make sure system doesn't cause path failures to pass + unpip("ghidradbg", "ghidratrace"); + // Ensure a compatible version of protobuf + pip("protobuf==6.31.0"); + } + + @Test + public void testLocalDbgSetup() throws Exception { + pipOob("protobuf==3.19.0"); + try (LaunchResult result = doLaunch("dbgeng", Map.ofEntries( + Map.entry("env:OPT_TARGET_IMG", chooseImage()), + Map.entry("env:OPT_PYTHON_EXE", + new PathIsFile(Path.of("C:\\Python313\\python.exe")))))) { + assertThat(result.exception(), instanceOf(EarlyTerminationException.class)); + assertThat(result.sessions().get("Shell").content(), + containsString("Would you like to install")); + } + try (LaunchResult result = doLaunch("dbgeng", Map.ofEntries( + Map.entry("env:OPT_TARGET_IMG", chooseImage()), + Map.entry("env:OPT_PYTHON_EXE", + new PathIsFile(Path.of("C:\\Python313\\python.exe")))))) { + checkResult(result); + } + } + + @Test + public void testLocalDbgWithImage() throws Exception { + try (LaunchResult result = doLaunch("dbgeng", Map.ofEntries( + Map.entry("env:OPT_TARGET_IMG", chooseImage()), + Map.entry("env:OPT_PYTHON_EXE", + new PathIsFile(Path.of("C:\\Python313\\python.exe")))))) { + checkResult(result); + } + } + + // LATER?: kernel + // LATER?: attach (usermode by PID) + // LATER?: ext + // LATER?: trace (TTD) + // LATER?: remote (Start WinDbg and join session) + // LATER?: svrcx (what scenario?) +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/AbstractDrgnTraceRmiTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/AbstractDrgnTraceRmiTest.java index 78ed579c22..fc8e93ea6c 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/AbstractDrgnTraceRmiTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/AbstractDrgnTraceRmiTest.java @@ -52,9 +52,9 @@ import junit.framework.AssertionFailedError; public abstract class AbstractDrgnTraceRmiTest extends AbstractGhidraHeadedDebuggerTest { - protected static String CORE = "core.12137"; - protected static String MDO = "/New Traces/" + CORE; - public static String PREAMBLE = """ + protected static final String CORE = "core.12137"; + protected static final String MDO = "/New Traces/" + CORE; + public static final String PREAMBLE = """ import os import drgn import drgn.cli diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnConnectorsTest.java new file mode 100644 index 0000000000..0996aab03d --- /dev/null +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/drgn/rmi/DrgnConnectorsTest.java @@ -0,0 +1,82 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.drgn.rmi; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Map; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; + +import agent.AbstractRmiConnectorsTest; +import generic.jar.ResourceFile; +import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.EarlyTerminationException; +import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.LaunchResult; +import ghidra.framework.Application; +import ghidra.framework.plugintool.AutoConfigState.PathIsFile; + +public class DrgnConnectorsTest extends AbstractRmiConnectorsTest { + + @Override + protected List getPipLinkModules() { + return List.of( + Application.getModuleRootDir("Debugger-rmi-trace"), + Application.getModuleRootDir("Debugger-agent-drgn")); + } + + protected PathIsFile chooseCore() throws FileNotFoundException { + return new PathIsFile(Application + .getModuleDataFile("TestResources", AbstractDrgnTraceRmiTest.CORE) + .getFile(true) + .toPath()); + } + + @Before + public void setUpDrgn() throws Exception { + // Make sure system doesn't cause path failures to pass + unpip("ghidradrgn", "ghidratrace"); + // Ensure a compatible version of protobuf + pip("protobuf==6.31.0"); + } + + @Test + public void testLocalDrgnSetup() throws Exception { + pipOob("protobuf==3.19.0"); + try (LaunchResult result = doLaunch("drgn core", Map.ofEntries( + Map.entry("env:OPT_TARGET_IMG", chooseCore())))) { + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); + } + try (LaunchResult result = doLaunch("drgn core", Map.ofEntries( + Map.entry("env:OPT_TARGET_IMG", chooseCore())))) { + checkResult(result); + } + } + + @Test + public void testLocalDrgnWithCore() throws Exception { + try (LaunchResult result = doLaunch("drgn core", Map.ofEntries( + Map.entry("env:OPT_TARGET_IMG", chooseCore())))) { + checkResult(result); + } + } +} diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbConnectorsTest.java index b33090739a..63b5a32967 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbConnectorsTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/GdbConnectorsTest.java @@ -15,134 +15,54 @@ */ package agent.gdb.rmi; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.net.SocketTimeoutException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.List; +import java.util.Map; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; +import agent.AbstractRmiConnectorsTest; import db.Transaction; -import generic.Unique; -import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerIntegrationTest; +import generic.jar.ResourceFile; import ghidra.app.plugin.core.debug.gui.action.BySectionAutoMapSpec; -import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesPlugin; -import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.NoStaticMappingException; -import ghidra.app.plugin.core.debug.gui.tracermi.launcher.TraceRmiLauncherServicePlugin; -import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin; -import ghidra.app.services.DebuggerAutoMappingService; -import ghidra.app.services.TraceRmiLauncherService; +import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.EarlyTerminationException; import ghidra.app.util.importer.AutoImporter; import ghidra.app.util.importer.MessageLog; -import ghidra.debug.api.ValStr; import ghidra.debug.api.action.AutoMapSpec; -import ghidra.debug.api.tracermi.TerminalSession; -import ghidra.debug.api.tracermi.TraceRmiLaunchOffer; -import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.*; -import ghidra.framework.OperatingSystem; +import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.LaunchResult; +import ghidra.framework.Application; import ghidra.framework.plugintool.AutoConfigState.PathIsFile; import ghidra.pty.testutil.DummyProc; -import ghidra.util.SystemUtilities; -public class GdbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationTest { - private TraceRmiLauncherService launchService; - private DebuggerAutoMappingService autoMappingService; +public class GdbConnectorsTest extends AbstractRmiConnectorsTest { + + @Override + protected List getPipLinkModules() { + return List.of( + Application.getModuleRootDir("Debugger-rmi-trace"), + Application.getModuleRootDir("Debugger-agent-gdb")); + } @Before - public void checkManual() throws Exception { - assumeFalse(SystemUtilities.isInTestingBatchMode()); - addPlugin(tool, DebuggerStaticMappingServicePlugin.class); - addPlugin(tool, DebuggerModulesPlugin.class); - autoMappingService = - Objects.requireNonNull(tool.getService(DebuggerAutoMappingService.class)); - launchService = addPlugin(tool, TraceRmiLauncherServicePlugin.class); - } - - protected PathIsFile chooseImage() { - if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) { - return new PathIsFile(Path.of("C:\\Windows\\notepad.exe")); - } - return new PathIsFile(Path.of("/bin/ls")); - } - - protected PathIsFile findQemu(String bin) { - if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) { - return new PathIsFile(Path.of("C:\\msys64\\ucrt64\bin\\").resolve(bin)); - } - return new PathIsFile(Path.of(bin)); - } - - protected PathIsFile createArmElfImage() throws Exception { - Path tempSrc = Files.createTempFile("hw", ".c"); - Path tempObj = Files.createTempFile("hw", ".o"); - Path tempImg = Files.createTempFile("hw", ""); - try (OutputStream os = new FileOutputStream(tempSrc.toFile())) { - os.write(""" - int main() { - return 0; - } - """.getBytes()); - } - new ProcessBuilder().command( - "arm-linux-eabi-gcc", "-c", - "-o", tempObj.toAbsolutePath().toString(), - tempSrc.toAbsolutePath().toString()).inheritIO().start().waitFor(); - new ProcessBuilder().command( - "arm-linux-eabi-ld", - "-o", tempImg.toAbsolutePath().toString(), - tempObj.toAbsolutePath().toString()).inheritIO().start().waitFor(); - return new PathIsFile(tempImg); - } - - protected PathIsFile createDummyQemuImage() throws Exception { - Path temp = Files.createTempFile("qemudummy", ".bin"); - try (OutputStream os = new FileOutputStream(temp.toFile())) { - os.write(new byte[4096]); - } - return new PathIsFile(temp); - } - - protected LaunchResult doLaunch(String title, Map args) { - TraceRmiLaunchOffer offer = Unique.assertOne( - launchService.getOffers(program).stream().filter(o -> o.getTitle().equals(title))); - return offer.launchProgram(monitor, new LaunchConfigurator() { - @Override - public Map> configureLauncher(TraceRmiLaunchOffer offer, - Map> arguments, RelPrompt relPrompt) { - Map> newArgs = new HashMap<>(arguments); - for (Map.Entry ent : args.entrySet()) { - newArgs.put(ent.getKey(), ValStr.from(ent.getValue())); - } - return newArgs; - } - }); - } - - protected void checkResult(LaunchResult result) { - if (result.exception() != null && - !(result.exception() instanceof NoStaticMappingException)) { - throw new AssertionError(result); - } + public void setUpGdb() throws Exception { + // Make sure system doesn't cause path failures to pass + unpip("ghidragdb", "ghidratrace"); + // Ensure a compatible version of protobuf + pip("protobuf==6.31.0"); } @Test public void testLocalGdbSetup() throws Exception { - new ProcessBuilder().command("pip", "install", "protobuf==3.19.0") - .inheritIO() - .start() - .waitFor(); + pipOob("protobuf==3.19.0"); try (LaunchResult result = doLaunch("gdb", Map.of("arg:1", chooseImage()))) { - assertTrue(result.exception() instanceof SocketTimeoutException); - TerminalSession term = Unique.assertOne(result.sessions().values()); - while (!term.isTerminated()) { - Thread.sleep(1000); - } + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); } try (LaunchResult result = doLaunch("gdb", Map.of("arg:1", chooseImage()))) { checkResult(result); @@ -206,6 +126,7 @@ public class GdbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationTe @Test public void testGdbViaSsh() throws Exception { + pip("ghidragdb==%s".formatted(Application.getApplicationVersion())); try (LaunchResult result = doLaunch("gdb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), Map.entry("OPT_HOST", "localhost")))) { @@ -215,15 +136,12 @@ public class GdbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationTe @Test public void testGdbViaSshSetupGhidraGdb() throws Exception { - new ProcessBuilder().command("pip", "uninstall", "ghidragdb").inheritIO().start().waitFor(); try (LaunchResult result = doLaunch("gdb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), Map.entry("OPT_HOST", "localhost")))) { - assertTrue(result.exception() instanceof SocketTimeoutException); - TerminalSession term = Unique.assertOne(result.sessions().values()); - while (!term.isTerminated()) { - Thread.sleep(1000); - } + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); } try (LaunchResult result = doLaunch("gdb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), @@ -234,18 +152,15 @@ public class GdbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationTe @Test public void testGdbViaSshSetupProtobuf() throws Exception { - new ProcessBuilder().command("pip", "install", "protobuf==3.19.0") - .inheritIO() - .start() - .waitFor(); + pip("ghidragdb==%s".formatted(Application.getApplicationVersion())); + // Overwrite with an incompatible version we don't include + pipOob("protobuf==3.19.0"); try (LaunchResult result = doLaunch("gdb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), Map.entry("OPT_HOST", "localhost")))) { - assertTrue(result.exception() instanceof SocketTimeoutException); - TerminalSession term = Unique.assertOne(result.sessions().values()); - while (!term.isTerminated()) { - Thread.sleep(1000); - } + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); } try (LaunchResult result = doLaunch("gdb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbConnectorsTest.java index 36b703f794..7193d83f29 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbConnectorsTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/lldb/rmi/LldbConnectorsTest.java @@ -15,132 +15,52 @@ */ package agent.lldb.rmi; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; -import static org.junit.Assume.assumeTrue; -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.net.SocketTimeoutException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.List; +import java.util.Map; +import org.hamcrest.Matchers; import org.junit.*; +import agent.AbstractRmiConnectorsTest; import db.Transaction; -import generic.Unique; -import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerIntegrationTest; +import generic.jar.ResourceFile; import ghidra.app.plugin.core.debug.gui.action.BySectionAutoMapSpec; -import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesPlugin; -import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.NoStaticMappingException; -import ghidra.app.plugin.core.debug.gui.tracermi.launcher.TraceRmiLauncherServicePlugin; -import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin; -import ghidra.app.services.DebuggerAutoMappingService; -import ghidra.app.services.TraceRmiLauncherService; +import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.EarlyTerminationException; import ghidra.app.util.importer.AutoImporter; import ghidra.app.util.importer.MessageLog; -import ghidra.debug.api.ValStr; import ghidra.debug.api.action.AutoMapSpec; -import ghidra.debug.api.tracermi.TerminalSession; -import ghidra.debug.api.tracermi.TraceRmiLaunchOffer; -import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.*; +import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.LaunchResult; +import ghidra.framework.Application; import ghidra.framework.OperatingSystem; import ghidra.framework.plugintool.AutoConfigState.PathIsFile; import ghidra.pty.testutil.DummyProc; -import ghidra.util.SystemUtilities; /** * NOTE: On Windows, these tests may need to be run with lldb's version of Python at the front of - * PATH, and it's lib and DLLs dirs at the front of PYTHONPATH. It's probably easiest to just get + * PATH, and its lib and DLLs dirs at the front of PYTHONPATH. It's probably easiest to just get * lldb working in a command prompt. Ensure that it can import socket, and then re-launch Eclipse * from there. */ -public class LldbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationTest { - private TraceRmiLauncherService launchService; - private DebuggerAutoMappingService autoMappingService; +public class LldbConnectorsTest extends AbstractRmiConnectorsTest { + + @Override + protected List getPipLinkModules() { + return List.of( + Application.getModuleRootDir("Debugger-rmi-trace"), + Application.getModuleRootDir("Debugger-agent-lldb")); + } @Before - public void checkManual() throws Exception { - assumeFalse(SystemUtilities.isInTestingBatchMode()); - addPlugin(tool, DebuggerStaticMappingServicePlugin.class); - addPlugin(tool, DebuggerModulesPlugin.class); - autoMappingService = - Objects.requireNonNull(tool.getService(DebuggerAutoMappingService.class)); - launchService = addPlugin(tool, TraceRmiLauncherServicePlugin.class); - } - - protected PathIsFile chooseImage() { - if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) { - return new PathIsFile(Path.of("C:\\Windows\\notepad.exe")); - } - return new PathIsFile(Path.of("/bin/ls")); - } - - protected PathIsFile findQemu(String bin) { - if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) { - return new PathIsFile(Path.of("C:\\msys64\\ucrt64\bin\\").resolve(bin)); - } - return new PathIsFile(Path.of(bin)); - } - - protected PathIsFile createArmElfImage() throws Exception { - assumeTrue(OperatingSystem.LINUX == OperatingSystem.CURRENT_OPERATING_SYSTEM); - Path tempSrc = Files.createTempFile("hw", ".c"); - Path tempObj = Files.createTempFile("hw", ".o"); - Path tempImg = Files.createTempFile("hw", ""); - try (OutputStream os = new FileOutputStream(tempSrc.toFile())) { - os.write(""" - int main() { - return 0; - } - """.getBytes()); - } - new ProcessBuilder().command( - "arm-linux-eabi-gcc", "-c", - "-o", tempObj.toAbsolutePath().toString(), - tempSrc.toAbsolutePath().toString()).inheritIO().start().waitFor(); - new ProcessBuilder().command( - "arm-linux-eabi-ld", - "-o", tempImg.toAbsolutePath().toString(), - tempObj.toAbsolutePath().toString()).inheritIO().start().waitFor(); - return new PathIsFile(tempImg); - } - - protected PathIsFile createDummyQemuImage() throws Exception { - Path temp = Files.createTempFile("qemudummy", ".bin"); - try (OutputStream os = new FileOutputStream(temp.toFile())) { - os.write(new byte[4096]); - } - return new PathIsFile(temp); - } - - protected LaunchResult doLaunch(String title, Map args) { - TraceRmiLaunchOffer offer = Unique.assertOne( - launchService.getOffers(program).stream().filter(o -> o.getTitle().equals(title))); - return offer.launchProgram(monitor, new LaunchConfigurator() { - @Override - public Map> configureLauncher(TraceRmiLaunchOffer offer, - Map> arguments, RelPrompt relPrompt) { - Map> newArgs = new HashMap<>(arguments); - for (Map.Entry ent : args.entrySet()) { - newArgs.put(ent.getKey(), ValStr.from(ent.getValue())); - } - return newArgs; - } - - @Override - public PromptMode getPromptMode() { - return title.contains("ssh") ? PromptMode.ALWAYS : PromptMode.NEVER; - } - }); - } - - protected void checkResult(LaunchResult result) { - if (result.exception() != null && - !(result.exception() instanceof NoStaticMappingException)) { - throw new AssertionError(result); - } + public void setupLldb() throws Exception { + // Make sure system doesn't cause path failures to pass + unpip("ghidralldb", "ghidratrace"); + // Ensure a compatible version of protobuf + pip("protobuf==6.31.0"); } /** @@ -149,24 +69,17 @@ public class LldbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationT * package missing and exits with code 253. May just have to cut losses there. The message hits * the screen, and this circumstance should be rare. * - * @throws Exception + * @throws Exception because */ @Test public void testLocalLldbSetup() throws Exception { - new ProcessBuilder().command("python", "-m", "pip", "install", "protobuf==3.19.0") - .inheritIO() - .start() - .waitFor(); + pipOob("protobuf==3.19.0"); try (LaunchResult result = doLaunch("lldb", Map.of("arg:1", chooseImage()))) { - assertTrue(result.exception() instanceof SocketTimeoutException); - TerminalSession term = Unique.assertOne(result.sessions().values()); - while (!term.isTerminated()) { - Thread.sleep(1000); - } - } - try (LaunchResult result = doLaunch("lldb", Map.of("arg:1", chooseImage()))) { - checkResult(result); + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); } + // NOTE: lldb will not let me prompt the user, so cannot test automatic mitigation } @Test @@ -219,7 +132,7 @@ public class LldbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationT * This has proven difficult to test on Windows, probably because the version of lldb and * gdbserver I'm using are not compatible? * - * @throws Exception + * @throws Exception because */ @Test public void testLldbRemoteGdb() throws Exception { @@ -237,6 +150,7 @@ public class LldbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationT @Test public void testLldbViaSsh() throws Exception { + pip("ghidralldb==%s".formatted(Application.getApplicationVersion())); try (LaunchResult result = doLaunch("lldb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), Map.entry("OPT_HOST", "localhost")))) { @@ -246,19 +160,12 @@ public class LldbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationT @Test public void testLldbViaSshSetupGhidraLldb() throws Exception { - // This only applies if we leave localhost in the dialog - new ProcessBuilder().command("python", "-m", "pip", "uninstall", "ghidralldb") - .inheritIO() - .start() - .waitFor(); try (LaunchResult result = doLaunch("lldb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), Map.entry("OPT_HOST", "localhost")))) { - assertTrue(result.exception() instanceof SocketTimeoutException); - TerminalSession term = Unique.assertOne(result.sessions().values()); - while (!term.isTerminated()) { - Thread.sleep(1000); - } + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); } try (LaunchResult result = doLaunch("lldb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), @@ -269,18 +176,15 @@ public class LldbConnectorsTest extends AbstractGhidraHeadedDebuggerIntegrationT @Test public void testLldbViaSshSetupProtobuf() throws Exception { - new ProcessBuilder().command("python", "-m", "pip", "install", "protobuf==3.19.0") - .inheritIO() - .start() - .waitFor(); + pip("ghidralldb==%s".formatted(Application.getApplicationVersion())); + // Overwrite with an incompatible version we don't include + pipOob("protobuf==3.19.0"); try (LaunchResult result = doLaunch("lldb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), Map.entry("OPT_HOST", "localhost")))) { - assertTrue(result.exception() instanceof SocketTimeoutException); - TerminalSession term = Unique.assertOne(result.sessions().values()); - while (!term.isTerminated()) { - Thread.sleep(1000); - } + assertTrue(result.exception() instanceof EarlyTerminationException); + assertThat(result.sessions().get("Shell").content(), + Matchers.containsString("Would you like to install")); } try (LaunchResult result = doLaunch("lldb via ssh", Map.ofEntries( Map.entry("arg:1", "/bin/ls"), diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptTraceRmiLaunchOfferTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptTraceRmiLaunchOfferTest.java index 3f0b7a3229..d1986336ac 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptTraceRmiLaunchOfferTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/ScriptTraceRmiLaunchOfferTest.java @@ -187,7 +187,7 @@ public class ScriptTraceRmiLaunchOfferTest extends AbstractGhidraHeadedDebuggerT } @Override - public void terminated() { + public void terminated(int exitcode) { } @Override diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TestTraceRmiLaunchOpinion.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TestTraceRmiLaunchOpinion.java index 550205072d..6e467ddebf 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TestTraceRmiLaunchOpinion.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/TestTraceRmiLaunchOpinion.java @@ -67,8 +67,10 @@ public class TestTraceRmiLaunchOpinion implements TraceRmiLaunchOpinion { } @Override - protected void launchBackEnd(TaskMonitor monitor, Map sessions, + protected TraceRmiBackEnd launchBackEnd(TaskMonitor monitor, + Map sessions, Map> args, SocketAddress address) throws Exception { + return null; } @Override