NAME
Devel::Trepan -- A new modular Perl debugger
SUMMARY
A modular, testable, gdb-like debugger in the family of the Ruby trepanning debuggers.
Features:
extensive online-help
syntax highlighting of Perl code
context-sensitive command completion
out-of-process and remote debugging
interactive shell support
code disassembly
gdb syntax
easy extensibility at several levels: aliases, commands, and plugins
comes with extensive tests
is not as ugly as perl5db
Some of the features above require additional modules before they take effect. See "Plugins" and "Recommended Modules" below.
DESCRIPTION
Invocation
From a shell:
$ trepan.pl [trepan-opts] -- perl-program [perl-program-opts]
For out-of-process (and possibly out-of server) debugging:
$ trepan.pl --server [trepan-opts] -- perl-program [perl-program-opts]
and then from another process or computer:
$ trepan.pl --client [--host DNS-NAME-OR-IP]
Calling the debugger from inside your Perl program using Joshua ben Jore's Enbugger:
# This needs to be done once and could even be in some sort of
# conditional code
require Enbugger; Enbugger->load_debugger( 'trepan' );
# Alternatively, to unconditionally load Enbugger and trepan:
use Enbugger 'trepan';
# work, work, work...
# Oops! there was an error! Enable the debugger now!
Enbugger->stop; # or Enbugger->stop if ...
Or if you just want POSIX-shell-like set -x
line tracing:
$ trepan.pl -x -- perl-program [perl-program-opts]
Inside the debugger tracing is turned on using the command set trace print
. There is extensive help from the help
command.
Basic Commands
The help system follows the gdb classificiation. Below is not a full list of commands, nor does it contain the full list of options on each command, but rather some of the more basic commands and options.
Commands involving running the program
The commands in the section involve controlling execution of the program, either by kinds of stepping (step into, step over, step out) restarting or termintating the program altogether. However setting breakpoints is in "Making the program stop at certain points".
Examining data
Making the program stop at certain points
A Breakpoint is a way to have the program stop at a pre-determined location. A breakpoint can be perminant or one-time. A one-time breakpoint is removed as soon as it is hit. In a sense, stepping is like setting one-time breakpoints. Breakpoints can also be disabled which allows you to temporarily ignore stopping at that breakpoint while it is disabled. Finally one can control conditions under which a breakpoint is enacted upon.
Another way to force a stop is to watch to see if the value of an expression changes. Often that expression is simply examinging a variable's value.
Examining the call stack
The commands in this section show the call stack and let set a reference for the default call stack which other commands like list
or break
use as a position when one is not specified.
The most recent call stack entry is 0. Except for the relative motion commands up
and down
, you can refer to the oldest or top-level stack entry with -1 and negative numbers refer to the stack from the other end.
Beware that in contrast to debuggers in other programming languages, Perl really doesn't have an easy way for one to evaluate statements and expressions other than at the most recent call stack. There are ways to see lexical variables my and our, however localized variables which can hide global variables and other lexicals variables can be problematic.
Print all or parts of the call stack (backtrace)
backtrace [count]
Print a stack trace, with the most recent frame at the top. With a positive number, print at most many entries.
In the listing produced, an arrow indicates the 'current frame'. The current frame determines the context used for many debugger commands such as source-line listing or the edit
command.
Examples:
backtrace # Print a full stack trace
backtrace 2 # Print only the top two entries
Select a call frame (frame)
frame [frame-number]
Change the current frame to frame frame-number if specified, or the most-recent frame, 0, if no frame number specified.
A negative number indicates the position from the other or least-recently-entered end. So frame -1
moves to the oldest frame.
Examples:
frame # Set current frame at the current stopping point
frame 0 # Same as above
frame . # Same as above. 'current thread' is explicit.
frame . 0 # Same as above.
frame 1 # Move to frame 1. Same as: frame 0; up
frame -1 # The least-recent frame
Move to a more recent frame (up)
up [count]
Move the current frame up in the stack trace (to an older frame). 0 is the most recent frame. If no count is given, move up 1.
Move to a less recent frame (down)
down [count]
Move the current frame down in the stack trace (to a newer frame). 0 is the most recent frame. If no count is given, move down 1.
Support facilities
Define an alias
alias alias command
Add alias alias for a debugger command command.
Add an alias when you want to use a command abbreviation for a command that would otherwise be ambigous. For example, by default we make s
be an alias of step
to force it to be used. Without the alias, s
might be step
, show
, or set
, among others.
Examples:
alias cat list # "cat file.pl" is the same as "list file.pl"
alias s step # "s" is now an alias for "step".
# The above "s" alias is initially set up, by
# default. But you can change or remove it.
For more complex definitions, see macro
. See also unalias
and show alias
.
Remove an unalias
unalias alias1 [alias2 ...]
Remove alias alias1 and so on.
Example:
unalias s # Remove 's' as an alias for 'step'
See also alias
.
Define a debugger macro
macro macro-name sub { ... }
Define macro-name as a debugger macro. Debugger macros get a list of arguments which you supply without parenthesis or commas. See below for an example.
The macro (really a Perl anonymous subroutine) should return either a string or an array reference to a list of strings. The string in both cases are strings of debugger commands. If the return is a string, that gets tokenized by a simple split(/ /, $string)
. Note that macro processing is done right after splitting on ;;
so if the macro returns a string containing ;;
this will not be handled on the string returned.
If instead, a reference to a list of strings is returned, then the first string is shifted from the array and executed. The remaining strings are pushed onto the command queue. In contrast to the first string, subsequent strings can contain other macros. Any ;;
in those strings will be split into separate commands.
Examples:
The below creates a macro called fin+ which issues two commands finish
followed by step
:
macro fin+ sub{ ['finish', 'step']}
If you wanted to parameterize the argument of the finish
command you could do it this way:
macro fin+ sub{ \
['finish', 'step ' . (shift)] \
}
Invoking with:
fin+ 3
would expand to ["finish", "step 3"]
If you were to add another parameter, note that the invocation is like you use for other debugger commands, no commas or parenthesis. That is:
fin+ 3 2
rather than fin+(3,2)
or fin+ 3, 2
.
See also info macro
.
Gently exit debugged program (quit)
quit[!] [unconditionally] [exit-code]
Allow remote debugger connections (server)
server [options]
options:
-p | --port NUMBER
-a | --address
Suspends interactive debugger session and puts debugger in server mode which opens a socket for debugger connections
Run debugger commands from a file (source)
source [options] file
options:
-q | --quiet | --no-quiet
-c | --continue | --no-continue
-Y | --yes | -N | --no
-v | --verbose | --no-verbose
Read debugger commands from a file named file. Optional -v
switch causes each command in FILE to be echoed as it is executed. Option -Y
sets the default value in any confirmation command to be 'yes' and -N
sets the default value to 'no'.
Option -q
will turn off any debugger output that normally occurs in the running of the program.
An error in any command terminates execution of the command file unless option -c
or --continue
is given.
Load or Reload something Perlish (load)
Sometimes in the middle of debugging you would like to make a change to a Perl module -- perhaps you've found a bug -- and start using that. If the change is inside a Perl module, you can use the command load module
:
load module {Perl-module-file}
Another thing that can occur especially if using Enbugger is that the source to Perl code is not cached inside the debugger and so you can't set a breakpoint on lines in that module. load source
can be used to rectify this. However this is a bit experimenta. There may still be a problem in making sure that debugging turned on when tracing inside of that source.
load source {Perl-source_file}
Finally, if you have debugger commands of your own or if you change a debugger command, you can force a reread of that debugger command using load command
.
load commmand {file-or-directory-name-1 [file-or-directory-name-2...]}
Modify parts of the Debugger Environment (set, show)
There are many parts of the debugger environment you can change, like the print line width, whether you want syntax highlighting or not and so on. These fall under set
commands. show
commands show you values that have been set. In fact, many of the set
commands finish by runnin the corresponding "show" to echo you see what you've just set.
Set commands
- abbrev
-
Set to allow unique abbreviations of commands
- auto
-
Set controls for some "automatic" default behaviors
- basename
-
Set to show only file basename in showing file names
- confirm
-
Set whether to confirm potentially dangerous operations.
- debug
-
Set debugging controls
- different
-
Set to make sure 'next/step' move to a new position.
- display
-
Set display attributes
- evaldisplay
-
Set whether we use terminal highlighting
- max
-
Set maximum length sizes of various things
- return
-
Set the value about to be returned
- substitute
-
Influence how filenames in the debugger map to local filenames
- timer
-
Set to show elapsed time between debugger events
- trace
-
Set tracing of various sorts.
- variable
-
Set a my or our variable
Show commands
- abbrev
-
Show whether we allow abbreviated debugger command names
- aliases
-
Show defined aliases
- args
-
Arguments to restart program
- auto
-
Show controls for things with some sort of "automatic" default behavior
- basename
-
Show only file basename in showing file names
- confirm
-
Show confirm potentially dangerous operations setting
- debug
-
Show debugging controls
- different
-
Show status of 'set different'
- display
-
Show display-related controls
- evaldisplay
-
Show whether we use terminal highlighting
- interactive
-
Show whether debugger input is a terminal
- max
-
Show "maximum length" settings
- timer
-
Show status of the timing hook
- trace
-
Set tracing of various sorts
- version
-
Show debugger name and version
Syntax of debugger commands
Overall Debugger Command Syntax
If the first non-blank character of a line starts with #, the command is ignored.
Commands are split at whereever ;;
appears. This process disregards any quotes or other symbols that have meaning in Perl. The strings after the leading command string are put back on a command queue.
Within a single command, tokens are then white-space split. Again, this process disregards quotes or symbols that have meaning in Perl. Some commands like eval
, macro
, and break
have access to the untokenized string entered and make use of that rather than the tokenized list.
Resolving a command name involves possibly 4 steps. Some steps may be omitted depending on early success or some debugger settings:
1. The leading token is first looked up in the macro table. If it is in the table, the expansion is replaces the current command and possibly other commands pushed onto a command queue. See the "help macros" for help on how to define macros, and "info macro" for current macro definitions.
2. The leading token is next looked up in the debugger alias table and the name may be substituted there. See "help alias" for how to define aliases, and "show alias" for the current list of aliases.
3. After the above, The leading token is looked up a table of debugger commands. If an exact match is found, the command name and arguments are dispatched to that command. Otherwise, we may check to see the the token is a unique prefix of a valid command. For example, "dis" is not a unique prefix because there are both "display" and "disable" commands, but "disp" is a unique prefix. You can allow or disallow abbreviations for commands using "set abbrev". The default is abbreviations are on.
4. If after all of the above, we still don't find a command, the line may be evaluated as a Perl statement in the current context of the program at the point it is stoppped. However this is done only if "auto eval" is on. (It is on by default.)
If "auto eval" is not set on, or if running the Perl statement produces an error, we display an error message that the entered string is "undefined".
Debugger Command Examples
Commenting
# This line does nothing. It is a comment and is useful
# in debugger command files.
# any amount of leading space is also ok
Splitting Commands
The following runs two commands: info program
and list
info program;; list
The following gives a syntax error since ;;
splits the line and the simple debugger parse then thinks that the quote (") is not closed.
print "hi ;;-)\n"
If you have the Devel::Trepan::Shell plugin, you can go into a real shell and run the above.
Command Continuation
If you want to continue a command on the next line use \
at the end of the line. For example:
eval $x = "This is \
a multi-line string"
The string in variable $x
will have a \n
before the article "a".
Command suffixes which have special meaning
Some commands like step
, or list
do different things when an alias to the command ends in a particular suffix like ">".
Here are a list of commands and the special suffixes:
command suffix
------- ------
list >
step +,-,<,>
next +,-,<,>
quit !
kill !
eval ?
See help on the commands listed above for the specific meaning of the suffix.
BUGS/CAVEATS
Because this should be useful in all sorts of environments such as back to perl 5.008, we often can make use of newer Perlisms nor can we require by default all of the modules, say for data printing, stack inspection, or interactive terminal handling. That said, if you have a newer Perl or the recommended modules or install plugins, you'll get more.
Although modular, this program is even larger than perl5db
and so it loads a little slower. I think part of the slowness is the fact that there are over 70 or so (smallish) files (rather than one nearly 10K file) and because relative linking via rlib is used to glue them together.
AUTHOR
Rocky Bernstein
SEE ALSO
My Devel::Trepan blogs and wiki
Plugins
Devel::Trepan::Shell adds a debugger
shell
command support via Devel::REPLDevel::Trepan::Disassemble adds a debugger
disassemble
command support via B::Concise
Recommended Modules
Devel::Callsite allows you to see the exact location of where you are stopped.
Enbugger allows you to enter the debugger via a direct call in source code
Eval::WithLexicals allows you to inspect my and our variables up the call stack
Data::Printer allows one to Use Data::Printer to format evaluation output
Data::Dumper::Perltidy allows one to Use Data::Dumper::Perltidy to format evaluation output
Term::ReadLine::Perl5 allows editing on the command line, command completion, and saving command history. This Module is preferred over Term::ReadLine::Perl or Term::ReadLine::Gnu.
Term::ReadLine::Gnu allows editing of the command line and command completion
Other Debuggers
perldebug is perl's built-in tried-and-true debugger that other debuggers will ultimately be compared with
DB is a somewhat abandoned debugger API interface. I've tried to use some parts of this along with
perl5db
.
COPYRIGHT
Copyright (C) 2011, 2012 Rocky Bernstein <rocky@cpan.org>
This program is distributed WITHOUT ANY WARRANTY, including but not limited to the implied warranties of merchantability or fitness for a particular purpose.
The program is free software. You may distribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (either version 2 or any later version) and the Perl Artistic License as published by O'Reilly Media, Inc. Please open the files named gpl-2.0.txt and Artistic for a copy of these licenses.