Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

PadWalker and Safe - getting the lexicals

by shushu (Scribe)
on Oct 09, 2002 at 15:29 UTC ( [id://203962]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks !
My task is to create a Perl reporting for unknown code.
The idea is to execute piece of Perl code in a place it can't harm anything, and create a "simple" report out of it.
The report should be a printout of every line, and (the hard work) the values of the variables in tihs line.
How do we do all of that ?
1. Before the execution we use "Xref.pm" to get detailed data regarding to every line and the variables in it, global and lexical.
2. Using "Safe.pm" and "Safe::Hole.pm" we create a compartment where we execute the code.
3. While executing we use a modified "Devel::Trace" to get every line executed.
- To get the global variables we use "dumpvar.pl", similar to the way perl5db do, giving it the list of the variables we took from Xref before.
Up to here (surprise) it all works fine. Here is the hard stuff...
- To get the lexical variables we needed something special and we found "PadWalker.pm", peek_my().
The problem is that PadWalker gives proper information up to the minute we try to use it via the Safe compartement. There, it seems it can't "penetrate" the compartement...
The new Trace relevant code is this, called from sub DB::DB -
sub peek_lexicals { my $h = peek_my(2); print "\nlexicals-----------------------\n"; print "keys=", join (", ", keys %$h), "-\n"; print "values=", join (", ", values %$h), "-\n"; print "end of lexicals-----------------------\n"; }
The unsafe code is "unsafe.pl":
my $b = 42; $c = "Hallo world\n"; print "printing lexical $b\n"; print "printing global $c\n";
The checking code is "check_code.pl":
use Safe; use Safe::Hole; my $SCRIPT_NAME = "unsafe.pl"; $QTL_HOLE_CPT = new Safe::Hole; $QTL_CPT = new Safe("QTL"); $Devel::Trace_shushu2::TRACE= 1; $QTL_CPT->rdo ( "$SCRIPT_NAME" );
When executed straight ("perl -d:Trace unsafe.pl") I get:
lexicals----------------------- keys=$b- values=SCALAR(0x810811c)- end of lexicals----------------------- lexicals----------------------- keys=$b- values=SCALAR(0x810811c)- end of lexicals----------------------- printing lexical 42 lexicals----------------------- keys=$b- values=SCALAR(0x810811c)- end of lexicals----------------------- printing global Hallo world
When executed via the checker ("perl -d:Trace_shushu2 check_code.pl") I get:
lexicals----------------------- keys=$SCRIPT_NAME- values=SCALAR(0x8108144)- end of lexicals----------------------- lexicals----------------------- keys=$SCRIPT_NAME- values=SCALAR(0x8108144)- end of lexicals----------------------- lexicals----------------------- keys=$SCRIPT_NAME- values=SCALAR(0x8108144)- end of lexicals----------------------- lexicals----------------------- keys=$default_share, $default_root, $VERSION- values=SCALAR(0x824f76c), SCALAR(0x810b704), SCALAR(0x8225304)- end of lexicals----------------------- lexicals----------------------- keys=$default_share, $default_root, $VERSION- values=SCALAR(0x824f76c), SCALAR(0x810b704), SCALAR(0x8225304)- end of lexicals----------------------- lexicals----------------------- keys=$default_share, $default_root, $VERSION- values=SCALAR(0x824f76c), SCALAR(0x810b704), SCALAR(0x8225304)- end of lexicals----------------------- printing lexical 42 lexicals----------------------- keys=$default_share, $default_root, $VERSION- values=SCALAR(0x824f76c), SCALAR(0x810b704), SCALAR(0x8225304)- end of lexicals----------------------- printing global Hallo world
* I tried to play with the level given to the &peek_my, with no good effect.
* robin (hopefully reading...) - In your jurnal (http://use.perl.org/~robin/journal) you wrote that PadWalker 0.8 is used in the new debugger to do exactly what I need. Can it be used here ?
Any suggestions ?
Thanks,
shushu

Replies are listed 'Best First'.
Re: PadWalker and Safe - getting the lexicals
by robin (Chaplain) on Oct 10, 2002 at 12:26 UTC
    Well, this is certainly a new one! I've never even dreamed of using PadWalker with a Safe compartment before :-)

    I'm not familiar with the details of how Safe works internally, but it's almost certainly fair to say that PadWalker will need to be modified to detect the Safe compartment and behave appropriately. In other words you'll need to dirty your hands with perlguts a little, to make this work. Probably.

    The only other idea I have is that it might work if you can load PadWalker and Devel::Trace inside the same Safe compartment as the code you're executing. Have you tried that?

      Thanks for the answer.
      Regarding to your idea - I was sure I can execute the debugger only via "perl -d", but since you reffered as if it is possible other way I looked again.

      From "perldebguts" under "Debugger Internals":
      "These mechanisms are enabled by calling Perl with the -d switch."
      It seems that the sub DB::DB is not executed unless you use the "-d" flag.
      Do I miss something here ???

      Thanks,
      shushu
        And another note (sorry I do it in parts...)

        From looking around I understand that the problem to enable the debugger. In Apache, when wanted to enable the debugger, it seems that special code was needed:
        From modperl archive (http://www.geocrawler.com/archives/3/182/2000/12/0/4895655/) -
        > there is quite a bit of overhead when -d is enabled. have a look at
        > Apache::DB.xs, there's in init_debugger() function todo what -d does. if
        > another method was added to turn it off, after the registry script was
        > compiled, the overhead would be reduced a great deal.

        shushu
      Before I jump into the cold water of perlguts I wanted to check another option to get what I want.
      In short - all I want it to print to a file the value of every lexical variable used in the executed code.

      The second idea was to overload all of the operators, and make them just print before doing their job.
      Well, we thought about this option only because we never actually did overloading.
      After reading the stuff I understand that overloading is done only for specific types, so to use it the code shoud have something like:
      my $a = new OVERLOADED "value";
      Which is impossible in our case.

      The question is - is there a way to overload ALL of the basic types of Perl and inherit it "quietly" to the Safe compartement ?

      TIA,
      shushu
      Hi (all and robin),
      Well, we had a good "fight", but now we are sure that in order to get the lexical information we do need to get into perlguts.
      The question now is - how to do it ?
      From where do we start ?
      Unfortunately we don't have the time to play around, and we need to understand fast whether it will take us 2 days or 2 weeks. Too many deadlines...

      - Do we need to get into Perl code, or do we need only PadWalker code ?
      - Where do we get PadWalker code ?
      - Does a standard RH 7.3 installation is enough, or should we get some other development environment ?

      TIA,
      shushu

        I haven't been motivated enough to see what the inside of a Safe::Hole->reval looks like but now that you've decided to go perlguts your first thing to do is to look at the B module. In my sig you'll notice an example of a script getting the current CV via B::svref_2object(sub {} )->OUTSIDE. I would initially recommend you read Gisle Aas' Illustrated PerlGuts, then Simon Cozens' internals tutorial and if that isn't enough descend into perlguts and perlhack. The key here is you're just walking structures. You aren't going to have to alter stuff so the documentation is to guide you in using B to walk all over.

        __SIG__ printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B:: +svref_2object(sub{})->OUTSIDE

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://203962]
Approved by kvale
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-03-29 05:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found