#!/usr/bin/env perl # Copyright (C) 2013-2015 Rocky Bernstein # Documentation is at the __END__ eval "use feature ':5.10';"; use strict; use warnings; use rlib '..'; use Devel::Trepan::Version; use Devel::Trepan::Core; package Devel::Trepan; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION $TREPAN_CMDPROC $PROGRAM); use Exporter; @EXPORT = qw(debugger); @ISA = qw(Exporter); use constant PROGRAM => 'trepan.pl'; our $VERSION='0.73'; # To fool CPAN indexer. Is <= real version $VERSION = $Devel::Trepan::Version::VERSION; $PROGRAM = PROGRAM; sub show_version() { PROGRAM . ", version $Devel::Trepan::VERSION"; } # Access to stopping point as an integer. sub addr() { $DB::OP_addr }; # Access to stopping point as a hex string. sub haddr() { sprintf "0x%x", $DB::OP_addr } # =head2 debugger # Allows program to make an explicit call to the debugger. # B # # In your Perl program I: # # my $x = 1; # Devel::Trepan::debugger; # my $y = 2; # Above line causes a stop here. # # Invoke as: # # $ trepan.pl foo.pl # -- main::(foo.pl:1) # (trepanpl): continue # (trepanpl): c # :o main::(foo.pl:3) # my $y = 2; # # This is like Cstop> but without L. However in # contrast to Enbugger, in order for this to work you must have # previously set up for debugging previously by running trepan.pl. # # =cut sub debugger { $DB::in_debugger = 0; $DB::event = 'debugger-call'; $DB::signal = 2; } if (__FILE__ eq $0 ) { print show_version(), "\n"; } unless (caller) { print show_version, "\n"; print "Pssst... this is a module. See trepan.pl to invoke.\n" } no warnings; "Just another Perl Debugger"; __END__ =pod =for comment This file is shared by both Trepan.pod and Trepan.pm after its __END__ Trepan.pod is useful in the Github wiki: https://github.com/rocky/Perl-Devel-Trepan/wiki where we can immediately see the results and others can contribute. =begin html =end html =for comment The version Trepan.pm however is what is seen at https://metacpan.org/module/Devel::Trepan and when folks download this file =head1 NAME Devel::Trepan -- A modular gdb-like Perl debugger =head1 SUMMARY A modular, testable, gdb-like debugger in the family of the Ruby L. =head2 Features: =over =item * extensive pod-formatted online-help =item * syntax highlighting of Perl code =item * context-sensitive command completion =item * out-of-process and remote debugging =item * gdb syntax =item * easy extensibility at several levels: aliases, commands, and plugins =item * comes with extensive tests =item * interactive shell support (via an optional plugin) =item * code deparsing and disassembly (via an optional plugins) =item * is not as ugly as perl5db =back Some of the features above require additional modules before they take effect. See L and L below. =head1 DESCRIPTION =head2 Invocation From a shell: $ trepan.pl [trepan-opts] [--] perl-program [perl-program-opts] Or for those who prefer the traditional Perlish way: $ perl -d:Trepan perl-program [perl-program-opts] The problem with the above "perlish" approach is that you get the default trepan options. If you want to set any of these, you'll have to set them either with a debugger command, possibly via startup script, e.g. I<~/.treplrc> or via environment variable I. To see the environement variables, run I with the C<--verbose> option or run C inside of the debugger. 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 L: # 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 C line tracing: $ trepan.pl -x -- perl-program [perl-program-opts] Inside the debugger tracing is turned on using the command C. There is extensive help from the C command. =head2 Command Categories The help system follows the I classificiation. =over =item * L =item * L =item * L =item * L =item * L =item * L =item * L =item * L =back =head3 Making the program stop at certain points A I 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. =over =item * L =item * L =item * L =item * L =item * L =item * L =item * L =item * L =item * L =back =head3 Examining data =over =item * L =item * L =item * L =item * L =item * L =item * L =item * L =back =head3 Specifying and examining files =over =item * L =item * L =back =head3 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 L. =over =item * L =item * L =item * L =item * L =item * L =item * L =item * L =item * L =back =head3 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 L|Devel::Trepan::CmdProcessor::Command::List> or L|Devel::Trepan::CmdProcessor::Command::Break> use as a position when one is not specified. The most recent call stack entry is 0. Except for the relative motion commands L|Devel::Trepan::CmdProcessor::Command::Up> and L|Devel::Trepan::CmdProcessor::Command::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 I and I, however localized variables which can hide global variables and other lexicals variables can be problematic. =over =item * L =item * L =item * L