Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
4.0 KiB

  1. # Disassembler.pm
  2. #
  3. # Copyright (c) 1996 Malcolm Beattie
  4. #
  5. # You may distribute under the terms of either the GNU General Public
  6. # License or the Artistic License, as specified in the README file.
  7. package B::Disassembler::BytecodeStream;
  8. use FileHandle;
  9. use Carp;
  10. use B qw(cstring cast_I32);
  11. @ISA = qw(FileHandle);
  12. sub readn {
  13. my ($fh, $len) = @_;
  14. my $data;
  15. read($fh, $data, $len);
  16. croak "reached EOF while reading $len bytes" unless length($data) == $len;
  17. return $data;
  18. }
  19. sub GET_U8 {
  20. my $fh = shift;
  21. my $c = $fh->getc;
  22. croak "reached EOF while reading U8" unless defined($c);
  23. return ord($c);
  24. }
  25. sub GET_U16 {
  26. my $fh = shift;
  27. my $str = $fh->readn(2);
  28. croak "reached EOF while reading U16" unless length($str) == 2;
  29. return unpack("n", $str);
  30. }
  31. sub GET_NV {
  32. my $fh = shift;
  33. my $str = $fh->readn(8);
  34. croak "reached EOF while reading NV" unless length($str) == 8;
  35. return unpack("N", $str);
  36. }
  37. sub GET_U32 {
  38. my $fh = shift;
  39. my $str = $fh->readn(4);
  40. croak "reached EOF while reading U32" unless length($str) == 4;
  41. return unpack("N", $str);
  42. }
  43. sub GET_I32 {
  44. my $fh = shift;
  45. my $str = $fh->readn(4);
  46. croak "reached EOF while reading I32" unless length($str) == 4;
  47. return cast_I32(unpack("N", $str));
  48. }
  49. sub GET_objindex {
  50. my $fh = shift;
  51. my $str = $fh->readn(4);
  52. croak "reached EOF while reading objindex" unless length($str) == 4;
  53. return unpack("N", $str);
  54. }
  55. sub GET_opindex {
  56. my $fh = shift;
  57. my $str = $fh->readn(4);
  58. croak "reached EOF while reading opindex" unless length($str) == 4;
  59. return unpack("N", $str);
  60. }
  61. sub GET_svindex {
  62. my $fh = shift;
  63. my $str = $fh->readn(4);
  64. croak "reached EOF while reading svindex" unless length($str) == 4;
  65. return unpack("N", $str);
  66. }
  67. sub GET_strconst {
  68. my $fh = shift;
  69. my ($str, $c);
  70. while (defined($c = $fh->getc) && $c ne "\0") {
  71. $str .= $c;
  72. }
  73. croak "reached EOF while reading strconst" unless defined($c);
  74. return cstring($str);
  75. }
  76. sub GET_pvcontents {}
  77. sub GET_PV {
  78. my $fh = shift;
  79. my $str;
  80. my $len = $fh->GET_U32;
  81. if ($len) {
  82. read($fh, $str, $len);
  83. croak "reached EOF while reading PV" unless length($str) == $len;
  84. return cstring($str);
  85. } else {
  86. return '""';
  87. }
  88. }
  89. sub GET_comment_t {
  90. my $fh = shift;
  91. my ($str, $c);
  92. while (defined($c = $fh->getc) && $c ne "\n") {
  93. $str .= $c;
  94. }
  95. croak "reached EOF while reading comment" unless defined($c);
  96. return cstring($str);
  97. }
  98. sub GET_double {
  99. my $fh = shift;
  100. my ($str, $c);
  101. while (defined($c = $fh->getc) && $c ne "\0") {
  102. $str .= $c;
  103. }
  104. croak "reached EOF while reading double" unless defined($c);
  105. return $str;
  106. }
  107. sub GET_none {}
  108. sub GET_op_tr_array {
  109. my $fh = shift;
  110. my @ary = unpack("n256", $fh->readn(256 * 2));
  111. return join(",", @ary);
  112. }
  113. sub GET_IV64 {
  114. my $fh = shift;
  115. my ($hi, $lo) = unpack("NN", $fh->readn(8));
  116. return sprintf("0x%4x%04x", $hi, $lo); # cheat
  117. }
  118. package B::Disassembler;
  119. use Exporter;
  120. @ISA = qw(Exporter);
  121. @EXPORT_OK = qw(disassemble_fh);
  122. use Carp;
  123. use strict;
  124. use B::Asmdata qw(%insn_data @insn_name);
  125. sub disassemble_fh {
  126. my ($fh, $out) = @_;
  127. my ($c, $getmeth, $insn, $arg);
  128. bless $fh, "B::Disassembler::BytecodeStream";
  129. while (defined($c = $fh->getc)) {
  130. $c = ord($c);
  131. $insn = $insn_name[$c];
  132. if (!defined($insn) || $insn eq "unused") {
  133. my $pos = $fh->tell - 1;
  134. die "Illegal instruction code $c at stream offset $pos\n";
  135. }
  136. $getmeth = $insn_data{$insn}->[2];
  137. $arg = $fh->$getmeth();
  138. if (defined($arg)) {
  139. &$out($insn, $arg);
  140. } else {
  141. &$out($insn);
  142. }
  143. }
  144. }
  145. 1;
  146. __END__
  147. =head1 NAME
  148. B::Disassembler - Disassemble Perl bytecode
  149. =head1 SYNOPSIS
  150. use Disassembler;
  151. =head1 DESCRIPTION
  152. See F<ext/B/B/Disassembler.pm>.
  153. =head1 AUTHOR
  154. Malcolm Beattie, C<[email protected]>
  155. =cut