Starting TotalView on a Script
It is sometimes convenient to start TotalView on a shell script. For example, a typical use case might be a script that calls into a shared library, and you need to debug the shared library code; another case is a shell script that sets environment variables, then execs the application to debug.
Anywhere in the examples above that an executable can be specified, an interpreter script can be specified instead. The underlying interpreter, which must be a valid executable object file for the platform, is debugged, not the script itself.
On Unix, an interpreter script starts with a line that is similar to the following:
#! interpreter [ interpreter-arg ]
Where
#! are the first two characters in the file.
interpreter is the path to an executable object file or some other interpreter script.
interpreter-arg is an optional argument to pass to the interpreter.
When the interpreter script is executed, the interpreter is invoked by the system as follows:
interpreter [ interpreter-arg ] script [ script-args ]
Here's a simple example:
% cat myscript.sh
#! /bin/sh -x
echo "$@"
% ./myscript.sh a b c
+ echo a b c
a b c
%
In the example above, the following command was executed:
/bin/sh -x ./myscript.sh a b c
Whenever TotalView is processing an executable file, it first checks to see if the file is an interpreter script. If the file starts with #!, it is treated as an interpreter script. The path to the interpreter is extracted from the script and used as the executable object file to debug. If the interpreter file is itself an interpreter script, TotalView repeats the procedure (up to 40 times) until it encounters an interpreter file that is not an interpreter script. If the procedure fails to find a valid executable object file for the platform, loading the script into the debugger will fail.
In most cases, the interpreter for the script does not directly contain the code you want to debug, and instead dynamically loads or executes the code to debug. TotalView contains several configuration settings that make it easier to plant breakpoints and stop in your code, as described by the Related Topics below. There are three common cases, where the interpreter script:
Dynamically loads a shared library and calls into the code to debug (see the entries below regarding shared libraries and creating pending breakpoints)
Execs the program containing the code to debug (relevant to exec handling)
Runs the program containing the code to debug (relevant to fork handling)