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