1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
use code_attribute::types::Instruction;
use nom::{be_i16, be_i32, be_i8, be_u16, be_u32, be_u8, IResult, Offset};
fn offset<'a>(remaining: &'a [u8], input: &[u8]) -> IResult<&'a [u8], usize> {
Ok((remaining, input.offset(remaining)))
}
fn align(input: &[u8], address: usize) -> IResult<&[u8], &[u8]> {
take!(input, (4 - address % 4) % 4)
}
fn lookupswitch_parser(input: &[u8]) -> IResult<&[u8], Instruction> {
do_parse!(
input,
default: be_i32
>> npairs: be_u32
>> pairs:
count!(
do_parse!(lookup: be_i32 >> offset: be_i32 >> (lookup, offset)),
npairs as usize
)
>> (Instruction::Lookupswitch {
default: default,
pairs: pairs
})
)
}
fn tableswitch_parser(input: &[u8]) -> IResult<&[u8], Instruction> {
do_parse!(
input,
default: be_i32
>> low: be_i32
>> high: be_i32
>> offsets: count!(be_i32, (high - low + 1) as usize)
>> (Instruction::Tableswitch {
default: default,
low: low,
high: high,
offsets: offsets
})
)
}
pub fn code_parser(input: &[u8]) -> IResult<&[u8], Vec<(usize, Instruction)>> {
many0!(
input,
complete!(do_parse!(
address: apply!(offset, input)
>> instruction: apply!(instruction_parser, address)
>> (address, instruction)
))
)
}
pub fn instruction_parser(input: &[u8], address: usize) -> IResult<&[u8], Instruction> {
switch!(input, be_u8,
0x32 => value!(Instruction::Aaload) |
0x53 => value!(Instruction::Aastore) |
0x01 => value!(Instruction::Aconstnull) |
0x19 => map!(be_u8, Instruction::Aload) |
0x2a => value!(Instruction::Aload0) |
0x2b => value!(Instruction::Aload1) |
0x2c => value!(Instruction::Aload2) |
0x2d => value!(Instruction::Aload3) |
0xbd => map!(be_u16, Instruction::Anewarray) |
0xb0 => value!(Instruction::Areturn) |
0xbe => value!(Instruction::Arraylength) |
0x3a => map!(be_u8, Instruction::Astore) |
0x4b => value!(Instruction::Astore0) |
0x4c => value!(Instruction::Astore1) |
0x4d => value!(Instruction::Astore2) |
0x4e => value!(Instruction::Astore3) |
0xbf => value!(Instruction::Athrow) |
0x33 => value!(Instruction::Baload) |
0x54 => value!(Instruction::Bastore) |
0x10 => map!(be_i8, Instruction::Bipush) |
0x34 => value!(Instruction::Caload) |
0x55 => value!(Instruction::Castore) |
0xc0 => map!(be_u16, Instruction::Checkcast) |
0x90 => value!(Instruction::D2f) |
0x8e => value!(Instruction::D2i) |
0x8f => value!(Instruction::D2l) |
0x63 => value!(Instruction::Dadd) |
0x31 => value!(Instruction::Daload) |
0x52 => value!(Instruction::Dastore) |
0x98 => value!(Instruction::Dcmpg) |
0x97 => value!(Instruction::Dcmpl) |
0x0e => value!(Instruction::Dconst0) |
0x0f => value!(Instruction::Dconst1) |
0x6f => value!(Instruction::Ddiv) |
0x18 => map!(be_u8, Instruction::Dload) |
0x26 => value!(Instruction::Dload0) |
0x27 => value!(Instruction::Dload1) |
0x28 => value!(Instruction::Dload2) |
0x29 => value!(Instruction::Dload3) |
0x6b => value!(Instruction::Dmul) |
0x77 => value!(Instruction::Dneg) |
0x73 => value!(Instruction::Drem) |
0xaf => value!(Instruction::Dreturn) |
0x39 => map!(be_u8, Instruction::Dstore) |
0x47 => value!(Instruction::Dstore0) |
0x48 => value!(Instruction::Dstore1) |
0x49 => value!(Instruction::Dstore2) |
0x4a => value!(Instruction::Dstore3) |
0x67 => value!(Instruction::Dsub) |
0x59 => value!(Instruction::Dup) |
0x5a => value!(Instruction::Dupx1) |
0x5b => value!(Instruction::Dupx2) |
0x5c => value!(Instruction::Dup2) |
0x5d => value!(Instruction::Dup2x1) |
0x5e => value!(Instruction::Dup2x2) |
0x8d => value!(Instruction::F2d) |
0x8b => value!(Instruction::F2i) |
0x8c => value!(Instruction::F2l) |
0x62 => value!(Instruction::Fadd) |
0x30 => value!(Instruction::Faload) |
0x51 => value!(Instruction::Fastore) |
0x96 => value!(Instruction::Fcmpg) |
0x95 => value!(Instruction::Fcmpl) |
0x0b => value!(Instruction::Fconst0) |
0x0c => value!(Instruction::Fconst1) |
0x0d => value!(Instruction::Fconst2) |
0x6e => value!(Instruction::Fdiv) |
0x17 => map!(be_u8, Instruction::Fload) |
0x22 => value!(Instruction::Fload0) |
0x23 => value!(Instruction::Fload1) |
0x24 => value!(Instruction::Fload2) |
0x25 => value!(Instruction::Fload3) |
0x6a => value!(Instruction::Fmul) |
0x76 => value!(Instruction::Fneg) |
0x72 => value!(Instruction::Frem) |
0xae => value!(Instruction::Freturn) |
0x38 => map!(be_u8, Instruction::Fstore) |
0x43 => value!(Instruction::Fstore0) |
0x44 => value!(Instruction::Fstore1) |
0x45 => value!(Instruction::Fstore2) |
0x46 => value!(Instruction::Fstore3) |
0x66 => value!(Instruction::Fsub) |
0xb4 => map!(be_u16, Instruction::Getfield) |
0xb2 => map!(be_u16, Instruction::Getstatic) |
0xa7 => map!(be_i16, Instruction::Goto) |
0xc8 => map!(be_i32, Instruction::GotoW) |
0x91 => value!(Instruction::I2b) |
0x92 => value!(Instruction::I2c) |
0x87 => value!(Instruction::I2d) |
0x86 => value!(Instruction::I2f) |
0x85 => value!(Instruction::I2l) |
0x93 => value!(Instruction::I2s) |
0x60 => value!(Instruction::Iadd) |
0x2e => value!(Instruction::Iaload) |
0x7e => value!(Instruction::Iand) |
0x4f => value!(Instruction::Iastore) |
0x02 => value!(Instruction::Iconstm1) |
0x03 => value!(Instruction::Iconst0) |
0x04 => value!(Instruction::Iconst1) |
0x05 => value!(Instruction::Iconst2) |
0x06 => value!(Instruction::Iconst3) |
0x07 => value!(Instruction::Iconst4) |
0x08 => value!(Instruction::Iconst5) |
0x6c => value!(Instruction::Idiv) |
0xa5 => map!(be_i16, Instruction::IfAcmpeq) |
0xa6 => map!(be_i16, Instruction::IfAcmpne) |
0x9f => map!(be_i16, Instruction::IfIcmpeq) |
0xa0 => map!(be_i16, Instruction::IfIcmpne) |
0xa1 => map!(be_i16, Instruction::IfIcmplt) |
0xa2 => map!(be_i16, Instruction::IfIcmpge) |
0xa3 => map!(be_i16, Instruction::IfIcmpgt) |
0xa4 => map!(be_i16, Instruction::IfIcmple) |
0x99 => map!(be_i16, Instruction::Ifeq) |
0x9a => map!(be_i16, Instruction::Ifne) |
0x9b => map!(be_i16, Instruction::Iflt) |
0x9c => map!(be_i16, Instruction::Ifge) |
0x9d => map!(be_i16, Instruction::Ifgt) |
0x9e => map!(be_i16, Instruction::Ifle) |
0xc7 => map!(be_i16, Instruction::Ifnonnull) |
0xc6 => map!(be_i16, Instruction::Ifnull) |
0x84 => do_parse!(index: be_u8 >> value: be_i8 >> (Instruction::Iinc{index: index, value: value})) |
0x15 => map!(be_u8, Instruction::Iload) |
0x1a => value!(Instruction::Iload0) |
0x1b => value!(Instruction::Iload1) |
0x1c => value!(Instruction::Iload2) |
0x1d => value!(Instruction::Iload3) |
0x68 => value!(Instruction::Imul) |
0x74 => value!(Instruction::Ineg) |
0xc1 => map!(be_u16, Instruction::Instanceof) |
0xba => do_parse!(index: be_u16 >> tag!(&[0, 0]) >> (Instruction::Invokedynamic(index))) |
0xb9 => do_parse!(index: be_u16 >> count: be_u8 >> tag!(&[0]) >> (Instruction::Invokeinterface{index: index, count: count})) |
0xb7 => map!(be_u16, Instruction::Invokespecial) |
0xb8 => map!(be_u16, Instruction::Invokestatic) |
0xb6 => map!(be_u16, Instruction::Invokevirtual) |
0x80 => value!(Instruction::Ior) |
0x70 => value!(Instruction::Irem) |
0xac => value!(Instruction::Ireturn) |
0x78 => value!(Instruction::Ishl) |
0x7a => value!(Instruction::Ishr) |
0x36 => map!(be_u8, Instruction::Istore) |
0x3b => value!(Instruction::Istore0) |
0x3c => value!(Instruction::Istore1) |
0x3d => value!(Instruction::Istore2) |
0x3e => value!(Instruction::Istore3) |
0x64 => value!(Instruction::Isub) |
0x7c => value!(Instruction::Iushr) |
0x82 => value!(Instruction::Ixor) |
0xa8 => map!(be_i16, Instruction::Jsr) |
0xc9 => map!(be_i32, Instruction::JsrW) |
0x8a => value!(Instruction::L2d) |
0x89 => value!(Instruction::L2f) |
0x88 => value!(Instruction::L2i) |
0x61 => value!(Instruction::Ladd) |
0x2f => value!(Instruction::Laload) |
0x7f => value!(Instruction::Land) |
0x50 => value!(Instruction::Lastore) |
0x94 => value!(Instruction::Lcmp) |
0x09 => value!(Instruction::Lconst0) |
0x0a => value!(Instruction::Lconst1) |
0x12 => map!(be_u8, Instruction::Ldc) |
0x13 => map!(be_u16, Instruction::LdcW) |
0x14 => map!(be_u16, Instruction::Ldc2W) |
0x6d => value!(Instruction::Ldiv) |
0x16 => map!(be_u8, Instruction::Lload) |
0x1e => value!(Instruction::Lload0) |
0x1f => value!(Instruction::Lload1) |
0x20 => value!(Instruction::Lload2) |
0x21 => value!(Instruction::Lload3) |
0x69 => value!(Instruction::Lmul) |
0x75 => value!(Instruction::Lneg) |
0xab => preceded!(apply!(align, address + 1), lookupswitch_parser) |
0x81 => value!(Instruction::Lor) |
0x71 => value!(Instruction::Lrem) |
0xad => value!(Instruction::Lreturn) |
0x79 => value!(Instruction::Lshl) |
0x7b => value!(Instruction::Lshr) |
0x37 => map!(be_u8, Instruction::Lstore) |
0x3f => value!(Instruction::Lstore0) |
0x40 => value!(Instruction::Lstore1) |
0x41 => value!(Instruction::Lstore2) |
0x42 => value!(Instruction::Lstore3) |
0x65 => value!(Instruction::Lsub) |
0x7d => value!(Instruction::Lushr) |
0x83 => value!(Instruction::Lxor) |
0xc2 => value!(Instruction::Monitorenter) |
0xc3 => value!(Instruction::Monitorexit) |
0xc5 => do_parse!(index: be_u16 >> dimensions: be_u8 >> (Instruction::Multianewarray{index: index, dimensions: dimensions})) |
0xbb => map!(be_u16, Instruction::New) |
0xbc => map!(be_u8, Instruction::Newarray) |
0x00 => value!(Instruction::Nop) |
0x57 => value!(Instruction::Pop) |
0x58 => value!(Instruction::Pop2) |
0xb5 => map!(be_u16, Instruction::Putfield) |
0xb3 => map!(be_u16, Instruction::Putstatic) |
0xa9 => map!(be_u8, Instruction::Ret) |
0xb1 => value!(Instruction::Return) |
0x35 => value!(Instruction::Saload) |
0x56 => value!(Instruction::Sastore) |
0x11 => map!(be_i16, Instruction::Sipush) |
0x5f => value!(Instruction::Swap) |
0xaa => preceded!(apply!(align, address + 1), tableswitch_parser) |
0xc4 => switch!(be_u8,
0x19 => map!(be_u16, Instruction::AloadWide) |
0x3a => map!(be_u16, Instruction::AstoreWide) |
0x18 => map!(be_u16, Instruction::DloadWide) |
0x39 => map!(be_u16, Instruction::DstoreWide) |
0x17 => map!(be_u16, Instruction::FloadWide) |
0x38 => map!(be_u16, Instruction::FstoreWide) |
0x15 => map!(be_u16, Instruction::IloadWide) |
0x36 => map!(be_u16, Instruction::IstoreWide) |
0x16 => map!(be_u16, Instruction::LloadWide) |
0x37 => map!(be_u16, Instruction::LstoreWide) |
0xa9 => map!(be_u16, Instruction::RetWide) |
0x84 => do_parse!(index: be_u16 >> value: be_i16 >> (Instruction::IincWide{index: index, value: value}))
)
)
}