Debugging Perl programs#

Perl ships with an unusually complete debugging surface: a built-in statement-by-statement debugger, a regex-engine tracer, a documented API for writing alternative debuggers, and a CPAN ecosystem of profilers, leak finders, post-mortem tools, and IDE integrations. pperl’s reimplementation preserves the interpreter’s hook points, so the entire stack works: perl -d, Devel::NYTProf, Devel::Cover, Perl::LanguageServer, and the rest of the -d:Module family.

This guide covers the p5 runtime (the default). The pp runtime has no interactive debugger; use the p5 runtime when debugging.

Which chapter do I want?#

Symptom

Start here

Program misbehaves and I want to inspect it live

interactive-debugger

Program crashes with a cryptic message

exceptions

I want to sprinkle prints and dumps

print-and-die

I want to turn more mistakes into compile errors

preflight

I need to stop on a specific line or condition

breakpoints

I need to see what a data structure actually holds

inspecting-state

I want to see every line / sub as it executes

tracing

I want breakpoints in VS Code / Neovim

ide-dap

The three layers of this guide#

  • Orientation — this page.

  • Working programmer — the chapters listed above. Each is self-contained; reading a single one is enough to solve the problem it names.

Known gaps#

Debugging surfaces where the ecosystem itself is thin, or where pperl’s implementation has not reached parity with upstream. Named here so readers do not waste time on them.

  • Regex tracer output format. pperl’s regex engine is a native reimplementation; use re 'debug' produces a trace but node names and field formats are not byte-identical to perl5’s. Consumers that parse the trace (few exist) will need adjustment.

  • B::* introspection modules. B::Deparse, B::Concise, and kin expose perl5’s op graph. pperl’s op representation differs; native equivalents are in progress.

  • XS-dependent introspection modules. Devel::Peek, Devel::FindRef, Devel::Gladiator, Devel::Refcount, Devel::Size, Devel::MAT::Dumper, Devel::Leak family — all reach the SV through XS (C-level macros against the SV pointer). pperl’s p5 runtime mirrors perl5’s SV layout faithfully, but XS loading is not supported; these modules therefore need native (Rust) reimplementations that expose the same Perl-level API. Pure-Perl Devel::Peek-workalike functionality is already provided natively by the built-in Devel::Peek; the others are in progress.

  • Enbugger on Perl ≥ 5.38. Last release 2012; works anecdotally on modern perls but has no active maintainer. The gdb-inject-perl path is more reliable.

  • Async provenance. No Perl equivalent to Node’s AsyncLocalStorage: a Future that fails in a distant callback carries no automatic record of who scheduled it.

  • Sentry breadcrumbs. Sentry::Raven is functional but maintenance-only; no first-class breadcrumb support. The OpenTelemetry Perl SDK is the forward path for new installations.

  • Perl::LanguageServer attach-to-running-process. Launch is supported; post-hoc attach is not.

See also#