How does the perl debugger find the source lines

Discussion in 'Perl Misc' started by Peter J. Holzer, Dec 26, 2013.

  1. I'm currently writing a plugin for qpsmtpd, which means that both the
    plugin and the tests are read from a file, massaged a bit, compiled via
    eval() and finally the test framework calls the test methods.

    This seems to confuse the debugger a bit, because it looks like this:

    | Qpsmtpd::plugin::run_tests(/home/hjp/wrk/qpsmtpd/t/Test/Qpsmtpd/Plugin.pm:36):
    | 36: $plugin->$method();
    | DB<2> s
    | Qpsmtpd::plugin::no_bcc::pass1(t/plugin_tests/no_bcc:9):
    | 9:
    | DB<2> n
    | Qpsmtpd::plugin::no_bcc::pass1(t/plugin_tests/no_bcc:11):
    | 11:
    | DB<2> n
    | Qpsmtpd::plugin::no_bcc::pass1(t/plugin_tests/no_bcc:12):
    | 12:
    | DB<2>

    The interesting thing is that it shows the correct source file
    ("t/plugin_tests/no_bcc") and the correct line numbers (9, 11, 12), but
    not the contents of the lines, which look like this:

    9 my ($self) = @_;
    10
    11 my $qp = $self->qp;
    12 $qp->command("rset");

    So, if the debugger knows the file and the line, why can't it display
    the content?

    hp

    --
    _ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
    |_|_) | | Man feilt solange an seinen Text um, bis
    | | | | die Satzbestandteile des Satzes nicht mehr
    __/ | http://www.hjp.at/ | zusammenpaƟt. -- Ralph Babel
    Peter J. Holzer, Dec 26, 2013
    #1
    1. Advertising

  2. Ben Morrow <> writes:
    > Quoth "Peter J. Holzer" <>:
    >> I'm currently writing a plugin for qpsmtpd, which means that both the
    >> plugin and the tests are read from a file, massaged a bit, compiled via
    >> eval() and finally the test framework calls the test methods.
    >>
    >> This seems to confuse the debugger a bit, because it looks like this:

    > [...]
    >>
    >> The interesting thing is that it shows the correct source file
    >> ("t/plugin_tests/no_bcc") and the correct line numbers (9, 11, 12), but
    >> not the contents of the lines, which look like this:
    >>
    >> 9 my ($self) = @_;
    >> 10
    >> 11 my $qp = $self->qp;
    >> 12 $qp->command("rset");
    >>
    >> So, if the debugger knows the file and the line, why can't it display
    >> the content?

    >
    > I'll see if I can come up with a more intelligent answer later, but to
    > start with you might want to read perldoc perl5db.pl (particularly 'DATA
    > STRUCTURES MAINTAINED BY CORE'), the entry for $^P in perlvar, and
    > perhaps perldoc perldebguts.


    The simple answer seems to be 'because the array perl uses to locate
    source lines' (assuming the path to the source file was a/b/c.pl, the
    corresponding array would be

    @_<a/b/c.pl

    in package main) doesn't contain the code.

    Example showing how to access that:

    ,----
    | [rw@sable]/tmp#perl -d ab/a.pl
    |
    | Loading DB routines from perl5db.pl version 1.32
    | Editor support available.
    |
    | Enter h or `h h' for help, or `man perldebug' for more help.
    |
    | main::(ab/a.pl:1): print 1;
    | DB<1> $a = *{"_<ab/a.pl"}{ARRAY}
    |
    | DB<2> p @$a
    | BEGIN { require 'perl5db.pl' };
    | print 1;
    | print 2;
    `----

    It is possible to load the source code lines into this array (offsetted
    by 1) and the debugger then happily uses it.

    > Alternatively you might want to find a way to avoid using the debugger.
    > IME it causes more problems than it solves; for interactive debugging I
    > find Devel::REPL useful.


    "Devel::REPL - a modern perl interactive shell"

    As usual, modern means "It prints 'Hello, world!'" but it needs six
    order of magnitude more infrastructure code than a simple

    perl -e 'print "Hello, World!\n"'

    would require" ...
    Rainer Weikusat, Dec 29, 2013
    #2
    1. Advertising

  3. On 2013-12-30 00:33, Ben Morrow <> wrote:
    > Quoth Rainer Weikusat <>:
    >> It is possible to load the source code lines into this array (offsetted
    >> by 1) and the debugger then happily uses it.

    >
    > Yes. The more interesting question is why they weren't there already; I
    > don't yet have an answer to that.


    I played around with it a bit more, but I am just becoming more
    confused. It's not like eval never fills in @{"_<$filename"}. In this
    simple test script:

    #!/usr/bin/perl
    use v5.10;

    eval ('
    #line 1 "3a"
    use v5.10;

    sub foo {
    say "bla";
    }
    ');

    foo();
    say;

    @{"_<3a"} is filled with the correct lines and I can singlestep into foo().

    So, sometimes the lines are there and sometimes they aren't.

    I'll try to come up with a minimal script which exhibits the faulty
    behaviour.

    hp

    --
    _ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
    |_|_) | | Man feilt solange an seinen Text um, bis
    | | | | die Satzbestandteile des Satzes nicht mehr
    __/ | http://www.hjp.at/ | zusammenpaƟt. -- Ralph Babel
    Peter J. Holzer, Dec 30, 2013
    #3
  4. Ben Morrow <> writes:
    > Quoth Rainer Weikusat <>:


    [...]

    >> "Devel::REPL - a modern perl interactive shell"
    >>
    >> As usual, modern means "It prints 'Hello, world!'" but it needs six
    >> order of magnitude more infrastructure code than a simple
    >>
    >> perl -e 'print "Hello, World!\n"'
    >>
    >> would require" ...

    >
    > Yup. It also gets all the hard things right, like running pieces of code
    > read separately in the same lexical context (or not, as you like).


    I've actually casually read through the 'core' of the implementation
    which is 123 lines of code and seems to be little more than a wrapper
    around Term::Readline (the perl debugger will use that as well if
    available) with a moose chained to its ankle because someone considered
    that a fashionably pet in 2007. If the author is really convinced to
    have solved any 'hard problems' (minus getting his head around the issue
    in the first place) in there, I seriously hope that he doesn't ever
    encounter a hard problem as this will probably blow a fuse in his head.

    OTOH, even the most trivial problem can be made to look very commanding
    by a suitably obfuscated solution, eg use

    sub wrap_as_sub {
    my ($self, $line, %args) = @_;
    return qq!sub {\n!. ( $args{no_mangling} ? $line : $self->mangle_line($line) ).qq!\n}\n!;
    }

    instead of

    sprintf('sub { %s }', $args{no_mangling} ? $line : $self->mangle_line($line));

    minus any of the fancy features (including sensible handling of
    exceptions thrown by the executed code), this is

    ----------
    use Term::ReadLine;

    sub run
    {
    eval($_[0]);
    print STDERR ("XX: $@") if $@;
    }

    my ($term, $line);

    $term = Term::ReadLine->new('Perl ERPL');
    print(run($line), "\n") while defined($line = $term->readline('Perl ERPL>'));
    print("\n");
    ----------

    (Erpel is the German word for a male duck)
    Rainer Weikusat, Dec 30, 2013
    #4
  5. Rainer Weikusat <> writes:

    [...]

    > sub run
    > {
    > eval($_[0]);
    > print STDERR ("XX: $@") if $@;
    > }


    The 2nd line was a 'last second' addition to make this print compiler
    errors encountered during eval which eats the return value of the
    former. Slightly more complicated demo which deals with that:

    ----------
    sub dorun
    {
    eval($_[0]);
    }

    sub run
    {
    my @r;

    @r = &dorun;
    return @r unless $@;

    print STDERR ("XX: $@");
    return;
    }
    -----------

    A supposed-to-be-reusable class providing such a feature should probably
    take some more pain in order to provide a clean execution environment
    than just using an 'empty sub', eg, it should localize all or at least
    some of the global variables affecting execution of Perl code in order
    to avoid leaking parts of the 'executor' environment into the executed
    code and the same in the opposite direction (especially @_ and $_).
    Rainer Weikusat, Dec 30, 2013
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sam Roberts
    Replies:
    0
    Views:
    89
    Sam Roberts
    Jan 31, 2005
  2. Wybo Dekker
    Replies:
    1
    Views:
    350
    Yukihiro Matsumoto
    Nov 15, 2005
  3. Markus Dehmann
    Replies:
    1
    Views:
    133
    Tad McClellan
    Sep 26, 2006
  4. Kuhl
    Replies:
    1
    Views:
    278
    Tad J McClellan
    Dec 22, 2008
  5. Robert Oschler
    Replies:
    1
    Views:
    221
    Mcginkel
    Sep 5, 2005
Loading...

Share This Page