line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package PJVM::Bytecode::Reader; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
41165
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
38
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
420
|
use List::MoreUtils qw(any); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
sub _index_byte { ${$_[1]} += 1; return (shift @{$_[0]}); } |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
sub _index_short { ${$_[1]} += 2; my ($i1, $i2) = splice @{$_[0]}, 0, 2; return ($i1 << 8 | $i2); } |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub _byte { ${$_[1]} += 1; return (shift @{$_[0]}); } |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub _short { ${$_[1]} += 2; my ($i1, $i2) = splice @{$_[0]}, 0, 2; return ($i1 << 8 | $i2); } |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub _offset_short { ${$_[1]} += 2; my ($o1, $o2) = splice @{$_[0]}, 0, 2; return ($o1 << 8 | $o2); } |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub _offset_long { |
19
|
|
|
|
|
|
|
${$_[1]} += 4; |
20
|
|
|
|
|
|
|
my ($o1, $o2, $o3, $o4) = splice @{$_[0]}, 0, 4; |
21
|
|
|
|
|
|
|
return ($o1 << 24 | $o2 << 16 | $o3 << 8 | $o4); |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub _index_byte_const { |
25
|
|
|
|
|
|
|
${$_[1]} += 2; |
26
|
|
|
|
|
|
|
return splice @{$_[0]}, 0, 2; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub _index_short_count_0 { |
30
|
|
|
|
|
|
|
${$_[1]} += 4; |
31
|
|
|
|
|
|
|
my ($i1, $i2, $count, undef) = splice @{$_[0]}, 0, 4; |
32
|
|
|
|
|
|
|
return ($i1 << 8 | $i2, $count); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub _index_short_count { |
36
|
|
|
|
|
|
|
${$_[1]} += 3; |
37
|
|
|
|
|
|
|
my ($i1, $i2, $count) = splice @{$_[0]}, 0, 3; |
38
|
|
|
|
|
|
|
return ($i1 << 8 | $i2, $count); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my %Op_transformation = ( |
43
|
|
|
|
|
|
|
0x19 => \&_index_byte, # aload |
44
|
|
|
|
|
|
|
0xbd => \&_index_short, # anewarray |
45
|
|
|
|
|
|
|
0x3a => \&_index_byte, # astore |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
0x10 => \&_byte, # bipush |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
0xc0 => \&_index_short, # checkcast |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
0x18 => \&_index_byte, # dload |
52
|
|
|
|
|
|
|
0x39 => \&_index_byte, # dstore |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
0x17 => \&_index_byte, # fload |
55
|
|
|
|
|
|
|
0x38 => \&_index_byte, # fstore |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
0xb4 => \&_index_short, # getfield |
58
|
|
|
|
|
|
|
0xb2 => \&_index_short, # getstatic |
59
|
|
|
|
|
|
|
0xa7 => \&_offset_short, # goto |
60
|
|
|
|
|
|
|
0xc8 => \&_offset_long, # goto_w |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
0xa5 => \&_offset_short, # if_acmpeq |
63
|
|
|
|
|
|
|
0xa6 => \&_offset_short, # if_acmpne |
64
|
|
|
|
|
|
|
0x9f => \&_offset_short, # if_icmpeq |
65
|
|
|
|
|
|
|
0xa0 => \&_offset_short, # if_icmpne |
66
|
|
|
|
|
|
|
0xa1 => \&_offset_short, # if_icmplt |
67
|
|
|
|
|
|
|
0xa2 => \&_offset_short, # if_icmpge |
68
|
|
|
|
|
|
|
0xa3 => \&_offset_short, # if_icmpgt |
69
|
|
|
|
|
|
|
0xa4 => \&_offset_short, # if_icmple |
70
|
|
|
|
|
|
|
0x99 => \&_offset_short, # ifeq |
71
|
|
|
|
|
|
|
0x9a => \&_offset_short, # ifne |
72
|
|
|
|
|
|
|
0x9b => \&_offset_short, # iflt |
73
|
|
|
|
|
|
|
0x9c => \&_offset_short, # ifge |
74
|
|
|
|
|
|
|
0x9d => \&_offset_short, # ifgt |
75
|
|
|
|
|
|
|
0x9e => \&_offset_short, # ifle |
76
|
|
|
|
|
|
|
0xc7 => \&_offset_short, # ifnotnull |
77
|
|
|
|
|
|
|
0xc6 => \&_offset_short, # ifnull |
78
|
|
|
|
|
|
|
0x84 => \&_index_byte_const, # iinc |
79
|
|
|
|
|
|
|
0x15 => \&_index_byte, # iload |
80
|
|
|
|
|
|
|
0xc1 => \&_index_short, # instanceof |
81
|
|
|
|
|
|
|
0xb9 => \&_index_short_count_0, # invokeinterface |
82
|
|
|
|
|
|
|
0xb7 => \&_index_short, # invokespecial |
83
|
|
|
|
|
|
|
0xb8 => \&_index_short, # invokestatic |
84
|
|
|
|
|
|
|
0xb6 => \&_index_short, # invokevirtual |
85
|
|
|
|
|
|
|
0x36 => \&_index_byte, # istore |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
0xa8 => \&_offset_short, # jsr |
88
|
|
|
|
|
|
|
0xc9 => \&_offset_long, # jsr_w |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
0x12 => \&_index_byte, # ldc |
91
|
|
|
|
|
|
|
0x13 => \&_index_short, # ldc_w |
92
|
|
|
|
|
|
|
0x14 => \&_index_short, # ldc2_w |
93
|
|
|
|
|
|
|
0x16 => \&_index_short, # lload |
94
|
|
|
|
|
|
|
0xab => sub { # lookupswitch |
95
|
|
|
|
|
|
|
my ($ops, $ix) = @_; |
96
|
|
|
|
|
|
|
my $pad = 3 - ($$ix - 1) % 4; |
97
|
|
|
|
|
|
|
if ($pad) { |
98
|
|
|
|
|
|
|
splice @$ops, 0, $pad; |
99
|
|
|
|
|
|
|
$$ix += $pad; |
100
|
|
|
|
|
|
|
}; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# default offset |
103
|
|
|
|
|
|
|
my ($d1, $d2, $d3, $d4) = splice @$ops, 0, 4; |
104
|
|
|
|
|
|
|
$$ix += 4; |
105
|
|
|
|
|
|
|
my $default = ($d1 << 24 | $d2 << 16 | $d3 << 8 | $d4); |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# number of case : |
108
|
|
|
|
|
|
|
my ($n1, $n2, $n3, $n4) = splice @$ops, 0, 4; |
109
|
|
|
|
|
|
|
$$ix += 4; |
110
|
|
|
|
|
|
|
my $case_no = ($d1 << 24 | $d2 << 16 | $d3 << 8 | $d4); |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
my @pairs; |
113
|
|
|
|
|
|
|
if ($case_no) { |
114
|
|
|
|
|
|
|
my ($i1, $i2, $i3, $i4, $o1, $o2, $o3, $o4) = splice @$ops, 0, 8; |
115
|
|
|
|
|
|
|
$$ix += 8; |
116
|
|
|
|
|
|
|
push @pairs, ($i1 << 24 | $i2 << 16 | $i3 << 8 | $i4), ($o1 << 24 | $o2 << 16 | $o3 << 8 | $o4); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
return ($default, @pairs); |
120
|
|
|
|
|
|
|
}, |
121
|
|
|
|
|
|
|
0x37 => \&_index_byte, # lstore |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
0xc5 => \&_index_short_count, # multianewarray |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
0xbb => \&_index_short, # new |
126
|
|
|
|
|
|
|
0xbc => \&_byte, # newarray |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
0xb5 => \&_index_short, # putfield |
129
|
|
|
|
|
|
|
0xb3 => \&_index_short, # putstatic |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
0xa9 => \&_index_byte, # ret |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
0x11 => \&_short, # sipush |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
0xaa => sub { # tableswitch |
136
|
|
|
|
|
|
|
my ($ops, $ix) = @_; |
137
|
|
|
|
|
|
|
my $pad = 3 - ($$ix - 1) % 4; |
138
|
|
|
|
|
|
|
if ($pad) { |
139
|
|
|
|
|
|
|
splice @$ops, 0, $pad; |
140
|
|
|
|
|
|
|
$$ix += $pad; |
141
|
|
|
|
|
|
|
}; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# default offset |
144
|
|
|
|
|
|
|
my ($d1, $d2, $d3, $d4) = splice @$ops, 0, 4; |
145
|
|
|
|
|
|
|
$$ix += 4; |
146
|
|
|
|
|
|
|
my $default = ($d1 << 24 | $d2 << 16 | $d3 << 8 | $d4); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# low : |
149
|
|
|
|
|
|
|
my ($l1, $l2, $l3, $l4) = splice @$ops, 0, 4; |
150
|
|
|
|
|
|
|
$$ix += 4; |
151
|
|
|
|
|
|
|
my $low = ($l1 << 24 | $l2 << 16 | $l3 << 8 | $l4); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
my ($h1, $h2, $h3, $h4) = splice @$ops, 0, 4; |
154
|
|
|
|
|
|
|
$$ix += 4; |
155
|
|
|
|
|
|
|
my $high = ($h1 << 24 | $h2 << 16 | $h3 << 8 | $h4); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
my $jump_offsets = $high - $low + 1; |
158
|
|
|
|
|
|
|
my @jump_offsets; |
159
|
|
|
|
|
|
|
if ($jump_offsets) { |
160
|
|
|
|
|
|
|
my ($o1, $o2, $o3, $o4) = splice @$ops, 0, 4; |
161
|
|
|
|
|
|
|
$$ix += 4; |
162
|
|
|
|
|
|
|
push @jump_offsets, ($o1 << 24 | $o2 << 16 | $o3 << 8 | $o4); |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
return ($default, $low, $high, @jump_offsets); |
166
|
|
|
|
|
|
|
}, |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
0xc4 => sub { # wide |
169
|
|
|
|
|
|
|
my ($ops, $ix) = @_; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my $op = shift @$ops; |
172
|
|
|
|
|
|
|
$$ix++; |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
if ($op == 0x84) { |
175
|
|
|
|
|
|
|
my ($i1, $i2, $c1, $c2) = splice @$ops, 0, 4; |
176
|
|
|
|
|
|
|
$$ix += 4; |
177
|
|
|
|
|
|
|
return ($op, $i1 << 8 | $i2, $c1 << 8 | $c2); |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
elsif (any { $_ == $op } (0x15, 0x36, 0x17, 0x38, 0x19, 0x3a, 0x16, 0x37, 0x18, 0x39, 0xa9)) { |
180
|
|
|
|
|
|
|
my ($i1, $i2) = splice @$ops, 0, 2; |
181
|
|
|
|
|
|
|
$$ix += 2; |
182
|
|
|
|
|
|
|
return ($op, $i1 << 8 | $i2); |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
else { |
185
|
|
|
|
|
|
|
die "Bytecode stream error" |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub read { |
191
|
|
|
|
|
|
|
my ($pkg, $bytecode) = @_; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
my @bytecode = unpack("C*", $bytecode); |
194
|
|
|
|
|
|
|
my @ops; |
195
|
|
|
|
|
|
|
my $ix = 0; |
196
|
|
|
|
|
|
|
while (@bytecode) { |
197
|
|
|
|
|
|
|
my $opcode = shift @bytecode; |
198
|
|
|
|
|
|
|
my $pc = $ix++; |
199
|
|
|
|
|
|
|
my $transformer = $Op_transformation{$opcode}; |
200
|
|
|
|
|
|
|
my @args = defined $transformer ? $transformer->(\@bytecode, \$ix) : (); |
201
|
|
|
|
|
|
|
push @ops, [$opcode, @args], (undef) x ($ix - 1 - $pc); |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
return \@ops; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
1; |
208
|
|
|
|
|
|
|
__END__ |