Do you know where your variables are? | |
PerlMonks |
Enabling or disabliing the debugger at runtimeby diotalevi (Canon) |
on Jul 16, 2007 at 05:34 UTC ( [id://626777]=perlmeditation: print w/replies, xml ) | Need Help?? |
I had a problem at work where two very small iterations of the debugger somehow triggered an "Out of memory" error. I think there was a little bit of memory corruption going on but that wasn't in the scope of what I was willing or able to tackle in that moment. So instead of solving the real problem, I learned how to load the debugger during runtime. I've no reason to think this method isn't applicable to removing the debugger either. By the way, the punchline is that the module Enbugger is an implementation of the ideas in this post and with it you don't need to start perl with the -d flag or incur any debugging overhead. It does a bit more than it needs to but that's only because my understanding of how to do this evolved while I writing the module. Some future version (the current version is 0.03) will take this information into account. In fact, feel free to do this yourself if you wish. Email me at jjore at cpan.org to get PAUSE permissions if you're interested. The only real trick appears to be to modify all "nextstate" opnodes to become "dbstate" opnodes. My first thought when approaching this problem was to hook the runops loop and change all OP_NEXTSTATE ops to OP_DBSTATE. This has two problems. Currently executing subroutines aren't affected because their runloop is already entered. I wasn't being discriminating about which nextstate ops to modify. I'd turned the debugger on itself. While this is interesting in theory, the debugger hasn't been tested while operating on itself and I'm not sure if this would break stuff. Without debugging:
With debugging:
In the above code, you can see an optree for the "main" part of a program including two "nextstate" operations. They occur roughly anywhere there could be a semi-colon in your perl program. If you compare to the debugged version, the same places that had nextstate operations now contain dbstate operations but were otherwise the same op class: COP. op.c: Perl_newSTATEOP
The above snippet of C code show the only fundamental difference between DBSTATE and NEXTSTATE ops. The op_type field which is largely informational and then the function pointer from PL_ppaddr[...]. Switching between debugging and non-debugging is as simple as loading perl5db.pl and changing all the relevant opcodes. Simple thanks to B::Utils! Enbugger.pm transforms all nextstate ops into breakpoints
Enbugger.xs does an ickle bit of magic. The XS safety is lax here but I expect to get only B::COP objects. All B::* objects are just blessed scalars where the integer value is the pointer value. You can easily marshal them back into COP or SVs just by turning the ints into pointers.
Removing the debugger at runtime is just the opposite operation to all the same COP nodes. Change all the nodes where ->name eq 'dbstate' and set cop->op_type = OP_NEXTSTATE; cop->op_ppaddr = PL_ppaddr[ OP_NEXTSTATE ]. Cake's done! ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊
Back to
Meditations
|
|