mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4906: Implement @image-opt. Have local-gdb use it. Fix 'null'.
This commit is contained in:
parent
e476b20476
commit
d5a25fa6a3
31 changed files with 497 additions and 462 deletions
|
@ -9,7 +9,7 @@
|
||||||
::@menu-group local
|
::@menu-group local
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#dbgeng_kernel
|
::@help TraceRmiLauncherServicePlugin#dbgeng_kernel
|
||||||
::@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_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
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Connection-string arguments (a la .server)"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Connection-string arguments (a la .server)"
|
||||||
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
::@menu-group local
|
::@menu-group local
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#dbgeng_attach
|
::@help TraceRmiLauncherServicePlugin#dbgeng_attach
|
||||||
::@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_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:str="" "Process id" "The target process id"
|
::@env OPT_TARGET_PID:int="" "Process id" "The target process id"
|
||||||
::@env OPT_ATTACH_FLAGS:str="0" "Attach flags" "Attach flags"
|
::@env OPT_ATTACH_FLAGS:int="0" "Attach flags" "Attach flags"
|
||||||
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
::@title dbgeng-ext
|
::@title dbgeng-ext
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -9,17 +10,17 @@
|
||||||
::@menu-group local
|
::@menu-group local
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#dbgeng_ext
|
::@help TraceRmiLauncherServicePlugin#dbgeng_ext
|
||||||
::@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_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
|
:: 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"
|
::@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image"
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
::@env OPT_TARGET_DIR:str="" "Dir" "Initial directory"
|
::@env OPT_TARGET_DIR:str="" "Dir" "Initial directory"
|
||||||
::@env OPT_TARGET_ENV:str="" "Env" "Environment variables (sep=/0)"
|
::@env OPT_TARGET_ENV:str="" "Env" "Environment variables (sep=/0)"
|
||||||
::@env OPT_CREATE_FLAGS:str="1" "Create flags" "Creation flags"
|
::@env OPT_CREATE_FLAGS:int="1" "Create flags" "Creation flags"
|
||||||
::@env OPT_CREATE_ENGFLAGS:str="0" "Create flags (Engine)" "Engine-specific creation flags"
|
::@env OPT_CREATE_ENGFLAGS:int="0" "Create flags (Engine)" "Engine-specific creation flags"
|
||||||
::@env OPT_VERIFIER_FLAGS:str="0" "Verifier flags" "Verifier flags"
|
::@env OPT_VERIFIER_FLAGS:int="0" "Verifier flags" "Verifier flags"
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
::@title dbgeng
|
::@title dbgeng
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -9,9 +10,9 @@
|
||||||
::@menu-group local
|
::@menu-group local
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#dbgeng
|
::@help TraceRmiLauncherServicePlugin#dbgeng
|
||||||
::@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_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
|
:: 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"
|
::@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image"
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
::@menu-group local
|
::@menu-group local
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#dbgeng_ttd
|
::@help TraceRmiLauncherServicePlugin#dbgeng_ttd
|
||||||
::@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_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
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
::@env OPT_TARGET_IMG:file="" "Trace (.run)" "A trace associated with the target binary executable"
|
::@env OPT_TARGET_IMG:file!="" "Trace (.run)" "A trace associated with the target binary executable"
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
::@env OPT_DBGMODEL_PATH:dir="" "Path to dbgeng.dll & \\ttd" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
::@env OPT_DBGMODEL_PATH:dir="" "Path to dbgeng.dll & \\ttd" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
::@title dbgeng-remote
|
::@title dbgeng-remote
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>dbgeng</tt> remotely (in a Python interpreter)</h3>
|
::@desc <h3>Launch with <tt>dbgeng</tt> remotely (in a Python interpreter)</h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -9,9 +10,9 @@
|
||||||
::@menu-group local
|
::@menu-group local
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#dbgeng_remote
|
::@help TraceRmiLauncherServicePlugin#dbgeng_remote
|
||||||
::@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_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
|
:: 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"
|
::@env OPT_TARGET_IMG:str!="" "Image" "The target binary executable image"
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_CONNECT_STRING:str="" "Connection" "Connection-string arguments (a la dbgsrv args)"
|
::@env OPT_CONNECT_STRING:str="" "Connection" "Connection-string arguments (a la dbgsrv args)"
|
||||||
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
data/debugger-launchers/local-gdb.bat||GHIDRA||||END|
|
data/debugger-launchers/local-gdb.bat||GHIDRA||||END|
|
||||||
data/debugger-launchers/qemu-gdb.bat||GHIDRA||||END|
|
data/debugger-launchers/qemu-gdb.bat||GHIDRA||||END|
|
||||||
data/debugger-launchers/raw-gdb.bat||GHIDRA||||END|
|
|
||||||
data/debugger-launchers/remote-gdb.bat||GHIDRA||||END|
|
data/debugger-launchers/remote-gdb.bat||GHIDRA||||END|
|
||||||
data/debugger-launchers/ssh-gdb.bat||GHIDRA||||END|
|
data/debugger-launchers/ssh-gdb.bat||GHIDRA||||END|
|
||||||
data/debugger-launchers/ssh-gdbserver.bat||GHIDRA||||END|
|
data/debugger-launchers/ssh-gdbserver.bat||GHIDRA||||END|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
::@title gdb
|
::@title gdb
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>gdb</tt></h3>
|
::@desc <h3>Launch with <tt>gdb</tt></h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -14,6 +15,8 @@
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
::@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
||||||
::@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
::@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
||||||
|
::@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
||||||
|
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
set PYTHONPATH0=%GHIDRA_HOME%\Ghidra\Debug\Debugger-agent-gdb\pypkg\src
|
set PYTHONPATH0=%GHIDRA_HOME%\Ghidra\Debug\Debugger-agent-gdb\pypkg\src
|
||||||
|
@ -28,7 +31,20 @@ IF EXIST %GHIDRA_HOME%\ghidra\.git (
|
||||||
)
|
)
|
||||||
set PYTHONPATH=%PYTHONPATH1%;%PYTHONPATH0%;%PYTHONPATH%
|
set PYTHONPATH=%PYTHONPATH1%;%PYTHONPATH0%;%PYTHONPATH%
|
||||||
|
|
||||||
"%OPT_GDB_PATH%" ^
|
IF "%OPT_TARGET_IMG%"=="" (
|
||||||
|
"%OPT_GDB_PATH%" ^
|
||||||
|
-q ^
|
||||||
|
-ex "set pagination off" ^
|
||||||
|
-ex "set confirm off" ^
|
||||||
|
-ex "show version" ^
|
||||||
|
-ex "python import ghidragdb" ^
|
||||||
|
-ex "ghidra trace connect '%GHIDRA_TRACE_RMI_ADDR%'" ^
|
||||||
|
-ex "ghidra trace start" ^
|
||||||
|
-ex "ghidra trace sync-enable" ^
|
||||||
|
-ex "set confirm on" ^
|
||||||
|
-ex "set pagination on"
|
||||||
|
) ELSE (
|
||||||
|
"%OPT_GDB_PATH%" ^
|
||||||
-q ^
|
-q ^
|
||||||
-ex "set pagination off" ^
|
-ex "set pagination off" ^
|
||||||
-ex "set confirm off" ^
|
-ex "set confirm off" ^
|
||||||
|
@ -36,10 +52,10 @@ set PYTHONPATH=%PYTHONPATH1%;%PYTHONPATH0%;%PYTHONPATH%
|
||||||
-ex "python import ghidragdb" ^
|
-ex "python import ghidragdb" ^
|
||||||
-ex "target exec %OPT_TARGET_IMG%" ^
|
-ex "target exec %OPT_TARGET_IMG%" ^
|
||||||
-ex "set args %OPT_TARGET_ARGS%" ^
|
-ex "set args %OPT_TARGET_ARGS%" ^
|
||||||
-ex "set inferior-tty %TTY_TARGET%" ^
|
|
||||||
-ex "ghidra trace connect '%GHIDRA_TRACE_RMI_ADDR%'" ^
|
-ex "ghidra trace connect '%GHIDRA_TRACE_RMI_ADDR%'" ^
|
||||||
-ex "ghidra trace start" ^
|
-ex "ghidra trace start" ^
|
||||||
-ex "ghidra trace sync-enable" ^
|
-ex "ghidra trace sync-enable" ^
|
||||||
-ex "%OPT_START_CMD%" ^
|
-ex "%OPT_START_CMD%" ^
|
||||||
-ex "set confirm on" ^
|
-ex "set confirm on" ^
|
||||||
-ex "set pagination on"
|
-ex "set pagination on"
|
||||||
|
)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
#@title gdb
|
#@title gdb
|
||||||
|
#@image-opt arg:1
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with <tt>gdb</tt></h3>
|
#@desc <h3>Launch with <tt>gdb</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -26,10 +27,11 @@
|
||||||
#@icon icon.debugger
|
#@icon icon.debugger
|
||||||
#@help TraceRmiLauncherServicePlugin#gdb
|
#@help TraceRmiLauncherServicePlugin#gdb
|
||||||
#@enum StartCmd:str run start starti
|
#@enum StartCmd:str run start starti
|
||||||
#@arg :file "Image" "The target binary executable image"
|
#@arg :file "Image" "The target binary executable image, empty for no target"
|
||||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||||
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
||||||
#@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
#@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
||||||
|
#@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
||||||
#@env OPT_EXTRA_TTY:bool=false "Inferior TTY" "Provide a separate terminal emulator for the target."
|
#@env OPT_EXTRA_TTY:bool=false "Inferior TTY" "Provide a separate terminal emulator for the target."
|
||||||
#@tty TTY_TARGET if env:OPT_EXTRA_TTY
|
#@tty TTY_TARGET if env:OPT_EXTRA_TTY
|
||||||
|
|
||||||
|
@ -50,14 +52,31 @@ target_image="$1"
|
||||||
shift
|
shift
|
||||||
target_args="$@"
|
target_args="$@"
|
||||||
|
|
||||||
# NOTE: Ghidra will leave TTY_TARGET empty, which gdb takes for the same terminal.
|
# Ghidra will leave TTY_TARGET empty when OPT_EXTRA_TTY is false. Gdb takes empty to mean the same terminal.
|
||||||
|
|
||||||
"$OPT_GDB_PATH" \
|
if [ -z "$target_image" ]
|
||||||
|
then
|
||||||
|
"$OPT_GDB_PATH" \
|
||||||
-q \
|
-q \
|
||||||
-ex "set pagination off" \
|
-ex "set pagination off" \
|
||||||
-ex "set confirm off" \
|
-ex "set confirm off" \
|
||||||
-ex "show version" \
|
-ex "show version" \
|
||||||
-ex "python import ghidragdb" \
|
-ex "python import ghidragdb" \
|
||||||
|
-ex "set architecture $OPT_ARCH" \
|
||||||
|
-ex "set inferior-tty $TTY_TARGET" \
|
||||||
|
-ex "ghidra trace connect \"$GHIDRA_TRACE_RMI_ADDR\"" \
|
||||||
|
-ex "ghidra trace start" \
|
||||||
|
-ex "ghidra trace sync-enable" \
|
||||||
|
-ex "set confirm on" \
|
||||||
|
-ex "set pagination on"
|
||||||
|
else
|
||||||
|
"$OPT_GDB_PATH" \
|
||||||
|
-q \
|
||||||
|
-ex "set pagination off" \
|
||||||
|
-ex "set confirm off" \
|
||||||
|
-ex "show version" \
|
||||||
|
-ex "python import ghidragdb" \
|
||||||
|
-ex "set architecture $OPT_ARCH" \
|
||||||
-ex "file \"$target_image\"" \
|
-ex "file \"$target_image\"" \
|
||||||
-ex "set args $target_args" \
|
-ex "set args $target_args" \
|
||||||
-ex "set inferior-tty $TTY_TARGET" \
|
-ex "set inferior-tty $TTY_TARGET" \
|
||||||
|
@ -67,3 +86,4 @@ target_args="$@"
|
||||||
-ex "$OPT_START_CMD" \
|
-ex "$OPT_START_CMD" \
|
||||||
-ex "set confirm on" \
|
-ex "set confirm on" \
|
||||||
-ex "set pagination on"
|
-ex "set pagination on"
|
||||||
|
fi
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
::@title qemu + gdb
|
::@title qemu + gdb
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>qemu</tt> and connect with <tt>gdb</tt></h3>
|
::@desc <h3>Launch with <tt>qemu</tt> and connect with <tt>gdb</tt></h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -10,7 +11,7 @@
|
||||||
::@menu-group cross
|
::@menu-group cross
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#gdb_qemu
|
::@help TraceRmiLauncherServicePlugin#gdb_qemu
|
||||||
::@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image"
|
::@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image"
|
||||||
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env GHIDRA_LANG_EXTTOOL_qemu:file="" "QEMU command" "The path to qemu for the target architecture."
|
::@env GHIDRA_LANG_EXTTOOL_qemu:file="" "QEMU command" "The path to qemu for the target architecture."
|
||||||
::@env QEMU_GDB:int=1234 "QEMU Port" "Port for gdb connection to qemu"
|
::@env QEMU_GDB:int=1234 "QEMU Port" "Port for gdb connection to qemu"
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
#@title qemu + gdb
|
#@title qemu + gdb
|
||||||
|
#@image-opt arg:1
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with <tt>qemu</tt> and connect with <tt>gdb</tt></h3>
|
#@desc <h3>Launch with <tt>qemu</tt> and connect with <tt>gdb</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
#@menu-group cross
|
#@menu-group cross
|
||||||
#@icon icon.debugger
|
#@icon icon.debugger
|
||||||
#@help TraceRmiLauncherServicePlugin#gdb_qemu
|
#@help TraceRmiLauncherServicePlugin#gdb_qemu
|
||||||
#@arg :file "Image" "The target binary executable image"
|
#@arg :file! "Image" "The target binary executable image"
|
||||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||||
#@env GHIDRA_LANG_EXTTOOL_qemu:file="" "QEMU command" "The path to qemu for the target architecture."
|
#@env GHIDRA_LANG_EXTTOOL_qemu:file="" "QEMU command" "The path to qemu for the target architecture."
|
||||||
#@env QEMU_GDB:int=1234 "QEMU Port" "Port for gdb connection to qemu"
|
#@env QEMU_GDB:int=1234 "QEMU Port" "Port for gdb connection to qemu"
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
::@title raw gdb
|
|
||||||
::@no-image
|
|
||||||
::@desc <html><body width="300px">
|
|
||||||
::@desc <h3>Start <tt>gdb</tt></h3>
|
|
||||||
::@desc <p>
|
|
||||||
::@desc This will start <tt>gdb</tt> and connect to it.
|
|
||||||
::@desc It will not launch a target, so you can (must) set up your target manually.
|
|
||||||
::@desc For setup instructions, press <b>F1</b>.
|
|
||||||
::@desc </p>
|
|
||||||
::@desc </body></html>
|
|
||||||
::@menu-group raw
|
|
||||||
::@icon icon.debugger
|
|
||||||
::@help TraceRmiLauncherServicePlugin#gdb_raw
|
|
||||||
::@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
|
||||||
::@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
|
||||||
|
|
||||||
@echo off
|
|
||||||
set PYTHONPATH0=%GHIDRA_HOME%\Ghidra\Debug\Debugger-agent-gdb\pypkg\src
|
|
||||||
set PYTHONPATH1=%GHIDRA_HOME%\Ghidra\Debug\Debugger-rmi-trace\pypkg\src
|
|
||||||
IF EXIST %GHIDRA_HOME%\.git (
|
|
||||||
set PYTHONPATH0=%GHIDRA_HOME%\Ghidra\Debug\Debugger-agent-gdb\build\pypkg\src
|
|
||||||
set PYTHONPATH1=%GHIDRA_HOME%\Ghidra\Debug\Debugger-rmi-trace\build\pypkg\src
|
|
||||||
)
|
|
||||||
IF EXIST %GHIDRA_HOME%\ghidra\.git (
|
|
||||||
set PYTHONPATH0=%GHIDRA_HOME%\ghidra\Ghidra\Debug\Debugger-agent-gdb\build\pypkg\src
|
|
||||||
set PYTHONPATH1=%GHIDRA_HOME%\ghidra\Ghidra\Debug\Debugger-rmi-trace\build\pypkg\src
|
|
||||||
)
|
|
||||||
set PYTHONPATH=%PYTHONPATH1%;%PYTHONPATH0%;%PYTHONPATH%
|
|
||||||
|
|
||||||
"%OPT_GDB_PATH%" ^
|
|
||||||
-q ^
|
|
||||||
-ex "set pagination off" ^
|
|
||||||
-ex "set confirm off" ^
|
|
||||||
-ex "show version" ^
|
|
||||||
-ex "python import ghidragdb" ^
|
|
||||||
-ex "set architecture %OPT_ARCH%" ^
|
|
||||||
-ex "ghidra trace connect '%GHIDRA_TRACE_RMI_ADDR%'" ^
|
|
||||||
-ex "ghidra trace start" ^
|
|
||||||
-ex "ghidra trace sync-enable" ^
|
|
||||||
-ex "set confirm on" ^
|
|
||||||
-ex "set pagination on"
|
|
|
@ -1,57 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
## ###
|
|
||||||
# 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.
|
|
||||||
##
|
|
||||||
#@title raw gdb
|
|
||||||
#@no-image
|
|
||||||
#@desc <html><body width="300px">
|
|
||||||
#@desc <h3>Start <tt>gdb</tt></h3>
|
|
||||||
#@desc <p>
|
|
||||||
#@desc This will start <tt>gdb</tt> and connect to it.
|
|
||||||
#@desc It will not launch a target, so you can (must) set up your target manually.
|
|
||||||
#@desc For setup instructions, press <b>F1</b>.
|
|
||||||
#@desc </p>
|
|
||||||
#@desc </body></html>
|
|
||||||
#@menu-group raw
|
|
||||||
#@icon icon.debugger
|
|
||||||
#@help TraceRmiLauncherServicePlugin#gdb_raw
|
|
||||||
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
|
||||||
#@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
|
||||||
|
|
||||||
if [ -d ${GHIDRA_HOME}/ghidra/.git ]
|
|
||||||
then
|
|
||||||
export PYTHONPATH=$GHIDRA_HOME/ghidra/Ghidra/Debug/Debugger-agent-gdb/build/pypkg/src:$PYTHONPATH
|
|
||||||
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-agent-gdb/build/pypkg/src:$PYTHONPATH
|
|
||||||
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH
|
|
||||||
else
|
|
||||||
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-agent-gdb/pypkg/src:$PYTHONPATH
|
|
||||||
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/pypkg/src:$PYTHONPATH
|
|
||||||
fi
|
|
||||||
|
|
||||||
"$OPT_GDB_PATH" \
|
|
||||||
-q \
|
|
||||||
-ex "set pagination off" \
|
|
||||||
-ex "set confirm off" \
|
|
||||||
-ex "show version" \
|
|
||||||
-ex "python import ghidragdb" \
|
|
||||||
-ex "set architecture $OPT_ARCH" \
|
|
||||||
-ex "ghidra trace connect \"$GHIDRA_TRACE_RMI_ADDR\"" \
|
|
||||||
-ex "ghidra trace start" \
|
|
||||||
-ex "ghidra trace sync-enable" \
|
|
||||||
-ex "set confirm on" \
|
|
||||||
-ex "set pagination on"
|
|
|
@ -1,5 +1,4 @@
|
||||||
::@title remote gdb
|
::@title remote gdb
|
||||||
::@no-image
|
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with local <tt>gdb</tt> and connect to a stub (e.g., <tt>gdbserver</tt>)</h3>
|
::@desc <h3>Launch with local <tt>gdb</tt> and connect to a stub (e.g., <tt>gdbserver</tt>)</h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -14,7 +13,7 @@
|
||||||
::@env OPT_TARGET_TYPE:TargetType="remote" "Target" "The type of remote target"
|
::@env OPT_TARGET_TYPE:TargetType="remote" "Target" "The type of remote target"
|
||||||
::@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
::@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
||||||
::@env OPT_PORT:int=9999 "Port" "The host's listening port"
|
::@env OPT_PORT:int=9999 "Port" "The host's listening port"
|
||||||
::@env OPT_ARCH:str="" "Architecture (optional)" "Target architecture override"
|
::@env OPT_ARCH:str="auto" "Architecture" "Target architecture override"
|
||||||
::@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb on the local system. Omit the full path to resolve using the system PATH."
|
::@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb on the local system. Omit the full path to resolve using the system PATH."
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
|
@ -30,19 +29,13 @@ IF EXIST %GHIDRA_HOME%\ghidra\.git (
|
||||||
)
|
)
|
||||||
set PYTHONPATH=%PYTHONPATH1%;%PYTHONPATH0%;%PYTHONPATH%
|
set PYTHONPATH=%PYTHONPATH1%;%PYTHONPATH0%;%PYTHONPATH%
|
||||||
|
|
||||||
IF "%OPT_ARCH%"=="" (
|
|
||||||
set archcmd=
|
|
||||||
) ELSE (
|
|
||||||
set archcmd=-ex "set arch %OPT_ARCH%"
|
|
||||||
)
|
|
||||||
|
|
||||||
"%OPT_GDB_PATH%" ^
|
"%OPT_GDB_PATH%" ^
|
||||||
-q ^
|
-q ^
|
||||||
-ex "set pagination off" ^
|
-ex "set pagination off" ^
|
||||||
-ex "set confirm off" ^
|
-ex "set confirm off" ^
|
||||||
-ex "show version" ^
|
-ex "show version" ^
|
||||||
-ex "python import ghidragdb" ^
|
-ex "python import ghidragdb" ^
|
||||||
%archcmd% ^
|
-ex "set arch %OPT_ARCH%" ^
|
||||||
-ex "echo Connecting to %OPT_HOST%:%OPT_PORT%... " ^
|
-ex "echo Connecting to %OPT_HOST%:%OPT_PORT%... " ^
|
||||||
-ex "target %OPT_TARGET_TYPE% %OPT_HOST%:%OPT_PORT%" ^
|
-ex "target %OPT_TARGET_TYPE% %OPT_HOST%:%OPT_PORT%" ^
|
||||||
-ex "ghidra trace connect '%GHIDRA_TRACE_RMI_ADDR%'" ^
|
-ex "ghidra trace connect '%GHIDRA_TRACE_RMI_ADDR%'" ^
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
#@title remote gdb
|
#@title remote gdb
|
||||||
#@no-image
|
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with local <tt>gdb</tt> and connect to a stub (e.g., <tt>gdbserver</tt>)</h3>
|
#@desc <h3>Launch with local <tt>gdb</tt> and connect to a stub (e.g., <tt>gdbserver</tt>)</h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -30,7 +29,7 @@
|
||||||
#@env OPT_TARGET_TYPE:TargetType="remote" "Target" "The type of remote target"
|
#@env OPT_TARGET_TYPE:TargetType="remote" "Target" "The type of remote target"
|
||||||
#@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
#@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
||||||
#@env OPT_PORT:int=9999 "Port" "The host's listening port"
|
#@env OPT_PORT:int=9999 "Port" "The host's listening port"
|
||||||
#@env OPT_ARCH:str="" "Architecture (optional)" "Target architecture override"
|
#@env OPT_ARCH:str="auto" "Architecture" "Target architecture override"
|
||||||
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb on the local system. Omit the full path to resolve using the system PATH."
|
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb on the local system. Omit the full path to resolve using the system PATH."
|
||||||
|
|
||||||
if [ -d ${GHIDRA_HOME}/ghidra/.git ]
|
if [ -d ${GHIDRA_HOME}/ghidra/.git ]
|
||||||
|
@ -46,20 +45,13 @@ else
|
||||||
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/pypkg/src:$PYTHONPATH
|
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/pypkg/src:$PYTHONPATH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$OPT_ARCH" ]
|
|
||||||
then
|
|
||||||
archcmd=
|
|
||||||
else
|
|
||||||
archcmd=-ex "set arch $OPT_ARCH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
"$OPT_GDB_PATH" \
|
"$OPT_GDB_PATH" \
|
||||||
-q \
|
-q \
|
||||||
-ex "set pagination off" \
|
-ex "set pagination off" \
|
||||||
-ex "set confirm off" \
|
-ex "set confirm off" \
|
||||||
-ex "show version" \
|
-ex "show version" \
|
||||||
-ex "python import ghidragdb" \
|
-ex "python import ghidragdb" \
|
||||||
$archcmd \
|
-ex "set arch $OPT_ARCH" \
|
||||||
-ex "echo Connecting to $OPT_HOST:$OPT_PORT... " \
|
-ex "echo Connecting to $OPT_HOST:$OPT_PORT... " \
|
||||||
-ex "target $OPT_TARGET_TYPE $OPT_HOST:$OPT_PORT" \
|
-ex "target $OPT_TARGET_TYPE $OPT_HOST:$OPT_PORT" \
|
||||||
-ex "ghidra trace connect \"$GHIDRA_TRACE_RMI_ADDR\"" \
|
-ex "ghidra trace connect \"$GHIDRA_TRACE_RMI_ADDR\"" \
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
::@timeout 60000
|
::@timeout 60000
|
||||||
::@title gdb via ssh
|
::@title gdb via ssh
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>gdb</tt> via <tt>ssh</tt></h3>
|
::@desc <h3>Launch with <tt>gdb</tt> via <tt>ssh</tt></h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -19,14 +20,31 @@
|
||||||
::@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
|
::@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
|
||||||
::@env OPT_GDB_PATH:str="gdb" "gdb command" "The path to gdb on the remote system. Omit the full path to resolve using the system PATH."
|
::@env OPT_GDB_PATH:str="gdb" "gdb command" "The path to gdb on the remote system. Omit the full path to resolve using the system PATH."
|
||||||
::@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
::@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
||||||
|
::@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
set cmd=TERM='%TERM%' '%OPT_GDB_PATH%' ^
|
|
||||||
|
IF "%OPT_TARGET_IMG%" == "" (
|
||||||
|
set cmd=TERM='%TERM%' '%OPT_GDB_PATH%' ^
|
||||||
-q ^
|
-q ^
|
||||||
-ex 'set pagination off' ^
|
-ex 'set pagination off' ^
|
||||||
-ex 'set confirm off' ^
|
-ex 'set confirm off' ^
|
||||||
-ex 'show version' ^
|
-ex 'show version' ^
|
||||||
-ex 'python import ghidragdb' ^
|
-ex 'python import ghidragdb' ^
|
||||||
|
-ex 'set architecture %OPT_ARCH%' ^
|
||||||
|
-ex 'ghidra trace connect \"localhost:%OPT_REMOTE_PORT%\"' ^
|
||||||
|
-ex 'ghidra trace start' ^
|
||||||
|
-ex 'ghidra trace sync-enable' ^
|
||||||
|
-ex 'set confirm on' ^
|
||||||
|
-ex 'set pagination on'
|
||||||
|
) ELSE (
|
||||||
|
set cmd=TERM='%TERM%' '%OPT_GDB_PATH%' ^
|
||||||
|
-q ^
|
||||||
|
-ex 'set pagination off' ^
|
||||||
|
-ex 'set confirm off' ^
|
||||||
|
-ex 'show version' ^
|
||||||
|
-ex 'python import ghidragdb' ^
|
||||||
|
-ex 'set architecture %OPT_ARCH%' ^
|
||||||
-ex 'file \"%OPT_TARGET_IMG%\"' ^
|
-ex 'file \"%OPT_TARGET_IMG%\"' ^
|
||||||
-ex 'set args %OPT_TARGET_ARGS%' ^
|
-ex 'set args %OPT_TARGET_ARGS%' ^
|
||||||
-ex 'ghidra trace connect \"localhost:%OPT_REMOTE_PORT%\"' ^
|
-ex 'ghidra trace connect \"localhost:%OPT_REMOTE_PORT%\"' ^
|
||||||
|
@ -35,5 +53,6 @@ set cmd=TERM='%TERM%' '%OPT_GDB_PATH%' ^
|
||||||
-ex '%OPT_START_CMD%' ^
|
-ex '%OPT_START_CMD%' ^
|
||||||
-ex 'set confirm on' ^
|
-ex 'set confirm on' ^
|
||||||
-ex 'set pagination on'
|
-ex 'set pagination on'
|
||||||
|
)
|
||||||
|
|
||||||
"%OPT_SSH_PATH%" "-R%OPT_REMOTE_PORT%:%GHIDRA_TRACE_RMI_ADDR%" -t %OPT_EXTRA_SSH_ARGS% "%OPT_HOST%" "%cmd%"
|
"%OPT_SSH_PATH%" "-R%OPT_REMOTE_PORT%:%GHIDRA_TRACE_RMI_ADDR%" -t %OPT_EXTRA_SSH_ARGS% "%OPT_HOST%" "%cmd%"
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
##
|
##
|
||||||
#@timeout 60000
|
#@timeout 60000
|
||||||
#@title gdb via ssh
|
#@title gdb via ssh
|
||||||
|
#@image-opt arg:1
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with <tt>gdb</tt> via <tt>ssh</tt></h3>
|
#@desc <h3>Launch with <tt>gdb</tt> via <tt>ssh</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -29,23 +30,40 @@
|
||||||
#@enum StartCmd:str run start starti
|
#@enum StartCmd:str run start starti
|
||||||
#@arg :str "Image" "The target binary executable image on the remote system"
|
#@arg :str "Image" "The target binary executable image on the remote system"
|
||||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||||
#@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
|
#@env OPT_SSH_PATH:file!="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
|
||||||
#@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
|
#@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
|
||||||
#@env OPT_REMOTE_PORT:int=12345 "Remote Trace RMI Port" "A free port on the remote end to receive and forward the Trace RMI connection."
|
#@env OPT_REMOTE_PORT:int=12345 "Remote Trace RMI Port" "A free port on the remote end to receive and forward the Trace RMI connection."
|
||||||
#@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
|
#@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
|
||||||
#@env OPT_GDB_PATH:str="gdb" "gdb command" "The path to gdb on the remote system. Omit the full path to resolve using the system PATH."
|
#@env OPT_GDB_PATH:str="gdb" "gdb command" "The path to gdb on the remote system. Omit the full path to resolve using the system PATH."
|
||||||
#@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
#@env OPT_START_CMD:StartCmd="starti" "Run command" "The gdb command to actually run the target."
|
||||||
|
#@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
||||||
|
|
||||||
target_image="$1"
|
target_image="$1"
|
||||||
shift
|
shift
|
||||||
target_args="$@"
|
target_args="$@"
|
||||||
|
|
||||||
"$OPT_SSH_PATH" "-R$OPT_REMOTE_PORT:$GHIDRA_TRACE_RMI_ADDR" -t $OPT_EXTRA_SSH_ARGS "$OPT_HOST" "TERM='$TERM' '$OPT_GDB_PATH' \
|
if [ -z "$target_image" ]
|
||||||
|
then
|
||||||
|
"$OPT_SSH_PATH" "-R$OPT_REMOTE_PORT:$GHIDRA_TRACE_RMI_ADDR" -t $OPT_EXTRA_SSH_ARGS "$OPT_HOST" "TERM='$TERM' '$OPT_GDB_PATH' \
|
||||||
-q \
|
-q \
|
||||||
-ex 'set pagination off' \
|
-ex 'set pagination off' \
|
||||||
-ex 'set confirm off' \
|
-ex 'set confirm off' \
|
||||||
-ex 'show version' \
|
-ex 'show version' \
|
||||||
-ex 'python import ghidragdb' \
|
-ex 'python import ghidragdb' \
|
||||||
|
-ex 'set architecture $OPT_ARCH' \
|
||||||
|
-ex 'ghidra trace connect \"localhost:$OPT_REMOTE_PORT\"' \
|
||||||
|
-ex 'ghidra trace start' \
|
||||||
|
-ex 'ghidra trace sync-enable' \
|
||||||
|
-ex 'set confirm on' \
|
||||||
|
-ex 'set pagination on'"
|
||||||
|
else
|
||||||
|
"$OPT_SSH_PATH" "-R$OPT_REMOTE_PORT:$GHIDRA_TRACE_RMI_ADDR" -t $OPT_EXTRA_SSH_ARGS "$OPT_HOST" "TERM='$TERM' '$OPT_GDB_PATH' \
|
||||||
|
-q \
|
||||||
|
-ex 'set pagination off' \
|
||||||
|
-ex 'set confirm off' \
|
||||||
|
-ex 'show version' \
|
||||||
|
-ex 'python import ghidragdb' \
|
||||||
|
-ex 'set architecture $OPT_ARCH' \
|
||||||
-ex 'file \"$target_image\"' \
|
-ex 'file \"$target_image\"' \
|
||||||
-ex 'set args $target_args' \
|
-ex 'set args $target_args' \
|
||||||
-ex 'ghidra trace connect \"localhost:$OPT_REMOTE_PORT\"' \
|
-ex 'ghidra trace connect \"localhost:$OPT_REMOTE_PORT\"' \
|
||||||
|
@ -54,3 +72,4 @@ target_args="$@"
|
||||||
-ex '$OPT_START_CMD' \
|
-ex '$OPT_START_CMD' \
|
||||||
-ex 'set confirm on' \
|
-ex 'set confirm on' \
|
||||||
-ex 'set pagination on'"
|
-ex 'set pagination on'"
|
||||||
|
fi
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
::@timeout 60000
|
::@timeout 60000
|
||||||
::@title gdb + gdbserver via ssh
|
::@title gdb + gdbserver via ssh
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with local <tt>gdb</tt> and <tt>gdbserver</tt> via <tt>ssh</tt></h3>
|
::@desc <h3>Launch with local <tt>gdb</tt> and <tt>gdbserver</tt> via <tt>ssh</tt></h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -10,7 +11,7 @@
|
||||||
::@menu-group remote
|
::@menu-group remote
|
||||||
::@icon icon.debugger
|
::@icon icon.debugger
|
||||||
::@help TraceRmiLauncherServicePlugin#gdb_gdbserver_ssh
|
::@help TraceRmiLauncherServicePlugin#gdb_gdbserver_ssh
|
||||||
::@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image on the remote system"
|
::@env OPT_TARGET_IMG: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"
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
|
::@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
|
||||||
::@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
|
::@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
##
|
##
|
||||||
#@timeout 60000
|
#@timeout 60000
|
||||||
#@title gdb + gdbserver via ssh
|
#@title gdb + gdbserver via ssh
|
||||||
|
#@image-opt arg:1
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with local <tt>gdb</tt> and <tt>gdbserver</tt> via <tt>ssh</tt></h3>
|
#@desc <h3>Launch with local <tt>gdb</tt> and <tt>gdbserver</tt> via <tt>ssh</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -26,9 +27,9 @@
|
||||||
#@menu-group remote
|
#@menu-group remote
|
||||||
#@icon icon.debugger
|
#@icon icon.debugger
|
||||||
#@help TraceRmiLauncherServicePlugin#gdb_gdbserver_ssh
|
#@help TraceRmiLauncherServicePlugin#gdb_gdbserver_ssh
|
||||||
#@arg :str "Image" "The target binary executable image on the remote system"
|
#@arg :str! "Image" "The target binary executable image on the remote system"
|
||||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||||
#@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
|
#@env OPT_SSH_PATH:file!="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
|
||||||
#@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
|
#@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
|
||||||
#@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
|
#@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
|
||||||
#@env OPT_GDBSERVER_PATH:str="gdbserver" "gdbserver command (remote)" "The path to gdbserver on the remote system. Omit the full path to resolve using the system PATH."
|
#@env OPT_GDBSERVER_PATH:str="gdbserver" "gdbserver command (remote)" "The path to gdbserver on the remote system. Omit the full path to resolve using the system PATH."
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
#@title wine + gdb
|
#@title wine + gdb
|
||||||
|
#@image-opt arg:1
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with <tt>gdb</tt> and <tt>wine</tt></h3>
|
#@desc <h3>Launch with <tt>gdb</tt> and <tt>wine</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -25,10 +26,11 @@
|
||||||
#@menu-group cross
|
#@menu-group cross
|
||||||
#@icon icon.debugger
|
#@icon icon.debugger
|
||||||
#@help TraceRmiLauncherServicePlugin#gdb_wine
|
#@help TraceRmiLauncherServicePlugin#gdb_wine
|
||||||
#@arg :file "Image" "The target binary executable image"
|
#@arg :file! "Image" "The target binary executable image"
|
||||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||||
#@env OPT_WINE_PATH:file="/usr/lib/wine/wine64" "Path to wine binary" "The path to the wine executable for your target architecture."
|
#@env OPT_WINE_PATH:file="/usr/lib/wine/wine64" "Path to wine binary" "The path to the wine executable for your target architecture."
|
||||||
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
#@env OPT_GDB_PATH:file="gdb" "gdb command" "The path to gdb. Omit the full path to resolve using the system PATH."
|
||||||
|
#@env OPT_ARCH:str="i386:x86-64" "Architecture" "Target architecture"
|
||||||
#@env OPT_EXTRA_TTY:bool=false "Inferior TTY" "Provide a separate terminal emulator for the target."
|
#@env OPT_EXTRA_TTY:bool=false "Inferior TTY" "Provide a separate terminal emulator for the target."
|
||||||
#@tty TTY_TARGET if env:OPT_EXTRA_TTY
|
#@tty TTY_TARGET if env:OPT_EXTRA_TTY
|
||||||
|
|
||||||
|
@ -53,6 +55,7 @@ fi
|
||||||
-ex "set confirm off" \
|
-ex "set confirm off" \
|
||||||
-ex "show version" \
|
-ex "show version" \
|
||||||
-ex "python import ghidragdb.wine" \
|
-ex "python import ghidragdb.wine" \
|
||||||
|
-ex "set architecture $OPT_ARCH" \
|
||||||
-ex "file \"$OPT_WINE_PATH\"" \
|
-ex "file \"$OPT_WINE_PATH\"" \
|
||||||
-ex "set args $@" \
|
-ex "set args $@" \
|
||||||
-ex "set inferior-tty $TTY_TARGET" \
|
-ex "set inferior-tty $TTY_TARGET" \
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
::@title lldb
|
::@title lldb
|
||||||
|
::@image-opt arg:1
|
||||||
::@desc <html><body width="300px">
|
::@desc <html><body width="300px">
|
||||||
::@desc <h3>Launch with <tt>lldb</tt></h3>
|
::@desc <h3>Launch with <tt>lldb</tt></h3>
|
||||||
::@desc <p>
|
::@desc <p>
|
||||||
|
@ -14,8 +15,6 @@
|
||||||
::@args "Arguments" "Command-line arguments to pass to the target"
|
::@args "Arguments" "Command-line arguments to pass to the target"
|
||||||
::@env OPT_LLDB_PATH:file="lldb" "lldb command" "The path to lldb. Omit the full path to resolve using the system PATH."
|
::@env OPT_LLDB_PATH:file="lldb" "lldb command" "The path to lldb. Omit the full path to resolve using the system PATH."
|
||||||
::@env OPT_START_CMD:StartCmd="process launch" "Run command" "The lldb command to actually run the target."
|
::@env OPT_START_CMD:StartCmd="process launch" "Run command" "The lldb command to actually run the target."
|
||||||
::@env OPT_EXTRA_TTY:bool=false "Target TTY" "Provide a separate terminal emulator for the target."
|
|
||||||
::@tty TTY_TARGET if env:OPT_EXTRA_TTY
|
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
set PYTHONPATH0=%GHIDRA_HOME%\Ghidra\Debug\Debugger-agent-gdb\pypkg\src
|
set PYTHONPATH0=%GHIDRA_HOME%\Ghidra\Debug\Debugger-agent-gdb\pypkg\src
|
||||||
|
@ -38,17 +37,21 @@ IF DEFINED target_args (
|
||||||
argspart=-o "settings set target.run-args %target_args%"
|
argspart=-o "settings set target.run-args %target_args%"
|
||||||
)
|
)
|
||||||
|
|
||||||
IF DEFINED TARGET_TTY (
|
IF "%target_image%"=="" (
|
||||||
ttypart=-o "settings set target.output-path %TTY_TARGET%" -o "settings set target.input-path $TTY_TARGET"
|
"%OPT_LLDB_PATH%" ^
|
||||||
)
|
-o "version" ^
|
||||||
|
-o "script import ghidralldb" ^
|
||||||
"%OPT_LLDB_PATH%" ^
|
-o "ghidra trace connect %GHIDRA_TRACE_RMI_ADDR%" ^
|
||||||
|
-o "ghidra trace start" ^
|
||||||
|
-o "ghidra trace sync-enable" ^
|
||||||
|
) ELSE (
|
||||||
|
"%OPT_LLDB_PATH%" ^
|
||||||
-o "version" ^
|
-o "version" ^
|
||||||
-o "script import ghidralldb" ^
|
-o "script import ghidralldb" ^
|
||||||
-o "target create %target_image%" ^
|
-o "target create %target_image%" ^
|
||||||
%argspart% ^
|
%argspart% ^
|
||||||
%ttypart% ^
|
|
||||||
-o "ghidra trace connect %GHIDRA_TRACE_RMI_ADDR%" ^
|
-o "ghidra trace connect %GHIDRA_TRACE_RMI_ADDR%" ^
|
||||||
-o "ghidra trace start" ^
|
-o "ghidra trace start" ^
|
||||||
-o "ghidra trace sync-enable" ^
|
-o "ghidra trace sync-enable" ^
|
||||||
-o "%OPT_START_CMD%"
|
-o "%OPT_START_CMD%"
|
||||||
|
)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
#@title lldb
|
#@title lldb
|
||||||
|
#@image-opt arg:1
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with <tt>lldb</tt></h3>
|
#@desc <h3>Launch with <tt>lldb</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -64,7 +65,17 @@ else
|
||||||
ttypart=-o "settings set target.output-path $TTY_TARGET" -o "settings set target.input-path $TTY_TARGET"
|
ttypart=-o "settings set target.output-path $TTY_TARGET" -o "settings set target.input-path $TTY_TARGET"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
"$OPT_LLDB_PATH" \
|
if [ -z "$target_image" ]
|
||||||
|
then
|
||||||
|
"$OPT_LLDB_PATH" \
|
||||||
|
-o "version" \
|
||||||
|
-o "script import ghidralldb" \
|
||||||
|
$ttypart \
|
||||||
|
-o "ghidra trace connect \"$GHIDRA_TRACE_RMI_ADDR\"" \
|
||||||
|
-o "ghidra trace start" \
|
||||||
|
-o "ghidra trace sync-enable"
|
||||||
|
else
|
||||||
|
"$OPT_LLDB_PATH" \
|
||||||
-o "version" \
|
-o "version" \
|
||||||
-o "script import ghidralldb" \
|
-o "script import ghidralldb" \
|
||||||
-o "target create \"$target_image\"" \
|
-o "target create \"$target_image\"" \
|
||||||
|
@ -74,3 +85,4 @@ fi
|
||||||
-o "ghidra trace start" \
|
-o "ghidra trace start" \
|
||||||
-o "ghidra trace sync-enable" \
|
-o "ghidra trace sync-enable" \
|
||||||
-o "$OPT_START_CMD"
|
-o "$OPT_START_CMD"
|
||||||
|
fi
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
##
|
##
|
||||||
#@title remote lldb
|
#@title remote lldb
|
||||||
#@no-image
|
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Launch with local <tt>lldb</tt> and connect to a stub (e.g., <tt>gdbserver</tt>)</h3>
|
#@desc <h3>Launch with local <tt>lldb</tt> and connect to a stub (e.g., <tt>gdbserver</tt>)</h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
@ -60,4 +59,3 @@ fi
|
||||||
-o "ghidra trace start" \
|
-o "ghidra trace start" \
|
||||||
-o "ghidra trace sync-enable" \
|
-o "ghidra trace sync-enable" \
|
||||||
-o "ghidra trace sync-synth-stopped"
|
-o "ghidra trace sync-synth-stopped"
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.debug.api;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public record ValStr<T>(T val, String str) {
|
public record ValStr<T>(T val, String str) {
|
||||||
|
@ -56,4 +57,18 @@ public record ValStr<T>(T val, String str) {
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(Entry::getKey, e -> e.getValue().val()));
|
.collect(Collectors.toMap(Entry::getKey, e -> e.getValue().val()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String normStr(ValStr<?> val) {
|
||||||
|
if (val == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return val.normStr();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String normStr() {
|
||||||
|
if (val == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return Objects.toString(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,10 +295,29 @@ public interface TraceRmiLaunchOffer {
|
||||||
*/
|
*/
|
||||||
Map<String, LaunchParameter<?>> getParameters();
|
Map<String, LaunchParameter<?>> getParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If present, get the parameter via which this offer expects to receive the current program
|
||||||
|
*
|
||||||
|
* @return the parameter, or null
|
||||||
|
*/
|
||||||
|
LaunchParameter<?> imageParameter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this offer presents a parameter for the open program
|
||||||
|
*
|
||||||
|
* @return true if present
|
||||||
|
*/
|
||||||
|
default boolean supportsImage() {
|
||||||
|
return imageParameter() != null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this offer requires an open program
|
* Check if this offer requires an open program
|
||||||
*
|
*
|
||||||
* @return true if required
|
* @return true if required
|
||||||
*/
|
*/
|
||||||
boolean requiresImage();
|
default boolean requiresImage() {
|
||||||
|
LaunchParameter<?> param = imageParameter();
|
||||||
|
return param != null && param.required();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
#@title raw python
|
#@title raw python
|
||||||
#@no-image
|
|
||||||
#@desc <html><body width="300px">
|
#@desc <html><body width="300px">
|
||||||
#@desc <h3>Start <tt>gdb</tt></h3>
|
#@desc <h3>Start <tt>gdb</tt></h3>
|
||||||
#@desc <p>
|
#@desc <p>
|
||||||
|
|
|
@ -124,7 +124,7 @@ public abstract class AbstractScriptTraceRmiLaunchOffer extends AbstractTraceRmi
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresImage() {
|
public LaunchParameter<?> imageParameter() {
|
||||||
return !attrs.noImage();
|
return attrs.imageOpt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,6 @@ import ghidra.util.task.Task;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer {
|
public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer {
|
||||||
public static final String PARAM_DISPLAY_IMAGE = "Image";
|
|
||||||
public static final String PREFIX_PARAM_EXTTOOL = "env:GHIDRA_LANG_EXTTOOL_";
|
public static final String PREFIX_PARAM_EXTTOOL = "env:GHIDRA_LANG_EXTTOOL_";
|
||||||
|
|
||||||
public static final int DEFAULT_TIMEOUT_MILLIS = 10000;
|
public static final int DEFAULT_TIMEOUT_MILLIS = 10000;
|
||||||
|
@ -299,15 +298,10 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
||||||
protected Map<String, ValStr<?>> generateDefaultLauncherArgs(
|
protected Map<String, ValStr<?>> generateDefaultLauncherArgs(
|
||||||
Map<String, LaunchParameter<?>> params) {
|
Map<String, LaunchParameter<?>> params) {
|
||||||
Map<String, ValStr<?>> map = new LinkedHashMap<>();
|
Map<String, ValStr<?>> map = new LinkedHashMap<>();
|
||||||
ImageParamSetter imageSetter = null;
|
|
||||||
for (Entry<String, LaunchParameter<?>> entry : params.entrySet()) {
|
for (Entry<String, LaunchParameter<?>> entry : params.entrySet()) {
|
||||||
LaunchParameter<?> param = entry.getValue();
|
LaunchParameter<?> param = entry.getValue();
|
||||||
map.put(entry.getKey(), ValStr.cast(Object.class, param.defaultValue()));
|
map.put(entry.getKey(), ValStr.cast(Object.class, param.defaultValue()));
|
||||||
if (PARAM_DISPLAY_IMAGE.equals(param.display())) {
|
if (param.name().startsWith(PREFIX_PARAM_EXTTOOL)) {
|
||||||
imageSetter = ImageParamSetter.get(param);
|
|
||||||
// May still be null if type is not supported
|
|
||||||
}
|
|
||||||
else if (param.name().startsWith(PREFIX_PARAM_EXTTOOL)) {
|
|
||||||
String tool = param.name().substring(PREFIX_PARAM_EXTTOOL.length());
|
String tool = param.name().substring(PREFIX_PARAM_EXTTOOL.length());
|
||||||
List<String> names =
|
List<String> names =
|
||||||
program.getLanguage().getLanguageDescription().getExternalNames(tool);
|
program.getLanguage().getLanguageDescription().getExternalNames(tool);
|
||||||
|
@ -328,7 +322,8 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (imageSetter != null && program != null) {
|
if (supportsImage() && program != null) {
|
||||||
|
ImageParamSetter imageSetter = ImageParamSetter.get(imageParameter());
|
||||||
imageSetter.setImage(map, program);
|
imageSetter.setImage(map, program);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
|
@ -559,9 +554,18 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
||||||
return auto == null ? ByModuleAutoMapSpec.instance() : auto.getAutoMapSpec(trace);
|
return auto == null ? ByModuleAutoMapSpec.instance() : auto.getAutoMapSpec(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initializeMonitor(TaskMonitor monitor) {
|
protected boolean providesImage(Map<String, ValStr<?>> args) {
|
||||||
|
LaunchParameter<?> param = imageParameter();
|
||||||
|
if (param == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !"".equals(param.get(args).str());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateMonitorMax(TaskMonitor monitor, Map<String, ValStr<?>> args) {
|
||||||
AutoMapSpec spec = getAutoMapSpec();
|
AutoMapSpec spec = getAutoMapSpec();
|
||||||
if (requiresImage() && spec.hasTask()) {
|
boolean image = args == null ? supportsImage() : providesImage(args);
|
||||||
|
if (image && spec.hasTask()) {
|
||||||
monitor.setMaximum(6);
|
monitor.setMaximum(6);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -621,7 +625,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
||||||
Trace trace = null;
|
Trace trace = null;
|
||||||
Throwable lastExc = null;
|
Throwable lastExc = null;
|
||||||
|
|
||||||
initializeMonitor(monitor);
|
updateMonitorMax(monitor, null);
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
monitor.setMessage("Gathering arguments");
|
monitor.setMessage("Gathering arguments");
|
||||||
|
@ -633,6 +637,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
||||||
return new LaunchResult(program, sessions, acceptor, connection, trace,
|
return new LaunchResult(program, sessions, acceptor, connection, trace,
|
||||||
lastExc);
|
lastExc);
|
||||||
}
|
}
|
||||||
|
updateMonitorMax(monitor, args);
|
||||||
monitor.increment();
|
monitor.increment();
|
||||||
|
|
||||||
acceptor = null;
|
acceptor = null;
|
||||||
|
|
|
@ -44,45 +44,46 @@ public abstract class ScriptAttributesParser {
|
||||||
public static final String ENV_GHIDRA_TRACE_RMI_HOST = "GHIDRA_TRACE_RMI_HOST";
|
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 ENV_GHIDRA_TRACE_RMI_PORT = "GHIDRA_TRACE_RMI_PORT";
|
||||||
|
|
||||||
public static final String AT_TITLE = "@title";
|
|
||||||
public static final String AT_DESC = "@desc";
|
|
||||||
public static final String AT_MENU_PATH = "@menu-path";
|
|
||||||
public static final String AT_MENU_GROUP = "@menu-group";
|
|
||||||
public static final String AT_MENU_ORDER = "@menu-order";
|
|
||||||
public static final String AT_ICON = "@icon";
|
|
||||||
public static final String AT_HELP = "@help";
|
|
||||||
public static final String AT_ENUM = "@enum";
|
|
||||||
public static final String AT_ENV = "@env";
|
|
||||||
public static final String AT_ARG = "@arg";
|
public static final String AT_ARG = "@arg";
|
||||||
public static final String AT_ARGS = "@args";
|
public static final String AT_ARGS = "@args";
|
||||||
public static final String AT_TTY = "@tty";
|
public static final String AT_DESC = "@desc";
|
||||||
|
public static final String AT_ENUM = "@enum";
|
||||||
|
public static final String AT_ENV = "@env";
|
||||||
|
public static final String AT_HELP = "@help";
|
||||||
|
public static final String AT_ICON = "@icon";
|
||||||
|
public static final String AT_IMAGE_OPT = "@image-opt";
|
||||||
|
public static final String AT_MENU_GROUP = "@menu-group";
|
||||||
|
public static final String AT_MENU_ORDER = "@menu-order";
|
||||||
|
public static final String AT_MENU_PATH = "@menu-path";
|
||||||
|
public static final String AT_TITLE = "@title";
|
||||||
public static final String AT_TIMEOUT = "@timeout";
|
public static final String AT_TIMEOUT = "@timeout";
|
||||||
public static final String AT_NOIMAGE = "@no-image";
|
public static final String AT_TTY = "@tty";
|
||||||
|
|
||||||
public static final String PREFIX_ENV = "env:";
|
|
||||||
public static final String PREFIX_ARG = "arg:";
|
|
||||||
public static final String KEY_ARGS = "args";
|
public static final String KEY_ARGS = "args";
|
||||||
|
public static final String PREFIX_ARG = "arg:";
|
||||||
|
public static final String PREFIX_ENV = "env:";
|
||||||
|
|
||||||
public static final String MSGPAT_INVALID_HELP_SYNTAX =
|
public static final String MSGPAT_DUPLICATE_TAG = "%s: Duplicate %s";
|
||||||
"%s: Invalid %s syntax. Use Topic#anchor";
|
|
||||||
public static final String MSGPAT_INVALID_ENUM_SYNTAX =
|
|
||||||
"%s: Invalid %s syntax. Use NAME:type Choice1 [ChoiceN...]";
|
|
||||||
public static final String MSGPAT_INVALID_ENV_SYNTAX =
|
|
||||||
"%s: Invalid %s syntax. Use NAME:type=default \"Display\" \"Tool Tip\"";
|
|
||||||
public static final String MSGPAT_INVALID_ARG_SYNTAX =
|
public static final String MSGPAT_INVALID_ARG_SYNTAX =
|
||||||
"%s: Invalid %s syntax. Use :type \"Display\" \"Tool Tip\"";
|
"%s: Invalid %s syntax. Use :type \"Display\" \"Tool Tip\"";
|
||||||
public static final String MSGPAT_INVALID_ARGS_SYNTAX =
|
public static final String MSGPAT_INVALID_ARGS_SYNTAX =
|
||||||
"%s: Invalid %s syntax. Use \"Display\" \"Tool Tip\"";
|
"%s: Invalid %s syntax. Use \"Display\" \"Tool Tip\"";
|
||||||
public static final String MSGPAT_INVALID_TTY_SYNTAX =
|
public static final String MSGPAT_INVALID_ENUM_SYNTAX =
|
||||||
"%s: Invalid %s syntax. Use TTY_TARGET [if env:OPT [== VAL]]";
|
"%s: Invalid %s syntax. Use NAME:type Choice1 [ChoiceN...]";
|
||||||
|
public static final String MSGPAT_INVALID_ENV_SYNTAX =
|
||||||
|
"%s: Invalid %s syntax. Use NAME:type=default \"Display\" \"Tool Tip\"";
|
||||||
|
public static final String MSGPAT_INVALID_HELP_SYNTAX =
|
||||||
|
"%s: Invalid %s syntax. Use Topic#anchor";
|
||||||
|
public static final String MSGPAT_INVALID_TIMEOUT_SYNTAX = "" +
|
||||||
|
"%s: Invalid %s syntax. Use [milliseconds]";
|
||||||
|
public static final String MSGPAT_INVALID_TTY_BAD_VAL =
|
||||||
|
"%s: In %s: Parameter '%s' has type %s, but '%s' cannot be parsed as such";
|
||||||
public static final String MSGPAT_INVALID_TTY_NO_PARAM =
|
public static final String MSGPAT_INVALID_TTY_NO_PARAM =
|
||||||
"%s: In %s: No such parameter '%s'";
|
"%s: In %s: No such parameter '%s'";
|
||||||
public static final String MSGPAT_INVALID_TTY_NOT_BOOL =
|
public static final String MSGPAT_INVALID_TTY_NOT_BOOL =
|
||||||
"%s: In %s: Parameter '%s' must have bool type";
|
"%s: In %s: Parameter '%s' must have bool type";
|
||||||
public static final String MSGPAT_INVALID_TTY_BAD_VAL =
|
public static final String MSGPAT_INVALID_TTY_SYNTAX =
|
||||||
"%s: In %s: Parameter '%s' has type %s, but '%s' cannot be parsed as such";
|
"%s: Invalid %s syntax. Use TTY_TARGET [if env:OPT [== VAL]]";
|
||||||
public static final String MSGPAT_INVALID_TIMEOUT_SYNTAX = "" +
|
|
||||||
"%s: Invalid %s syntax. Use [milliseconds]";
|
|
||||||
|
|
||||||
public static class ParseException extends Exception {
|
public static class ParseException extends Exception {
|
||||||
private Location loc;
|
private Location loc;
|
||||||
|
@ -289,8 +290,9 @@ public abstract class ScriptAttributesParser {
|
||||||
return tac.withCastDefault(new ValStr<>(value, defaultString));
|
return tac.withCastDefault(new ValStr<>(value, defaultString));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LaunchParameter<T> createParameter(String name, String display, String description) {
|
public LaunchParameter<T> createParameter(String name, String display, String description,
|
||||||
return type.createParameter(name, display, description, false, defaultValue);
|
boolean required) {
|
||||||
|
return type.createParameter(name, display, description, required, defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +342,7 @@ public abstract class ScriptAttributesParser {
|
||||||
public record ScriptAttributes(String title, String description, List<String> menuPath,
|
public record ScriptAttributes(String title, String description, List<String> menuPath,
|
||||||
String menuGroup, String menuOrder, Icon icon, HelpLocation helpLocation,
|
String menuGroup, String menuOrder, Icon icon, HelpLocation helpLocation,
|
||||||
Map<String, LaunchParameter<?>> parameters, Map<String, TtyCondition> extraTtys,
|
Map<String, LaunchParameter<?>> parameters, Map<String, TtyCondition> extraTtys,
|
||||||
int timeoutMillis, boolean noImage) {}
|
int timeoutMillis, LaunchParameter<?> imageOpt) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an arguments map into a command line and environment variables
|
* Convert an arguments map into a command line and environment variables
|
||||||
|
@ -371,7 +373,7 @@ public abstract class ScriptAttributesParser {
|
||||||
LaunchParameter<?> param;
|
LaunchParameter<?> param;
|
||||||
for (int i = 1; (param = parameters.get("arg:" + i)) != null; i++) {
|
for (int i = 1; (param = parameters.get("arg:" + i)) != null; i++) {
|
||||||
// Don't use ValStr.str here. I'd like the script's input normalized
|
// Don't use ValStr.str here. I'd like the script's input normalized
|
||||||
commandLine.add(Objects.toString(param.get(args).val()));
|
commandLine.add(param.get(args).normStr());
|
||||||
}
|
}
|
||||||
|
|
||||||
param = parameters.get("args");
|
param = parameters.get("args");
|
||||||
|
@ -384,29 +386,24 @@ public abstract class ScriptAttributesParser {
|
||||||
if (key.startsWith(PREFIX_ENV)) {
|
if (key.startsWith(PREFIX_ENV)) {
|
||||||
String varName = key.substring(PREFIX_ENV.length());
|
String varName = key.substring(PREFIX_ENV.length());
|
||||||
ValStr<?> val = ent.getValue().get(args);
|
ValStr<?> val = ent.getValue().get(args);
|
||||||
if (val == null || val.val() == null) {
|
env.put(varName, ValStr.normStr(val));
|
||||||
env.put(varName, "");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
env.put(varName, Objects.toString(val.val()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int argc = 0;
|
private int argc;
|
||||||
private String title;
|
private String title;
|
||||||
private StringBuilder description;
|
private StringBuilder description;
|
||||||
private List<String> menuPath;
|
|
||||||
private String menuGroup;
|
|
||||||
private String menuOrder;
|
|
||||||
private String iconId;
|
private String iconId;
|
||||||
private HelpLocation helpLocation;
|
private HelpLocation helpLocation;
|
||||||
|
private String menuGroup;
|
||||||
|
private String menuOrder;
|
||||||
|
private List<String> menuPath;
|
||||||
private final Map<String, UserType<?>> userTypes = new HashMap<>();
|
private final Map<String, UserType<?>> userTypes = new HashMap<>();
|
||||||
private final Map<String, LaunchParameter<?>> parameters = new LinkedHashMap<>();
|
private final Map<String, LaunchParameter<?>> parameters = new LinkedHashMap<>();
|
||||||
private final Map<String, TtyCondition> extraTtys = new LinkedHashMap<>();
|
private final Map<String, TtyCondition> extraTtys = new LinkedHashMap<>();
|
||||||
private int timeoutMillis = AbstractTraceRmiLaunchOffer.DEFAULT_TIMEOUT_MILLIS;
|
private int timeoutMillis = AbstractTraceRmiLaunchOffer.DEFAULT_TIMEOUT_MILLIS;
|
||||||
private boolean noImage = false;
|
private String imageOptKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a line should just be ignored, e.g., blank lines, or the "shebang" line on UNIX.
|
* Check if a line should just be ignored, e.g., blank lines, or the "shebang" line on UNIX.
|
||||||
|
@ -489,36 +486,66 @@ public abstract class ScriptAttributesParser {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parts.length == 1) {
|
if (parts.length == 1) {
|
||||||
switch (parts[0].trim()) {
|
parseUnrecognized(loc, comment);
|
||||||
case AT_NOIMAGE -> parseNoImage(loc);
|
|
||||||
default -> parseUnrecognized(loc, comment);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (parts[0].trim()) {
|
switch (parts[0].trim()) {
|
||||||
case AT_TITLE -> parseTitle(loc, parts[1]);
|
|
||||||
case AT_DESC -> parseDesc(loc, parts[1]);
|
|
||||||
case AT_MENU_PATH -> parseMenuPath(loc, parts[1]);
|
|
||||||
case AT_MENU_GROUP -> parseMenuGroup(loc, parts[1]);
|
|
||||||
case AT_MENU_ORDER -> parseMenuOrder(loc, parts[1]);
|
|
||||||
case AT_ICON -> parseIcon(loc, parts[1]);
|
|
||||||
case AT_HELP -> parseHelp(loc, parts[1]);
|
|
||||||
case AT_ENUM -> parseEnum(loc, parts[1]);
|
|
||||||
case AT_ENV -> parseEnv(loc, parts[1]);
|
|
||||||
case AT_ARG -> parseArg(loc, parts[1], ++argc);
|
case AT_ARG -> parseArg(loc, parts[1], ++argc);
|
||||||
case AT_ARGS -> parseArgs(loc, parts[1]);
|
case AT_ARGS -> parseArgs(loc, parts[1]);
|
||||||
case AT_TTY -> parseTty(loc, parts[1]);
|
case AT_DESC -> parseDesc(loc, parts[1]);
|
||||||
|
case AT_ENUM -> parseEnum(loc, parts[1]);
|
||||||
|
case AT_ENV -> parseEnv(loc, parts[1]);
|
||||||
|
case AT_HELP -> parseHelp(loc, parts[1]);
|
||||||
|
case AT_ICON -> parseIcon(loc, parts[1]);
|
||||||
|
case AT_IMAGE_OPT -> parseImageOpt(loc, parts[1]);
|
||||||
|
case AT_MENU_GROUP -> parseMenuGroup(loc, parts[1]);
|
||||||
|
case AT_MENU_ORDER -> parseMenuOrder(loc, parts[1]);
|
||||||
|
case AT_MENU_PATH -> parseMenuPath(loc, parts[1]);
|
||||||
case AT_TIMEOUT -> parseTimeout(loc, parts[1]);
|
case AT_TIMEOUT -> parseTimeout(loc, parts[1]);
|
||||||
|
case AT_TITLE -> parseTitle(loc, parts[1]);
|
||||||
|
case AT_TTY -> parseTty(loc, parts[1]);
|
||||||
default -> parseUnrecognized(loc, comment);
|
default -> parseUnrecognized(loc, comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseTitle(Location loc, String str) {
|
protected void parseArg(Location loc, String str, int argNum) {
|
||||||
if (title != null) {
|
List<String> parts = ShellUtils.parseArgs(str);
|
||||||
reportWarning("%s: Duplicate %s".formatted(loc, AT_TITLE));
|
if (parts.size() != 3) {
|
||||||
|
reportError(MSGPAT_INVALID_ARG_SYNTAX.formatted(loc, AT_ARG));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String colonType = parts.get(0).trim();
|
||||||
|
if (!colonType.startsWith(":")) {
|
||||||
|
reportError(MSGPAT_INVALID_ARG_SYNTAX.formatted(loc, AT_ARG));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OptType<?> type;
|
||||||
|
boolean required = colonType.endsWith("!");
|
||||||
|
int endType = required ? colonType.length() - 1 : colonType.length();
|
||||||
|
try {
|
||||||
|
type = OptType.parse(loc, colonType.substring(1, endType), userTypes);
|
||||||
|
String name = PREFIX_ARG + argNum;
|
||||||
|
parameters.put(name, type.createParameter(name, parts.get(1), parts.get(2), required,
|
||||||
|
new ValStr<>(null, "")));
|
||||||
|
}
|
||||||
|
catch (ParseException e) {
|
||||||
|
reportError(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseArgs(Location loc, String str) {
|
||||||
|
List<String> parts = ShellUtils.parseArgs(str);
|
||||||
|
if (parts.size() != 2) {
|
||||||
|
reportError(MSGPAT_INVALID_ARGS_SYNTAX.formatted(loc, AT_ARGS));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchParameter<String> parameter = BaseType.STRING.createParameter(
|
||||||
|
"args", parts.get(0), parts.get(1), false, ValStr.str(""));
|
||||||
|
if (parameters.put(KEY_ARGS, parameter) != null) {
|
||||||
|
reportWarning("%s: Duplicate %s. Replaced".formatted(loc, AT_ARGS));
|
||||||
}
|
}
|
||||||
title = str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseDesc(Location loc, String str) {
|
protected void parseDesc(Location loc, String str) {
|
||||||
|
@ -529,54 +556,6 @@ public abstract class ScriptAttributesParser {
|
||||||
description.append("\n");
|
description.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseMenuPath(Location loc, String str) {
|
|
||||||
if (menuPath != null) {
|
|
||||||
reportWarning("%s: Duplicate %s".formatted(loc, AT_MENU_PATH));
|
|
||||||
}
|
|
||||||
menuPath = List.of(str.trim().split("\\."));
|
|
||||||
if (menuPath.isEmpty()) {
|
|
||||||
reportError(
|
|
||||||
"%s: Empty %s. Ignoring.".formatted(loc, AT_MENU_PATH));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseMenuGroup(Location loc, String str) {
|
|
||||||
if (menuGroup != null) {
|
|
||||||
reportWarning("%s: Duplicate %s".formatted(loc, AT_MENU_GROUP));
|
|
||||||
}
|
|
||||||
menuGroup = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseMenuOrder(Location loc, String str) {
|
|
||||||
if (menuOrder != null) {
|
|
||||||
reportWarning("%s: Duplicate %s".formatted(loc, AT_MENU_ORDER));
|
|
||||||
}
|
|
||||||
menuOrder = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseIcon(Location loc, String str) {
|
|
||||||
if (iconId != null) {
|
|
||||||
reportWarning("%s: Duplicate %s".formatted(loc, AT_ICON));
|
|
||||||
}
|
|
||||||
iconId = str.trim();
|
|
||||||
if (!Gui.hasIcon(iconId)) {
|
|
||||||
reportError(
|
|
||||||
"%s: Icon id %s not registered in the theme".formatted(loc, iconId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseHelp(Location loc, String str) {
|
|
||||||
if (helpLocation != null) {
|
|
||||||
reportWarning("%s: Duplicate %s".formatted(loc, AT_HELP));
|
|
||||||
}
|
|
||||||
String[] parts = str.trim().split("#", 2);
|
|
||||||
if (parts.length != 2) {
|
|
||||||
reportError(MSGPAT_INVALID_HELP_SYNTAX.formatted(loc, AT_HELP));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
helpLocation = new HelpLocation(parts[0].trim(), parts[1].trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T> UserType<T> parseEnumChoices(Location loc, BaseType<T> baseType,
|
protected <T> UserType<T> parseEnumChoices(Location loc, BaseType<T> baseType,
|
||||||
List<String> choiceParts) {
|
List<String> choiceParts) {
|
||||||
List<T> choices = new ArrayList<>();
|
List<T> choices = new ArrayList<>();
|
||||||
|
@ -642,10 +621,14 @@ public abstract class ScriptAttributesParser {
|
||||||
reportError(MSGPAT_INVALID_ENV_SYNTAX.formatted(loc, AT_ENV));
|
reportError(MSGPAT_INVALID_ENV_SYNTAX.formatted(loc, AT_ENV));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String typePart = tadParts[0].trim();
|
||||||
|
boolean required = typePart.endsWith("!");
|
||||||
|
int endType = required ? typePart.length() - 1 : typePart.length();
|
||||||
try {
|
try {
|
||||||
TypeAndDefault<?> tad =
|
TypeAndDefault<?> tad = TypeAndDefault.parse(loc, typePart.substring(0, endType),
|
||||||
TypeAndDefault.parse(loc, tadParts[0].trim(), tadParts[1].trim(), userTypes);
|
tadParts[1].trim(), userTypes);
|
||||||
LaunchParameter<?> param = tad.createParameter(name, parts.get(1), parts.get(2));
|
LaunchParameter<?> param =
|
||||||
|
tad.createParameter(name, parts.get(1), parts.get(2), required);
|
||||||
if (parameters.put(name, param) != null) {
|
if (parameters.put(name, param) != null) {
|
||||||
reportWarning("%s: Duplicate %s %s. Replaced.".formatted(loc, AT_ENV, trimmed));
|
reportWarning("%s: Duplicate %s %s. Replaced.".formatted(loc, AT_ENV, trimmed));
|
||||||
}
|
}
|
||||||
|
@ -655,42 +638,75 @@ public abstract class ScriptAttributesParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseArg(Location loc, String str, int argNum) {
|
protected void parseHelp(Location loc, String str) {
|
||||||
List<String> parts = ShellUtils.parseArgs(str);
|
if (helpLocation != null) {
|
||||||
if (parts.size() != 3) {
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_HELP));
|
||||||
reportError(MSGPAT_INVALID_ARG_SYNTAX.formatted(loc, AT_ARG));
|
}
|
||||||
|
String[] parts = str.trim().split("#", 2);
|
||||||
|
if (parts.length != 2) {
|
||||||
|
reportError(MSGPAT_INVALID_HELP_SYNTAX.formatted(loc, AT_HELP));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String colonType = parts.get(0).trim();
|
helpLocation = new HelpLocation(parts[0].trim(), parts[1].trim());
|
||||||
if (!colonType.startsWith(":")) {
|
|
||||||
reportError(MSGPAT_INVALID_ARG_SYNTAX.formatted(loc, AT_ARG));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
OptType<?> type;
|
|
||||||
|
protected void parseIcon(Location loc, String str) {
|
||||||
|
if (iconId != null) {
|
||||||
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_ICON));
|
||||||
|
}
|
||||||
|
iconId = str.trim();
|
||||||
|
if (!Gui.hasIcon(iconId)) {
|
||||||
|
reportError(
|
||||||
|
"%s: Icon id %s not registered in the theme".formatted(loc, iconId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseImageOpt(Location loc, String str) {
|
||||||
|
if (imageOptKey != null) {
|
||||||
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_IMAGE_OPT));
|
||||||
|
}
|
||||||
|
imageOptKey = str.strip();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseMenuGroup(Location loc, String str) {
|
||||||
|
if (menuGroup != null) {
|
||||||
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_MENU_GROUP));
|
||||||
|
}
|
||||||
|
menuGroup = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseMenuOrder(Location loc, String str) {
|
||||||
|
if (menuOrder != null) {
|
||||||
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_MENU_ORDER));
|
||||||
|
}
|
||||||
|
menuOrder = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseMenuPath(Location loc, String str) {
|
||||||
|
if (menuPath != null) {
|
||||||
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_MENU_PATH));
|
||||||
|
}
|
||||||
|
menuPath = List.of(str.trim().split("\\."));
|
||||||
|
if (menuPath.isEmpty()) {
|
||||||
|
reportError(
|
||||||
|
"%s: Empty %s. Ignoring.".formatted(loc, AT_MENU_PATH));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseTimeout(Location loc, String str) {
|
||||||
try {
|
try {
|
||||||
type = OptType.parse(loc, colonType.substring(1), userTypes);
|
timeoutMillis = Integer.parseInt(str);
|
||||||
String name = PREFIX_ARG + argNum;
|
|
||||||
parameters.put(name,
|
|
||||||
type.createParameter(name, parts.get(1), parts.get(2), true,
|
|
||||||
new ValStr<>(null, "")));
|
|
||||||
}
|
}
|
||||||
catch (ParseException e) {
|
catch (NumberFormatException e) {
|
||||||
reportError(e.getMessage());
|
reportError(MSGPAT_INVALID_TIMEOUT_SYNTAX.formatted(loc, AT_TIMEOUT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseArgs(Location loc, String str) {
|
protected void parseTitle(Location loc, String str) {
|
||||||
List<String> parts = ShellUtils.parseArgs(str);
|
if (title != null) {
|
||||||
if (parts.size() != 2) {
|
reportWarning(MSGPAT_DUPLICATE_TAG.formatted(loc, AT_TITLE));
|
||||||
reportError(MSGPAT_INVALID_ARGS_SYNTAX.formatted(loc, AT_ARGS));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchParameter<String> parameter = BaseType.STRING.createParameter(
|
|
||||||
"args", parts.get(0), parts.get(1), false, ValStr.str(""));
|
|
||||||
if (parameters.put(KEY_ARGS, parameter) != null) {
|
|
||||||
reportWarning("%s: Duplicate %s. Replaced".formatted(loc, AT_ARGS));
|
|
||||||
}
|
}
|
||||||
|
title = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putTty(Location loc, String name, TtyCondition condition) {
|
protected void putTty(Location loc, String name, TtyCondition condition) {
|
||||||
|
@ -749,19 +765,6 @@ public abstract class ScriptAttributesParser {
|
||||||
reportError(MSGPAT_INVALID_TTY_SYNTAX.formatted(loc, AT_TTY));
|
reportError(MSGPAT_INVALID_TTY_SYNTAX.formatted(loc, AT_TTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseTimeout(Location loc, String str) {
|
|
||||||
try {
|
|
||||||
timeoutMillis = Integer.parseInt(str);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
reportError(MSGPAT_INVALID_TIMEOUT_SYNTAX.formatted(loc, AT_TIMEOUT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseNoImage(Location loc) {
|
|
||||||
noImage = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void parseUnrecognized(Location loc, String line) {
|
protected void parseUnrecognized(Location loc, String line) {
|
||||||
reportWarning("%s: Unrecognized metadata: %s".formatted(loc, line));
|
reportWarning("%s: Unrecognized metadata: %s".formatted(loc, line));
|
||||||
}
|
}
|
||||||
|
@ -784,10 +787,18 @@ public abstract class ScriptAttributesParser {
|
||||||
if (iconId == null) {
|
if (iconId == null) {
|
||||||
iconId = "icon.debugger";
|
iconId = "icon.debugger";
|
||||||
}
|
}
|
||||||
|
LaunchParameter<?> imageOpt = null;
|
||||||
|
if (imageOptKey != null) {
|
||||||
|
imageOpt = parameters.get(imageOptKey);
|
||||||
|
if (imageOpt == null) {
|
||||||
|
reportError("%s: %s refers to %s, which is not a parameter name".formatted(fileName,
|
||||||
|
AT_IMAGE_OPT, imageOptKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
return new ScriptAttributes(title, getDescription(), List.copyOf(menuPath), menuGroup,
|
return new ScriptAttributes(title, getDescription(), List.copyOf(menuPath), menuGroup,
|
||||||
menuOrder, new GIcon(iconId), helpLocation,
|
menuOrder, new GIcon(iconId), helpLocation,
|
||||||
Collections.unmodifiableMap(new LinkedHashMap<>(parameters)),
|
Collections.unmodifiableMap(new LinkedHashMap<>(parameters)),
|
||||||
Collections.unmodifiableMap(new LinkedHashMap<>(extraTtys)), timeoutMillis, noImage);
|
Collections.unmodifiableMap(new LinkedHashMap<>(extraTtys)), timeoutMillis, imageOpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDescription() {
|
private String getDescription() {
|
||||||
|
|
|
@ -637,6 +637,9 @@ public abstract class AbstractDebuggerParameterDialog<P> extends DialogComponent
|
||||||
protected void setEditorValue(PropertyEditor editor, P param, ValStr<?> val) {
|
protected void setEditorValue(PropertyEditor editor, P param, ValStr<?> val) {
|
||||||
switch (val.val()) {
|
switch (val.val()) {
|
||||||
case null -> {
|
case null -> {
|
||||||
|
if (parameterType(param) == String.class) {
|
||||||
|
editor.setValue(val.str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case BigInteger bi -> editor.setAsText(val.str());
|
case BigInteger bi -> editor.setAsText(val.str());
|
||||||
default -> editor.setValue(val.val());
|
default -> editor.setValue(val.val());
|
||||||
|
|
|
@ -30,8 +30,8 @@ public class TestTraceRmiLaunchOpinion implements TraceRmiLaunchOpinion {
|
||||||
|
|
||||||
public static class TestTraceRmiLaunchOffer extends AbstractTraceRmiLaunchOffer {
|
public static class TestTraceRmiLaunchOffer extends AbstractTraceRmiLaunchOffer {
|
||||||
private static final LaunchParameter<String> PARAM_IMAGE =
|
private static final LaunchParameter<String> PARAM_IMAGE =
|
||||||
LaunchParameter.create(String.class, "image", PARAM_DISPLAY_IMAGE, "Image to execute",
|
LaunchParameter.create(String.class, "image", "Image", "Image to execute",
|
||||||
true, ValStr.str(""), str -> str);
|
false, ValStr.str(""), str -> str);
|
||||||
|
|
||||||
public TestTraceRmiLaunchOffer(TraceRmiLauncherServicePlugin plugin, Program program) {
|
public TestTraceRmiLaunchOffer(TraceRmiLauncherServicePlugin plugin, Program program) {
|
||||||
super(plugin, program);
|
super(plugin, program);
|
||||||
|
@ -62,8 +62,8 @@ public class TestTraceRmiLaunchOpinion implements TraceRmiLaunchOpinion {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresImage() {
|
public LaunchParameter<?> imageParameter() {
|
||||||
return false;
|
return PARAM_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue