Skip to content

Commit 83700e0

Browse files
authored
Merge pull request #22 from george-hopkins/code-parser
Implement code parser
2 parents 8a4ac90 + 9a18d6a commit 83700e0

7 files changed

Lines changed: 620 additions & 0 deletions

File tree

763 Bytes
Binary file not shown.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package uk.co.palmr.classfileparser;
2+
3+
public class Instructions {
4+
public static int[] test(int x) {
5+
int a = 0;
6+
switch (x) {
7+
case 1: a = 10; break;
8+
case 2: a = 20; break;
9+
case 3: a = 30; break;
10+
}
11+
int b = 0;
12+
switch (x) {
13+
case 100: b = 2; break;
14+
case 1000: b = 3; break;
15+
case 10000: b = 4; break;
16+
}
17+
System.out.printf("%d + %d = %d\n", a, b, a + b);
18+
return new int[]{ a, b, a + b };
19+
}
20+
}

src/code_attribute/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
mod parser;
2+
mod types;
3+
4+
pub use self::types::*;
5+
6+
pub use self::parser::code_parser;
7+
pub use self::parser::instruction_parser;

src/code_attribute/parser.rs

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

0 commit comments

Comments
 (0)