Devel::Chitin - Programmatic interface to the Perl debugging API
package CLIENT; use base 'Devel::Chitin'; # These inherited methods can be called by the client class CLIENT->attach(); # Register with the debugging system CLIENT->detach(); # Un-register with the debugging system CLIENT->step(); # single-step into subs CLIENT->stepover(); # single-step over subs CLIENT->stepout(); # Return from the current sub, then stop CLIENT->continue(); # Run until the next breakpoint CLIENT->trace([$flag]); # Get/set the trace flag CLIENT->disable_debugger(); # Deactivate the debugging system CLIENT->is_loaded($file); # Return true if the file is loaded CLIENT->loaded_files(); # Return a list of loaded file names CLIENT->postpone($file, $subref); # Run $subref->() when $file is loaded CLIENT->is_breakable($file, $line); # Return true if the line is executable CLIENT->stack(); # Return Devel::Chitin::Stack CLIENT->current_location(); # Where is the program stopped at? CLIENT->next_statement(); # Return the next statement to execute CLIENT->next_fragment([$parents]); # Return the next op to execute CLIENT->add_watchexpr($expr); # Add a new watch expression CLIENT->remove_watchexpr($expr); # Remove a watch expression # These methods are called by the debugging system at the appropriate time. # Base-class methods do nothing. These methods must not block. CLIENT->init(); # Called when the debugging system is ready CLIENT->poll($location); # Return true if there is user input CLIENT->idle($location); # Handle user interaction (can block) CLIENT->notify_trace($location); # Called on each executable statement CLIENT->notify_trace_resumed($location); # Called before the program gets control after trace CLIENT->notify_stopped($location); # Called when a break has occured CLIENT->notify_resumed($location); # Called before the program gets control after a break CLIENT->notify_fork_parent($location,$pid); # Called after fork() in parent CLIENT->notify_fork_child($location); # Called after fork() in child CLIENT->notify_program_terminated($?); # Called as the program is finishing CLIENT->notify_program_exit(); # Called as the program is exiting CLIENT->notify_uncaught_exception($exc); # Called after an uncaught exception CLIENT->notify_watch_expr($location, $expr, $old, $new); # Called when a watch expr changes
This class exposes the Perl debugging facilities as an API useful for implementing debuggers, tracers, profilers, etc so they can all benefit from common code.
Devel::Chitin is not a usable debugger per se. It has no mechanism for interacting with a user such as reading command input or printing results. Instead, clients of this API may call methods to inspect the debugged program state. The debugger core calls methods on clients when certain events occur, such as when the program is stopped by breakpoint or when the program exits. Multiple clients can attach themselves to Devel::Chitin simultaneously within the same debugged program.
This class does not supply a constructor. Clients wishing to use this API must inherit from this class and call the attach method. They may use whatever mechanism they wish to implement their object or class.
attach
These methods are provided by the debugging API and may be called as inherited methods by clients.
Attaches a client to the debugging API. May be called as a class or instance method. When later client methods are called by the debugging API, the same invocant will be used.
Removes a client from the debugging API. The invocant must match a previous attach call.
Get or set the trace flag. If trace is on, the client will get notified before every executable statement by having its notify_trace method called, and before returning to the debugged program by having its notify_trace_resumed method called.
notify_trace
notify_trace_resumed
Turn off the debugging system. The debugged program will continue normally. The debugger system will not be triggered afterward.
Causes $subref to be called when $file is loaded. If $file is already loaded, then $subref will be called immediately.
$subref
Single-step the next statement in the debugged program. If the next statement is a subroutine call, the debugger will stop on its first executable statement.
Single-step the next statement in the debugged program. If the next statement is a subroutine call, the debugger will stop on its first executable statement after that subroutine call returns.
Continue running the debugged program until the current subroutine returns or until the next breakpoint, whichever comes first.
This form of stepout() allows registering a callback to be invoked when the current subroutine returns. The callback's first argument is an instance of Devel::Chitin::SubroutineReturn, which provides access to the location the function is returning from, its wantarray status, and the function's return value. The rv property of the SubroutineReturn object is mutable, and actually changes the value being returned from the function.
rv
Callbacks are invoked in the order they are queued, and a return value changed in this way is presented as the return value to the next callback. The final callback gets the last say about the ultimate return value from the function.
Continue running the debugged program until the next breakpoint.
Sets a flag that indicates the program should completely exit after the debugged program ends. Normally, the debugger will regain control after the program ends.
Evaluate the given string in the context of the most recent stack frame of the program being debugged. Because of the limitations of Perl's debugging hooks, this function does not return the value directly. Instead, the caller must cede control back to the debugger system and the eval will be done before the next statement in the program being debugged. If the debugged program is currently stopped at a breakpoint, then the eval will be done before resuming.
The result is delivered by calling the given $coderef with two arguments: the $result and $exception. If $wantarray was true, then the result will be an arrayref.
Evaluate the given string in the context of the program being debugged. If $level is omitted, the string is run in the context of the most recent stack frame of the debugged program. Otherwise, $level is the number of stack frames before the most recent to evaluate the code in. Negative numbers are treated as 0. eval_at returns a list of two items, the result and exception.
This method requires the PadWalker module.
This method is not yet implemented.
Return the value of the given variable expression. $level is the stack level in the context of the debugged program; 0 is the most recent level. $string is the name of the variable to inspect, including the sigil. This method handles some more complicated expressions such array and hash elements and slices.
This method is temporary, until eval_at() is implemented.
Return true if the file is loaded
Return a list of loaded file names
Return true if the line has an executable statement. Only lines with executable statements may have breakpoints. In particular, line containing only comments, whitespace or block delimiters are typically not breakable.
Return a Devel::Chitin::SubroutineLocation instance for where the named subroutine was defined. $subroutine should be fully qualified including the package name.
$subroutine
If the named function does not exist, it returns undef.
Return an instance of Devel::Chitin::Stack. This object represents the execution/call stack of the debugged program.
Return an instance of Devel::Chitin::Location representing the currently stopped location in the debugged program. This method returns undef if called when the debugged program is actively running.
Returns a string representing the next Perl statement to execute when control returns to the debugged program with "step over". This involves inspecting the OpTree of the currently executing subroutine and deparsing it at the stopped location. Since the returned string is a reconstruction based on the OpTree, it may not match the original source code exactly.
The deparse normally starts by finding the closest contol OP (COP) before the current OP, then deparsing its sibling. In some cases this results in a misleading deparse, so some adjustments may be made to the starting OP:
Return the while loop condition instead of the whole loop
Return either the list construction or the function call
Return the if () condition instead of the entire if()/unless() statement
Return the list being mapped/grepped over
Requires the Devel::Callsite module to be installed.
Returns a string representing the next Perl operation to execute when control returns to the debugged program. This differes from next_statement() in that next_fragment() only deparses the immediately next opcode (and its children). $parents is an optional param to indicate how many parent OPs to back up before deparsing.
$parents
Return a list of strings containing the source code for a loaded file.
See Devel::Chitin::Actionable for documentation on setting breakpoints and actions.
Watch expressions are evaluated before each statement in the program. If a watched expression's value ever changes, the client that added the expression will be notified via its notify_watch_expr() method. These expressions are always evaluated in list context. They are considered changed if the list's length changes, or if one of the elements has a different value when compared as strings. This comparison is only shallow; it will not recurse into references or nested data structures.
notify_watch_expr()
Adds a new watch expression linked to the calling client.
Remove a previously added watch expression. Returns false if the expression was not previously added with add_watch_expr().
add_watch_expr()
These methods exist in the base class, but only as empty stubs. They are called at the appropriate time by the debugging system. Clients may provide their own implementation.
With the exception of idle, these client-provided methods must not block so that other clients may get called.
idle
Called before the first breakpoint, usually before the first executable statement in the debugged program. Its return value is ignored
Called when the debugger is stopped on a line. This method should return true to indicate that it wants its idle method called. $location is an instance of Devel::Chitin::Location indicating the next statement to be executed in the debugged program.
$location
Called when the client can block, to accept and process user input, for example. This method should return true to indicate to the debugger system that it has finished processing, and that it is OK to continue the debugged program. The loop around calls to idle will stop when all clients return true.
If a client has turned on the trace flag, this method will be called before each executable statement. The return value is ignored.
If a client has turned on the trace flag, this method will be called before the debugged program regains control. The return value is ignored.
notify_trace() will be called only on clients that have requested tracing by calling CLIENT->trace(1).
This method is called when a breakpoint has occurred. Its return value is ignored.
This method is called after a breakpoint, after any calls to idle, and just before the debugged program resumes execution. The return value is ignored.
This method is called immediately after the debugged program calls fork() in the context of the parent process. $pid is the child process ID created by the fork. The return value is ignored.
$pid
Note that the $location will be the first executable statement after the fork() in the parent process.
This method is called immediately after the debugged program calls fork() in the context of the child process. The return value is ignored.
This method is called after the last executable statement in the debugged program. After all clients are notified, the debugger system emulates one final breakpoint inside a function called at_exit and the program remains running, though stopped.
at_exit
If the a client has requested that the program terminate completely by calling CLIENT->user_requested_exit(), then this method will be called during the debugger's END block as the interpreter is cleaning up.
The debugger system installs a __DIE__ handler to trap exceptions that are not otherwise handled by the debugged program. When an uncaught exception occurs, this method is called. $exception is an instance of Devel::Chitin::Exception.
Called when a client has added a watchexpr expression and its value has changed. Since watch expressions are evaluated in list context, $old and $new are listrefs containing the previous and new values.
The location reported is whichever program line was executing immediately prior to the current line.
Note that this does not stop execution of the debugged program. The notify_watch_expr() method should call CLIENT->step to trigger a breakpoint.
CLIENT->step
As this is an extremely early release, this API should be considered experimental. It was developed to extract the debugger-specific code from Devel::hdb. I encourage others to make suggestions and submit bug reports so we can converge on a usable API quickly.
Devel::Chitin::Location, Devel::Chitin::Exception, Devel::Chitin::Stack, Devel::Chitin::Actionable, Devel::Chitin::GetVarAtLevel, Devel::Callsite
The API for this module was inspired by DB
Anthony Brummett <brummett@cpan.org>
Copyright 2017, Anthony Brummett. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
To install Devel::Chitin, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Devel::Chitin
CPAN shell
perl -MCPAN -e shell install Devel::Chitin
For more information on module installation, please visit the detailed CPAN module installation guide.