1N/A# Devel::Peek - A data debugging tool for the XS programmer
1N/A# The documentation is after the __END__
1N/A
1N/Apackage Devel::Peek;
1N/A
1N/A$VERSION = '1.01';
1N/A$XS_VERSION = $VERSION;
1N/A$VERSION = eval $VERSION;
1N/A
1N/Arequire Exporter;
1N/Ause XSLoader ();
1N/A
1N/A@ISA = qw(Exporter);
1N/A@EXPORT = qw(Dump mstat DeadCode DumpArray DumpWithOP DumpProg
1N/A fill_mstats mstats_fillhash mstats2hash runops_debug debug_flags);
1N/A@EXPORT_OK = qw(SvREFCNT SvREFCNT_inc SvREFCNT_dec CvGV);
1N/A%EXPORT_TAGS = ('ALL' => [@EXPORT, @EXPORT_OK]);
1N/A
1N/AXSLoader::load 'Devel::Peek';
1N/A
1N/Asub import {
1N/A my $c = shift;
1N/A my $ops_rx = qr/^:opd(=[stP]*)?\b/;
1N/A my @db = grep m/$ops_rx/, @_;
1N/A @_ = grep !m/$ops_rx/, @_;
1N/A if (@db) {
1N/A die "Too many :opd options" if @db > 1;
1N/A runops_debug(1);
1N/A my $flags = ($db[0] =~ m/$ops_rx/ and $1);
1N/A $flags = 'st' unless defined $flags;
1N/A my $f = 0;
1N/A $f |= 2 if $flags =~ /s/;
1N/A $f |= 8 if $flags =~ /t/;
1N/A $f |= 64 if $flags =~ /P/;
1N/A $^D |= $f if $f;
1N/A }
1N/A unshift @_, $c;
1N/A goto &Exporter::import;
1N/A}
1N/A
1N/Asub DumpWithOP ($;$) {
1N/A local($Devel::Peek::dump_ops)=1;
1N/A my $depth = @_ > 1 ? $_[1] : 4 ;
1N/A Dump($_[0],$depth);
1N/A}
1N/A
1N/A$D_flags = 'psltocPmfrxuLHXDSTR';
1N/A
1N/Asub debug_flags (;$) {
1N/A my $out = "";
1N/A for my $i (0 .. length($D_flags)-1) {
1N/A $out .= substr $D_flags, $i, 1 if $^D & (1<<$i);
1N/A }
1N/A my $arg = shift;
1N/A my $num = $arg;
1N/A if (defined $arg and $arg =~ /\D/) {
1N/A die "unknown flags in debug_flags()" if $arg =~ /[^-$D_flags]/;
1N/A my ($on,$off) = split /-/, "$arg-";
1N/A $num = $^D;
1N/A $num |= (1<<index($D_flags, $_)) for split //, $on;
1N/A $num &= ~(1<<index($D_flags, $_)) for split //, $off;
1N/A }
1N/A $^D = $num if defined $arg;
1N/A $out
1N/A}
1N/A
1N/A1;
1N/A__END__
1N/A
1N/A=head1 NAME
1N/A
1N/ADevel::Peek - A data debugging tool for the XS programmer
1N/A
1N/A=head1 SYNOPSIS
1N/A
1N/A use Devel::Peek;
1N/A Dump( $a );
1N/A Dump( $a, 5 );
1N/A DumpArray( 5, $a, $b, ... );
1N/A mstat "Point 5";
1N/A
1N/A use Devel::Peek ':opd=st';
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/ADevel::Peek contains functions which allows raw Perl datatypes to be
1N/Amanipulated from a Perl script. This is used by those who do XS programming
1N/Ato check that the data they are sending from C to Perl looks as they think
1N/Ait should look. The trick, then, is to know what the raw datatype is
1N/Asupposed to look like when it gets to Perl. This document offers some tips
1N/Aand hints to describe good and bad raw data.
1N/A
1N/AIt is very possible that this document will fall far short of being useful
1N/Ato the casual reader. The reader is expected to understand the material in
1N/Athe first few sections of L<perlguts>.
1N/A
1N/ADevel::Peek supplies a C<Dump()> function which can dump a raw Perl
1N/Adatatype, and C<mstat("marker")> function to report on memory usage
1N/A(if perl is compiled with corresponding option). The function
1N/ADeadCode() provides statistics on the data "frozen" into inactive
1N/AC<CV>. Devel::Peek also supplies C<SvREFCNT()>, C<SvREFCNT_inc()>, and
1N/AC<SvREFCNT_dec()> which can query, increment, and decrement reference
1N/Acounts on SVs. This document will take a passive, and safe, approach
1N/Ato data debugging and for that it will describe only the C<Dump()>
1N/Afunction.
1N/A
1N/AFunction C<DumpArray()> allows dumping of multiple values (useful when you
1N/Aneed to analyze returns of functions).
1N/A
1N/AThe global variable $Devel::Peek::pv_limit can be set to limit the
1N/Anumber of character printed in various string values. Setting it to 0
1N/Ameans no limit.
1N/A
1N/AIf C<use Devel::Peek> directive has a C<:opd=FLAGS> argument,
1N/Athis switches on debugging of opcode dispatch. C<FLAGS> should be a
1N/Acombination of C<s>, C<t>, and C<P> (see B<-D> flags in L<perlrun>).
1N/AC<:opd> is a shortcut for C<:opd=st>.
1N/A
1N/A=head2 Runtime debugging
1N/A
1N/AC<CvGV($cv)> return one of the globs associated to a subroutine reference $cv.
1N/A
1N/Adebug_flags() returns a string representation of C<$^D> (similar to
1N/Awhat is allowed for B<-D> flag). When called with a numeric argument,
1N/Asets $^D to the corresponding value. When called with an argument of
1N/Athe form C<"flags-flags">, set on/off bits of C<$^D> corresponding to
1N/Aletters before/after C<->. (The returned value is for C<$^D> before
1N/Athe modification.)
1N/A
1N/Arunops_debug() returns true if the current I<opcode dispatcher> is the
1N/Adebugging one. When called with an argument, switches to debugging or
1N/Anon-debugging dispatcher depending on the argument (active for
1N/Anewly-entered subs/etc only). (The returned value is for the dispatcher before the modification.)
1N/A
1N/A=head2 Memory footprint debugging
1N/A
1N/AWhen perl is compiled with support for memory footprint debugging
1N/A(default with Perl's malloc()), Devel::Peek provides an access to this API.
1N/A
1N/AUse mstat() function to emit a memory state statistic to the terminal.
1N/AFor more information on the format of output of mstat() see
1N/AL<perldebguts/Using C<$ENV{PERL_DEBUG_MSTATS}>>.
1N/A
1N/AThree additional functions allow access to this statistic from Perl.
1N/AFirst, use C<mstats_fillhash(%hash)> to get the information contained
1N/Ain the output of mstat() into %hash. The field of this hash are
1N/A
1N/A minbucket nbuckets sbrk_good sbrk_slack sbrked_remains sbrks start_slack
1N/A topbucket topbucket_ev topbucket_odd total total_chain total_sbrk totfree
1N/A
1N/ATwo additional fields C<free>, C<used> contain array references which
1N/Aprovide per-bucket count of free and used chunks. Two other fields
1N/AC<mem_size>, C<available_size> contain array references which provide
1N/Athe information about the allocated size and usable size of chunks in
1N/Aeach bucket. Again, see L<perldebguts/Using C<$ENV{PERL_DEBUG_MSTATS}>>
1N/Afor details.
1N/A
1N/AKeep in mind that only the first several "odd-numbered" buckets are
1N/Aused, so the information on size of the "odd-numbered" buckets which are
1N/Anot used is probably meaningless.
1N/A
1N/AThe information in
1N/A
1N/A mem_size available_size minbucket nbuckets
1N/A
1N/Ais the property of a particular build of perl, and does not depend on
1N/Athe current process. If you do not provide the optional argument to
1N/Athe functions mstats_fillhash(), fill_mstats(), mstats2hash(), then
1N/Athe information in fields C<mem_size>, C<available_size> is not
1N/Aupdated.
1N/A
1N/AC<fill_mstats($buf)> is a much cheaper call (both speedwise and
1N/Amemory-wise) which collects the statistic into $buf in
1N/Amachine-readable form. At a later moment you may need to call
1N/AC<mstats2hash($buf, %hash)> to use this information to fill %hash.
1N/A
1N/AAll three APIs C<fill_mstats($buf)>, C<mstats_fillhash(%hash)>, and
1N/AC<mstats2hash($buf, %hash)> are designed to allocate no memory if used
1N/AI<the second time> on the same $buf and/or %hash.
1N/A
1N/ASo, if you want to collect memory info in a cycle, you may call
1N/A
1N/A $#buf = 999;
1N/A fill_mstats($_) for @buf;
1N/A mstats_fillhash(%report, 1); # Static info too
1N/A
1N/A foreach (@buf) {
1N/A # Do something...
1N/A fill_mstats $_; # Collect statistic
1N/A }
1N/A foreach (@buf) {
1N/A mstats2hash($_, %report); # Preserve static info
1N/A # Do something with %report
1N/A }
1N/A
1N/A=head1 EXAMPLES
1N/A
1N/AThe following examples don't attempt to show everything as that would be a
1N/Amonumental task, and, frankly, we don't want this manpage to be an internals
1N/Adocument for Perl. The examples do demonstrate some basics of the raw Perl
1N/Adatatypes, and should suffice to get most determined people on their way.
1N/AThere are no guidewires or safety nets, nor blazed trails, so be prepared to
1N/Atravel alone from this point and on and, if at all possible, don't fall into
1N/Athe quicksand (it's bad for business).
1N/A
1N/AOh, one final bit of advice: take L<perlguts> with you. When you return we
1N/Aexpect to see it well-thumbed.
1N/A
1N/A=head2 A simple scalar string
1N/A
1N/ALet's begin by looking a simple scalar which is holding a string.
1N/A
1N/A use Devel::Peek;
1N/A $a = "hello";
1N/A Dump $a;
1N/A
1N/AThe output:
1N/A
1N/A SV = PVIV(0xbc288)
1N/A REFCNT = 1
1N/A FLAGS = (POK,pPOK)
1N/A IV = 0
1N/A PV = 0xb2048 "hello"\0
1N/A CUR = 5
1N/A LEN = 6
1N/A
1N/AThis says C<$a> is an SV, a scalar. The scalar is a PVIV, a string.
1N/AIts reference count is 1. It has the C<POK> flag set, meaning its
1N/Acurrent PV field is valid. Because POK is set we look at the PV item
1N/Ato see what is in the scalar. The \0 at the end indicate that this
1N/APV is properly NUL-terminated.
1N/AIf the FLAGS had been IOK we would look
1N/Aat the IV item. CUR indicates the number of characters in the PV.
1N/ALEN indicates the number of bytes requested for the PV (one more than
1N/ACUR, in this case, because LEN includes an extra byte for the
1N/Aend-of-string marker).
1N/A
1N/A=head2 A simple scalar number
1N/A
1N/AIf the scalar contains a number the raw SV will be leaner.
1N/A
1N/A use Devel::Peek;
1N/A $a = 42;
1N/A Dump $a;
1N/A
1N/AThe output:
1N/A
1N/A SV = IV(0xbc818)
1N/A REFCNT = 1
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 42
1N/A
1N/AThis says C<$a> is an SV, a scalar. The scalar is an IV, a number. Its
1N/Areference count is 1. It has the C<IOK> flag set, meaning it is currently
1N/Abeing evaluated as a number. Because IOK is set we look at the IV item to
1N/Asee what is in the scalar.
1N/A
1N/A=head2 A simple scalar with an extra reference
1N/A
1N/AIf the scalar from the previous example had an extra reference:
1N/A
1N/A use Devel::Peek;
1N/A $a = 42;
1N/A $b = \$a;
1N/A Dump $a;
1N/A
1N/AThe output:
1N/A
1N/A SV = IV(0xbe860)
1N/A REFCNT = 2
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 42
1N/A
1N/ANotice that this example differs from the previous example only in its
1N/Areference count. Compare this to the next example, where we dump C<$b>
1N/Ainstead of C<$a>.
1N/A
1N/A=head2 A reference to a simple scalar
1N/A
1N/AThis shows what a reference looks like when it references a simple scalar.
1N/A
1N/A use Devel::Peek;
1N/A $a = 42;
1N/A $b = \$a;
1N/A Dump $b;
1N/A
1N/AThe output:
1N/A
1N/A SV = RV(0xf041c)
1N/A REFCNT = 1
1N/A FLAGS = (ROK)
1N/A RV = 0xbab08
1N/A SV = IV(0xbe860)
1N/A REFCNT = 2
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 42
1N/A
1N/AStarting from the top, this says C<$b> is an SV. The scalar is an RV, a
1N/Areference. It has the C<ROK> flag set, meaning it is a reference. Because
1N/AROK is set we have an RV item rather than an IV or PV. Notice that Dump
1N/Afollows the reference and shows us what C<$b> was referencing. We see the
1N/Asame C<$a> that we found in the previous example.
1N/A
1N/ANote that the value of C<RV> coincides with the numbers we see when we
1N/Astringify $b. The addresses inside RV() and IV() are addresses of
1N/AC<X***> structure which holds the current state of an C<SV>. This
1N/Aaddress may change during lifetime of an SV.
1N/A
1N/A=head2 A reference to an array
1N/A
1N/AThis shows what a reference to an array looks like.
1N/A
1N/A use Devel::Peek;
1N/A $a = [42];
1N/A Dump $a;
1N/A
1N/AThe output:
1N/A
1N/A SV = RV(0xf041c)
1N/A REFCNT = 1
1N/A FLAGS = (ROK)
1N/A RV = 0xb2850
1N/A SV = PVAV(0xbd448)
1N/A REFCNT = 1
1N/A FLAGS = ()
1N/A IV = 0
1N/A NV = 0
1N/A ARRAY = 0xb2048
1N/A ALLOC = 0xb2048
1N/A FILL = 0
1N/A MAX = 0
1N/A ARYLEN = 0x0
1N/A FLAGS = (REAL)
1N/A Elt No. 0 0xb5658
1N/A SV = IV(0xbe860)
1N/A REFCNT = 1
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 42
1N/A
1N/AThis says C<$a> is an SV and that it is an RV. That RV points to
1N/Aanother SV which is a PVAV, an array. The array has one element,
1N/Aelement zero, which is another SV. The field C<FILL> above indicates
1N/Athe last element in the array, similar to C<$#$a>.
1N/A
1N/AIf C<$a> pointed to an array of two elements then we would see the
1N/Afollowing.
1N/A
1N/A use Devel::Peek 'Dump';
1N/A $a = [42,24];
1N/A Dump $a;
1N/A
1N/AThe output:
1N/A
1N/A SV = RV(0xf041c)
1N/A REFCNT = 1
1N/A FLAGS = (ROK)
1N/A RV = 0xb2850
1N/A SV = PVAV(0xbd448)
1N/A REFCNT = 1
1N/A FLAGS = ()
1N/A IV = 0
1N/A NV = 0
1N/A ARRAY = 0xb2048
1N/A ALLOC = 0xb2048
1N/A FILL = 0
1N/A MAX = 0
1N/A ARYLEN = 0x0
1N/A FLAGS = (REAL)
1N/A Elt No. 0 0xb5658
1N/A SV = IV(0xbe860)
1N/A REFCNT = 1
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 42
1N/A Elt No. 1 0xb5680
1N/A SV = IV(0xbe818)
1N/A REFCNT = 1
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 24
1N/A
1N/ANote that C<Dump> will not report I<all> the elements in the array,
1N/Aonly several first (depending on how deep it already went into the
1N/Areport tree).
1N/A
1N/A=head2 A reference to a hash
1N/A
1N/AThe following shows the raw form of a reference to a hash.
1N/A
1N/A use Devel::Peek;
1N/A $a = {hello=>42};
1N/A Dump $a;
1N/A
1N/AThe output:
1N/A
1N/A SV = RV(0xf041c)
1N/A REFCNT = 1
1N/A FLAGS = (ROK)
1N/A RV = 0xb2850
1N/A SV = PVHV(0xbd448)
1N/A REFCNT = 1
1N/A FLAGS = ()
1N/A NV = 0
1N/A ARRAY = 0xbd748
1N/A KEYS = 1
1N/A FILL = 1
1N/A MAX = 7
1N/A RITER = -1
1N/A EITER = 0x0
1N/A Elt "hello" => 0xbaaf0
1N/A SV = IV(0xbe860)
1N/A REFCNT = 1
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 42
1N/A
1N/AThis shows C<$a> is a reference pointing to an SV. That SV is a PVHV, a
1N/Ahash. Fields RITER and EITER are used by C<L<each>>.
1N/A
1N/A=head2 Dumping a large array or hash
1N/A
1N/AThe C<Dump()> function, by default, dumps up to 4 elements from a
1N/Atoplevel array or hash. This number can be increased by supplying a
1N/Asecond argument to the function.
1N/A
1N/A use Devel::Peek;
1N/A $a = [10,11,12,13,14];
1N/A Dump $a;
1N/A
1N/ANotice that C<Dump()> prints only elements 10 through 13 in the above code.
1N/AThe following code will print all of the elements.
1N/A
1N/A use Devel::Peek 'Dump';
1N/A $a = [10,11,12,13,14];
1N/A Dump $a, 5;
1N/A
1N/A=head2 A reference to an SV which holds a C pointer
1N/A
1N/AThis is what you really need to know as an XS programmer, of course. When
1N/Aan XSUB returns a pointer to a C structure that pointer is stored in an SV
1N/Aand a reference to that SV is placed on the XSUB stack. So the output from
1N/Aan XSUB which uses something like the T_PTROBJ map might look something like
1N/Athis:
1N/A
1N/A SV = RV(0xf381c)
1N/A REFCNT = 1
1N/A FLAGS = (ROK)
1N/A RV = 0xb8ad8
1N/A SV = PVMG(0xbb3c8)
1N/A REFCNT = 1
1N/A FLAGS = (OBJECT,IOK,pIOK)
1N/A IV = 729160
1N/A NV = 0
1N/A PV = 0
1N/A STASH = 0xc1d10 "CookBookB::Opaque"
1N/A
1N/AThis shows that we have an SV which is an RV. That RV points at another
1N/ASV. In this case that second SV is a PVMG, a blessed scalar. Because it is
1N/Ablessed it has the C<OBJECT> flag set. Note that an SV which holds a C
1N/Apointer also has the C<IOK> flag set. The C<STASH> is set to the package
1N/Aname which this SV was blessed into.
1N/A
1N/AThe output from an XSUB which uses something like the T_PTRREF map, which
1N/Adoesn't bless the object, might look something like this:
1N/A
1N/A SV = RV(0xf381c)
1N/A REFCNT = 1
1N/A FLAGS = (ROK)
1N/A RV = 0xb8ad8
1N/A SV = PVMG(0xbb3c8)
1N/A REFCNT = 1
1N/A FLAGS = (IOK,pIOK)
1N/A IV = 729160
1N/A NV = 0
1N/A PV = 0
1N/A
1N/A=head2 A reference to a subroutine
1N/A
1N/ALooks like this:
1N/A
1N/A SV = RV(0x798ec)
1N/A REFCNT = 1
1N/A FLAGS = (TEMP,ROK)
1N/A RV = 0x1d453c
1N/A SV = PVCV(0x1c768c)
1N/A REFCNT = 2
1N/A FLAGS = ()
1N/A IV = 0
1N/A NV = 0
1N/A COMP_STASH = 0x31068 "main"
1N/A START = 0xb20e0
1N/A ROOT = 0xbece0
1N/A XSUB = 0x0
1N/A XSUBANY = 0
1N/A GVGV::GV = 0x1d44e8 "MY" :: "top_targets"
1N/A FILE = "(eval 5)"
1N/A DEPTH = 0
1N/A PADLIST = 0x1c9338
1N/A
1N/AThis shows that
1N/A
1N/A=over 4
1N/A
1N/A=item *
1N/A
1N/Athe subroutine is not an XSUB (since C<START> and C<ROOT> are
1N/Anon-zero, and C<XSUB> is zero);
1N/A
1N/A=item *
1N/A
1N/Athat it was compiled in the package C<main>;
1N/A
1N/A=item *
1N/A
1N/Aunder the name C<MY::top_targets>;
1N/A
1N/A=item *
1N/A
1N/Ainside a 5th eval in the program;
1N/A
1N/A=item *
1N/A
1N/Ait is not currently executed (see C<DEPTH>);
1N/A
1N/A=item *
1N/A
1N/Ait has no prototype (C<PROTOTYPE> field is missing).
1N/A
1N/A=back
1N/A
1N/A=head1 EXPORTS
1N/A
1N/AC<Dump>, C<mstat>, C<DeadCode>, C<DumpArray>, C<DumpWithOP> and
1N/AC<DumpProg>, C<fill_mstats>, C<mstats_fillhash>, C<mstats2hash> by
1N/Adefault. Additionally available C<SvREFCNT>, C<SvREFCNT_inc> and
1N/AC<SvREFCNT_dec>.
1N/A
1N/A=head1 BUGS
1N/A
1N/AReaders have been known to skip important parts of L<perlguts>, causing much
1N/Afrustration for all.
1N/A
1N/A=head1 AUTHOR
1N/A
1N/AIlya Zakharevich ilya@math.ohio-state.edu
1N/A
1N/ACopyright (c) 1995-98 Ilya Zakharevich. All rights reserved.
1N/AThis program is free software; you can redistribute it and/or
1N/Amodify it under the same terms as Perl itself.
1N/A
1N/AAuthor of this software makes no claim whatsoever about suitability,
1N/Areliability, edability, editability or usability of this product, and
1N/Ashould not be kept liable for any damage resulting from the use of
1N/Ait. If you can use it, you are in luck, if not, I should not be kept
1N/Aresponsible. Keep a handy copy of your backup tape at hand.
1N/A
1N/A=head1 SEE ALSO
1N/A
1N/AL<perlguts>, and L<perlguts>, again.
1N/A
1N/A=cut