++ed by:
KES
Author image Mattia Barbon

REMOTE DEBUGGING

Copy the following files from a Komodo installation to the target system

    <Komodo InstallDir>/perllib/* <TargetDir>

Set the following shell variables. On Windows use set instead of export, use double-quoting instead of single-quoting, and use backslashes instead of forward-slashes.

    export PERLDB_OPTS=RemotePort=hostname:port
    export PERL5DB='BEGIN { require q(<TargetDir>/perl5db.pl) }'
    export PERL5LIB=<TargetDir>
    export DBGP_IDEKEY="username"

FLAGS, FLAGS, FLAGS

There is a certain C programming legacy in the debugger. Some variables, such as $single, $trace, and $frame, have "magical" values composed of 1, 2, 4, etc. (powers of 2) OR'ed together. This allows several pieces of state to be stored independently in a single scalar.

$signal

Used to track whether or not an INT signal has been detected. DB::DB(), which is called before every statement, checks this and puts the user into command mode if it finds $signal set to a true value.

$single

Controls behavior during single-stepping. Stacked in @stack on entry to each subroutine; popped again at the end of each subroutine.

  • 0 - run continuously.

  • 1 - single-step, go into subs. The 's' command.

  • 2 - single-step, don't go into subs. The 'n' command.

  • 4 - print current sub depth (turned on to force this when "too much recursion" occurs.

@saved

Saves important globals ($@, $!, $^E, $,, $/, $\, $^W) so that the debugger can substitute safe values while it's running, and restore them when it returns control.

@stack

Saves the current value of $single on entry to a subroutine. Manipulated by the c command to turn off tracing in all subs above the current one.

%dbline

Keys are line numbers, values are "condition\0action". If used in numeric context, values are 0 if not breakable, 1 if breakable, no matter what is in the actual hash entry.

DEBUGGER INITIALIZATION

The debugger\'s initialization actually jumps all over the place inside this package. This is because there are several BEGIN blocks (which of course execute immediately) spread through the code. Why is that?

The debugger needs to be able to change some things and set some things up before the debugger code is compiled; most notably, the $deep variable that DB::sub uses to tell when a program has recursed deeply. In addition, the debugger has to turn off warnings while the debugger code is compiled, but then restore them to their original setting before the program being debugged begins executing.

The first BEGIN block simply turns off warnings by saving the current setting of $^W and then setting it to zero. The second one initializes the debugger variables that are needed before the debugger begins executing. The third one puts $^X back to its former value.

We'll detail the second BEGIN block later; just remember that if you need to initialize something before the debugger starts really executing, that's where it has to go.

DEBUGGER INITIALIZATION

The debugger starts up in phases.

BASIC SETUP

First, it initializes the environment it wants to run in: turning off warnings during its own compilation, defining variables which it will need to avoid warnings later, setting itself up to not exit when the program terminates, and defaulting to printing return values for the r command.

DEBUGGER SETTINGS

Keep track of the various settings in this hash

StopReasons

Why we are stopping

  • 0 - started program

  • 1 - user did a step_into

  • 2 - user did a step_over

  • 4 - user did a step_out

  • 8 - program hit max-recursion depth

findAndAddFunctionBreakPoints

Four ways to break on a sub:

1. No file or line # given: break at the start (or end) of all instances of all loaded subs with the given name

2. File given, no line #: break at the start (or end) of all instances ot the named function in the given file

3. File and line # given: use the line # to identify which instance of a function that matches the given name. This is to allow for a file that contains multiple packages, with the same function name in more than one package.

4. No file given, but line # given: This is weird, but we have a story: Find all instances of the given function, and accept only if the given line # falls in the function's range.

                    my %opts;
                {
                    local *ARGV = \@cmdArgs;
                    shift @ARGV;
                    getopts('c:l:', \%opts);
                }
                if ($opts{c} == 1) {
                } else {
                    dblog("stdin: opts{c} = $opts{c}\n") if $ldebug;
                    next CMD;
                }
                my $dataLength = $opts{l}; # ignore
                my $encodedData = join("", @cmdArgs);
                my $actualData = decodeData($encodedData, 'base64');
                dblog "stdin: [$actualData]\n" if $ldebug;

parse_options

Trimmed down version for processing only RemotePort=\d+

DB::fake

Contains the at_exit routine that the debugger uses to issue the Debugged program terminated ... message after the program completes. See the END block documentation for more details.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 3326:

Unknown directive: =head