http://www.perlmonks.org?node_id=924268

PerlOnTheWay has asked for the wisdom of the Perl Monks concerning the following question:

AFAIK break point can only be set at assembly instruction level with ptrace, and that's what happens when we set a bp on a specific line of C code because gdb understands c well enough that it knows at which instruction to set the bp.

But how does perl debugger work? It needs to somehow know the exact instruction for the bp set on a perl statement.

How is that done?

Replies are listed 'Best First'.
Re: How perl debugger breakpoint works?
by ikegami (Patriarch) on Sep 05, 2011 at 16:17 UTC

    I don't see why breakpoints would be attached to machine opcodes or addresses. Perl code runs in a virtual machine of sorts, so they would be attached to Perl opcodes or lines. (Yes, line information is available. It's stored in nextstate ops for warnings and die.) Sorry, I don't know any details beyond that.

    Example Perl opcodes:

    $ perl -MO=Concise,-exec -e' print "Hello, "; print "World!\n"; ' 1 <0> enter 2 <;> nextstate(main 1 -e:2) v:{ 3 <0> pushmark s 4 <$> const(PV "Hello, ") s 5 <@> print vK 6 <;> nextstate(main 1 -e:3) v:{ 7 <0> pushmark s 8 <$> const(PV "World!\n") s 9 <@> print vK a <@> leave[1 ref] vKP/REFC -e syntax OK
Re: How perl debugger breakpoint works?
by chromatic (Archbishop) on Sep 06, 2011 at 02:06 UTC

    When compiling code with the debugger active, Perl replaces what would normally be nextstate ops with dbstate ops. The latter check for breakpoints when encountered. See pp_dbstate in pp_ctl.c.

      Where does Perl replace nextstate with dbstate?

      When I search OPf_SPECIAL,there're too many stuff popped up..

        See the newSTATEOP function in op.c. The optree generator calls this function during compilation.

Re: How perl debugger breakpoint works?
by DanielSpaniel (Scribe) on Sep 05, 2011 at 17:52 UTC

    You may find it useful to see the information available by doing:

    perldoc perldebug

    Unless I am misunderstanding you, then using the debugger is pretty straightforward. So, for example, if you want to debug a program from the command line, you'd simply do:

    perl -d program_name

    ... and then you can step through each line using the letter "n" (or you can just hit enter, after you've hit "n" the first time). If you want to go into a sub-routine then you type "s" instead of "n", when you get to that line (and then do "n" again once you're in there). To show line numbers when you're debugging you can just scroll through using the letter "l". Using "l" doesn't execute code, it just lists it; so, when you're done with listing it you can just carry on from where you were with an "n". If you want to break on a specific line number then, once you've started the program in debug mode you can just type in "b 99" (for example), where "99" is the line number. Then just type in "c" to continue the program. It will continue without intervention until/if it reaches the breakpoint. Once you get familiar with it you can also break on conditions too, such as when a variable =xyz.

    Does that help?

      He's not asking how to use the debugger, but rather how it works under the hood. See for example (based on C) "Playing with ptrace". You might be interested in perldebguts.

        Yup, I want to know how debugger works.

        I'm very familiar with its usage.

        Every debugger needs to call ptrace finally, how does the bridge between Perl code and assembly work?

        Yeah, realized that afterwards, but then figured it might be helpful to anybody actually looking to see how to use the debugger too. Apologies for the misguided post, and thanks for the links - very interesting to know about all that under-the-hood bits and pieces.
Re: How perl debugger breakpoint works?
by pemungkah (Priest) on Sep 07, 2011 at 08:11 UTC
    The Perl debugger has two parts - one in the Perl internals, which hooks into the optree walk that happens during the execution of your program, and the other in perl5db.pl, found in your Perl library.

    perl5db.pl does all the work of tracking breakpoints, handling commands, and executing code in the context of the programming being debugged.

    Here's how a breakpoint works:

    1. You run your program under the debugger by adding the -d flag.
    2. The debugger is loaded and initialized. Perl switches the nextops to dbnexts.
    3. The debugger initializes, and prints its prompt, starting a loop in DB::DB that reads, executes, and prompts.
    4. You ask to add a breakpoint via its b command.
    5. The debugger stores this in the hash %<_yourscript.pl (yes, that's the real name of the hash; inside the debugger it's aliased to %dbline). The keys are line numbers, and the values are 1 if the line is considered breakable by the Perl core, and 0 if not. Any true value stored in %dbline sets a breakpoint for that line (assuming the line is breakable).
    6. You enter 'c' to continue to the next breakpoint. The debugger sets the variable $DB::single to 0, causing the Perl core to simply move on to the next op without calling the debugger as long as %dbline{$current_line} doesn't exist.
    7. When the core reaches a breakpoint, it sets $DB::singleback to 1, causing the core to call DB::DB (the debugger's read/execute/print core) just before every line again. You're back in single-step mode.
    So the debugger's really just a special Perl program that sets up specific subroutines and watches specific variables shared with the Perl core that contain the source code and breakpoints. This allows the same core hooks to be used for all kinds of things: debuggers, tracers, test coverage, profiling.

    I've skipped over subroutine calls and other complications like eval; if you're interested in how it works, you may find reading perl5db.pl more profitable. (I wrote the internal docs and comments for the debugger, which is why I'm holding forth at such length about it here.)

      which is why I'm holding forth at such length about it here.

      WOW, what is that a golf reference or something?