Home / Alt manpages / perldebguts(1)

  • perldebguts(1)
  • User command
  • linux

Inspect Perl's Debugger Hooks Without Guessing

By the end of this guide you will be able to attach a tiny debugger to a Perl program, observe statement and subroutine hooks, and turn on regular-expression tracing when a pattern behaves unexpectedly. The examples target the installed Perl 5.38.2 and its matching perl-doc package. Allow about 15 minutes if you already have a script to inspect, or 25 minutes if you are working through the examples.

What this page is for

perldebguts is not the ordinary debugger tutorial. It documents the low-level interface that Perl exposes when you run with -d: the DB package, debugger variables, source-line storage, breakpoint hashes and regular-expression diagnostics. That makes it useful when the standard debugger is not showing enough, or when you need to understand a debugger extension.

There is a practical boundary here. The manpage labels undocumented variables and functions as internal, and says they may change without notice. Treat names such as %DB::sub and @DB::dbline as version-specific inspection points, not as a stable application interface.

Prerequisites and a safe workspace

  1. Check the interpreter and documentation versions.
perl -v
dpkg-query -W -f='${Package} ${Version}\n' perl-doc

On the machine used for this guide, the interpreter reports Perl 5.38.2 and the package is perl-doc 5.38.2-3.2ubuntu0.6. Your output may differ. No elevated privileges are needed: run these commands as your normal user. Keep the examples in a temporary directory if the program under inspection has side effects.

Checkpoint

You have confirmed which Perl documentation version describes the interpreter you are about to trace.

Attach the smallest possible debugger

  1. Create a program with one subroutine call.
cat > /tmp/perl-debug-demo.pl <<'EOF'
sub add { $_[0] + $_[1] }
print add(2, 3), "\n";
EOF

The file is deliberately simple. The only state change is creating a temporary file, so recovery is just removing that file when you are done.

  1. Run Perl with a DB::DB hook that pauses at statements.
PERL5DB='sub DB::DB { print "statement\n"; scalar <STDIN> }' \
  perl -d /tmp/perl-debug-demo.pl

Press Enter each time the hook prints statement. On this version, the example prints two hook messages and then:

5

The -d switch enables Perl's debugging hooks. PERL5DB supplies code before the first line of the program, so this example does not need a debugger file on disk. If PERL5DB is absent, Perl uses perl5db.pl instead. That default is why a plain perl -d normally opens the familiar interactive debugger rather than silently doing nothing.

Checkpoint

If you see no pause, check that the command includes both -d and the environment assignment, and that the shell has not expanded the Perl code. The single quotes around the assignment are intentional.

Observe subroutine calls

  1. Replace the statement hook with a subroutine hook.
PERL5DB='{ package DB; sub DB {} sub sub { print "call: $DB::sub\n"; &$DB::sub } }' \
  perl -d /tmp/perl-debug-demo.pl

The empty DB::DB prevents a statement-by-statement stop. DB::sub is called when execution reaches a subroutine, and $DB::sub identifies the called routine. The final &$DB::sub is essential: it lets the original call continue after the diagnostic.

The output includes a call line followed by the program's result. Exact call names and the number of internal calls can vary as the program grows, so use the hook to answer a focused question rather than treating every line as a compatibility promise.

Do not paste this hook into a production command without reviewing it. A debugger hook runs inside the target process and can print arguments or other sensitive data. It can also change timing and behaviour, especially when it reads from standard input.

Know where breakpoints and source lines live

When debugging is enabled, Perl keeps compiled source lines in arrays named like @{"_<$filename"}. The corresponding hash, %{"_<$filename"}, stores breakpoint and action values keyed by line number. The values in the source array are magical in numeric context: a zero comparison indicates that a line is not breakable.

The standard debugger exposes the current file through aliases named @DB::dbline and %DB::dbline. A debugger extension can inspect individual breakpoint entries, but should avoid replacing the entire hash. The manpage specifically describes individual entries as settable and says that Perl only cares whether their values are true.

For evaluated strings, the pseudo-filename looks like (eval 34). The number is an internal identifier, not a stable source name. If an inspection script relies on it, log the surrounding context as well.

Trace a regular expression

  1. Run a small pattern with the portable re debugging pragma.
perl -Mre=debug -e '"abc123" =~ /([a-z]+)(\d+)/' 2>&1 | sed -n '1,18p'

The output starts with the compiled form of the pattern and then shows the matching process. On Perl 5.38.2 it begins along these lines:

Compiling REx "([a-z]+)(\d+)"
Final program:
   1: OPEN1 (3)
   3:   PLUS (5)
   4:     POSIXA[:lower:] (0)
...
Matching REx "([a-z]+)(\d+)" against "abc123"

use re 'debug' affects compilation and execution, and since Perl 5.9.5 it is lexically scoped. That is usually preferable to the command-line -Dr or -Drv options, which require a Perl built with -DDEBUGGING. Check that prerequisite before blaming a missing -Dr trace.

Regex traces are verbose. Redirect standard error when you want to save them, and narrow the output while experimenting. Avoid enabling them around secrets: the trace includes the pattern and the string being matched.

Configuration files and environment defaults

The standard debugger reads ./.perldb or ~/.perldb on Unix, then reads PERLDB_OPTS as if its contents were an o ... debugger command. These are convenient for personal settings, but they are also easy to forget when reproducing a bug. For a clean comparison, inspect the environment and run from a directory without an unexpected .perldb.

env | grep -E '^(PERL5DB|PERLDB_OPTS)=' || true
test -e .perldb && echo "local .perldb is active"

Do not put passwords, tokens or private input in these files or variables. They can affect every perl -d invocation in that shell. To undo the temporary environment setting, start a new shell or run unset PERL5DB PERLDB_OPTS. Remove only a test .perldb after checking its contents; do not delete a shared configuration blindly.

Done means

  • You confirmed the installed Perl and perl-doc versions.
  • You used PERL5DB with -d to observe a statement or subroutine hook.
  • You know that %DB::sub, @DB::dbline and related names are internal details.
  • You can enable scoped regex tracing with use re 'debug' or -Mre=debug.
  • You checked .perldb, PERL5DB and PERLDB_OPTS when output did not match expectations.