| 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__ |