X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FB%2FB%2FDisassembler.pm;h=e1993aa9537b02b7561bf5d37f3387a731429628;hb=461824dcfbc00b3c4e20590f06d6c9881e4a416b;hp=f26441d2d0626dc580e43e735e38975c0722d85f;hpb=7f20e9dd0ffd291ea63da3dcb7fbfa7029e93f0d;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/B/B/Disassembler.pm b/ext/B/B/Disassembler.pm index f26441d..e1993aa 100644 --- a/ext/B/B/Disassembler.pm +++ b/ext/B/B/Disassembler.pm @@ -4,9 +4,14 @@ # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the README file. + +$B::Disassembler::VERSION = '1.05'; + package B::Disassembler::BytecodeStream; + use FileHandle; use Carp; +use Config qw(%Config); use B qw(cstring cast_I32); @ISA = qw(FileHandle); sub readn { @@ -28,33 +33,65 @@ sub GET_U16 { my $fh = shift; my $str = $fh->readn(2); croak "reached EOF while reading U16" unless length($str) == 2; - return unpack("n", $str); + return unpack("S", $str); +} + +sub GET_NV { + my $fh = shift; + my ($str, $c); + while (defined($c = $fh->getc) && $c ne "\0") { + $str .= $c; + } + croak "reached EOF while reading double" unless defined($c); + return $str; } sub GET_U32 { my $fh = shift; my $str = $fh->readn(4); croak "reached EOF while reading U32" unless length($str) == 4; - return unpack("N", $str); + return unpack("L", $str); } sub GET_I32 { my $fh = shift; my $str = $fh->readn(4); croak "reached EOF while reading I32" unless length($str) == 4; - return cast_I32(unpack("N", $str)); + return unpack("l", $str); } sub GET_objindex { my $fh = shift; my $str = $fh->readn(4); croak "reached EOF while reading objindex" unless length($str) == 4; - return unpack("N", $str); + return unpack("L", $str); +} + +sub GET_opindex { + my $fh = shift; + my $str = $fh->readn(4); + croak "reached EOF while reading opindex" unless length($str) == 4; + return unpack("L", $str); +} + +sub GET_svindex { + my $fh = shift; + my $str = $fh->readn(4); + croak "reached EOF while reading svindex" unless length($str) == 4; + return unpack("L", $str); +} + +sub GET_pvindex { + my $fh = shift; + my $str = $fh->readn(4); + croak "reached EOF while reading pvindex" unless length($str) == 4; + return unpack("L", $str); } sub GET_strconst { my $fh = shift; my ($str, $c); + $str = ''; while (defined($c = $fh->getc) && $c ne "\0") { $str .= $c; } @@ -77,7 +114,7 @@ sub GET_PV { } } -sub GET_comment { +sub GET_comment_t { my $fh = shift; my ($str, $c); while (defined($c = $fh->getc) && $c ne "\n") { @@ -101,29 +138,61 @@ sub GET_none {} sub GET_op_tr_array { my $fh = shift; - my @ary = unpack("n256", $fh->readn(256 * 2)); - return join(",", @ary); + my $len = unpack "S", $fh->readn(2); + my @ary = unpack "S*", $fh->readn($len*2); + return join(",", $len, @ary); } sub GET_IV64 { my $fh = shift; - my ($hi, $lo) = unpack("NN", $fh->readn(8)); - return sprintf("0x%4x%04x", $hi, $lo); # cheat + my $str = $fh->readn(8); + croak "reached EOF while reading I32" unless length($str) == 8; + return sprintf "0x%09llx", unpack("q", $str); +} + +sub GET_IV { + $Config{ivsize} == 4 ? &GET_I32 : &GET_IV64; +} + +sub GET_PADOFFSET { + $Config{ptrsize} == 8 ? &GET_IV64 : &GET_U32; } +sub GET_long { + $Config{longsize} == 8 ? &GET_IV64 : &GET_U32; +} + + package B::Disassembler; use Exporter; @ISA = qw(Exporter); -@EXPORT_OK = qw(disassemble_fh); +@EXPORT_OK = qw(disassemble_fh get_header); use Carp; use strict; use B::Asmdata qw(%insn_data @insn_name); +our( $magic, $archname, $blversion, $ivsize, $ptrsize ); + +sub dis_header($){ + my( $fh ) = @_; + $magic = $fh->GET_U32(); + warn( "bad magic" ) if $magic != 0x43424c50; + $archname = $fh->GET_strconst(); + $blversion = $fh->GET_strconst(); + $ivsize = $fh->GET_U32(); + $ptrsize = $fh->GET_U32(); +} + +sub get_header(){ + return( $magic, $archname, $blversion, $ivsize, $ptrsize); +} + sub disassemble_fh { my ($fh, $out) = @_; my ($c, $getmeth, $insn, $arg); bless $fh, "B::Disassembler::BytecodeStream"; + dis_header( $fh ); while (defined($c = $fh->getc)) { $c = ord($c); $insn = $insn_name[$c];