Skip to content

Commit 7f5ddc4

Browse files
committed
Update class file printer
1 parent ac26c20 commit 7f5ddc4

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed

src/bytecode/printer.rs

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ impl ClassfilePrinter {
2222
.map(|line| lines.push(line))
2323
.collect();
2424

25+
let _: Vec<()> = ClassfilePrinter::render_methods(&classfile).iter()
26+
.map(|method| {
27+
format!("{}", method)
28+
})
29+
.map(|line| lines.push(line))
30+
.collect();
31+
2532
lines
2633
}
2734

@@ -90,6 +97,13 @@ impl ClassfilePrinter {
9097
}).unwrap_or(String::from("<Not found>"))
9198
}
9299

100+
pub fn resolve_method_reference(method_reference: &ConstantPoolIndex, cp: &ConstantPool) -> String {
101+
cp.resolve_index(method_reference).map(|constant| match constant {
102+
&Constant::MethodRef { class_index: ref ci, name_and_type_index: ref ni } => format!("{}:{}", ClassfilePrinter::resolve_class(ci, cp), ClassfilePrinter::resolve_name_and_type(ni, cp)),
103+
_ => String::from("Not a method reference>")
104+
}).unwrap_or(String::from("<Not found>"))
105+
}
106+
93107
pub fn resolve_reference_kind(kind: &ReferenceKind) -> String {
94108
String::from(match kind {
95109
&ReferenceKind::GetField => "GetField",
@@ -104,4 +118,279 @@ impl ClassfilePrinter {
104118
_ => "Unknown"
105119
})
106120
}
121+
122+
pub fn render_methods(classfile: &Classfile) -> Vec<String> {
123+
classfile.methods.iter().flat_map(|method| ClassfilePrinter::render_method(method, &classfile.constant_pool)).collect()
124+
}
125+
126+
pub fn render_method(method: &Method, cp: &ConstantPool) -> Vec<String> {
127+
let mut lines = vec![];
128+
129+
lines.push(format!(" {}()", ClassfilePrinter::resolve_utf8(&method.name_index, cp)));
130+
lines.push(format!(" Descriptor: {}", ClassfilePrinter::resolve_utf8(&method.descriptor_index, cp)));
131+
// TODO display access flags
132+
lines.push(String::from(" Code: "));
133+
134+
let _: Vec<()> = method.attributes.iter()/*.filter(|attr| match attr {
135+
&&Attribute::Code { max_stack: _, max_locals: _, code: _, exception_table: _, attributes: _ } => true,
136+
_ => false
137+
})*/.flat_map(|code_attr| ClassfilePrinter::render_attribute(code_attr, cp)).map(|line| lines.push(line)).collect();
138+
139+
lines.push(String::from(""));
140+
141+
lines
142+
}
143+
144+
pub fn render_attribute(code: &Attribute, cp: &ConstantPool) -> Vec<String> {
145+
let mut lines = vec![];
146+
147+
match code {
148+
&Attribute::Code { max_stack: ref ms, max_locals: ref ml, code: ref c, exception_table: ref et, attributes: ref at } => {
149+
let mut instr_pointer: usize = 0;
150+
151+
lines.push(format!(" stack={} locals={} args={}", ms, ml, "???"));
152+
let _: Vec<()> = c.iter().map(|instr| (instr.len(), match instr {
153+
&Instruction::AALOAD => format!("aaload"),
154+
&Instruction::AASTORE => format!("aastore"),
155+
&Instruction::ACONST_NULL => format!("aconst_null"),
156+
&Instruction::ALOAD(value) => format!("aload {}", value),
157+
&Instruction::ALOAD_0 => format!("aload_0"),
158+
&Instruction::ALOAD_1 => format!("aload_1"),
159+
&Instruction::ALOAD_2 => format!("aload_2"),
160+
&Instruction::ALOAD_3 => format!("aload_3"),
161+
&Instruction::ATHROW => format!("athrow"),
162+
&Instruction::BALOAD => format!("baload"),
163+
&Instruction::BASTORE => format!("bastore"),
164+
&Instruction::BIPUSH(value) => format!("bipush {}", value),
165+
&Instruction::CALOAD => format!("caload"),
166+
&Instruction::CASTORE => format!("castore"),
167+
&Instruction::CHECKCAST(value) => format!("checkcast {}", value),
168+
&Instruction::D2F => format!("d2f"),
169+
&Instruction::D2I => format!("d2i"),
170+
&Instruction::D2L => format!("d2l"),
171+
&Instruction::DADD => format!("dadd"),
172+
&Instruction::DALOAD => format!("daload"),
173+
&Instruction::DASTORE => format!("dastore"),
174+
&Instruction::DCMPL => format!("dcmpl"),
175+
&Instruction::DCMPG => format!("dcmpg"),
176+
&Instruction::DCONST_0 => format!("dconst_0"),
177+
&Instruction::DCONST_1 => format!("dconst_1"),
178+
&Instruction::DDIV => format!("ddiv"),
179+
&Instruction::DLOAD(value) => format!("dload {}", value),
180+
&Instruction::DLOAD_0 => format!("dload_0"),
181+
&Instruction::DLOAD_1 => format!("dload_1"),
182+
&Instruction::DLOAD_2 => format!("dload_2"),
183+
&Instruction::DLOAD_3 => format!("dload_3"),
184+
&Instruction::DMUL => format!("dmul"),
185+
&Instruction::DNEG => format!("dneg"),
186+
&Instruction::DREM => format!("drem"),
187+
&Instruction::DRETURN => format!("dreturn"),
188+
&Instruction::DSTORE(value) => format!("dstore {}", value),
189+
&Instruction::DSTORE_0 => format!("dstore_0"),
190+
&Instruction::DSTORE_1 => format!("dstore_1"),
191+
&Instruction::DSTORE_2 => format!("dstore_2"),
192+
&Instruction::DSTORE_3 => format!("dstore_3"),
193+
&Instruction::DSUB => format!("dsub"),
194+
&Instruction::DUP => format!("dup"),
195+
&Instruction::DUP_X1 => format!("dup_x1"),
196+
&Instruction::DUP_X2 => format!("dup_x2"),
197+
&Instruction::DUP2 => format!("dup2"),
198+
&Instruction::DUP2_X1 => format!("dup2_x1"),
199+
&Instruction::DUP2_X2 => format!("dup2_x2"),
200+
&Instruction::F2D => format!("f2d"),
201+
&Instruction::F2I => format!("f2i"),
202+
&Instruction::F2L => format!("f2l"),
203+
&Instruction::FADD => format!("fadd"),
204+
&Instruction::FALOAD => format!("faload"),
205+
&Instruction::FASTORE => format!("fastore"),
206+
&Instruction::FCMPL => format!("fcmpl"),
207+
&Instruction::FCMPG => format!("fcmpg"),
208+
&Instruction::FCONST_0 => format!("fconst_0"),
209+
&Instruction::FCONST_1 => format!("fconst_1"),
210+
&Instruction::FCONST_2 => format!("fconst_2"),
211+
&Instruction::FDIV => format!("fdiv"),
212+
&Instruction::FLOAD(value) => format!("fload {}", value),
213+
&Instruction::FLOAD_0 => format!("fload_0"),
214+
&Instruction::FLOAD_1 => format!("fload_1"),
215+
&Instruction::FLOAD_2 => format!("fload_2"),
216+
&Instruction::FLOAD_3 => format!("fload_3"),
217+
&Instruction::FMUL => format!("fmul"),
218+
&Instruction::FNEG => format!("fneg"),
219+
&Instruction::FREM => format!("frem"),
220+
&Instruction::FRETURN => format!("freturn"),
221+
&Instruction::FSTORE(value) => format!("fstore {}", value),
222+
&Instruction::FSTORE_0 => format!("fstore_0"),
223+
&Instruction::FSTORE_1 => format!("fstore_1"),
224+
&Instruction::FSTORE_2 => format!("fstore_2"),
225+
&Instruction::FSTORE_3 => format!("fstore_3"),
226+
&Instruction::FSUB => format!("fsub"),
227+
&Instruction::GETFIELD(value) => format!("getfield {}", value),
228+
&Instruction::GETSTATIC(value) => format!("getstatic {}", value),
229+
&Instruction::GOTO(value) => format!("goto {}", value),
230+
&Instruction::GOTO_W(value) => format!("goto_w {}", value),
231+
&Instruction::I2B => format!("i2b"),
232+
&Instruction::I2C => format!("i2c"),
233+
&Instruction::I2D => format!("i2d"),
234+
&Instruction::I2F => format!("i2f"),
235+
&Instruction::I2L => format!("i2l"),
236+
&Instruction::I2S => format!("i2s"),
237+
&Instruction::IADD => format!("iadd"),
238+
&Instruction::IALOAD => format!("iaload"),
239+
&Instruction::IAND => format!("iand"),
240+
&Instruction::IASTORE => format!("iastore"),
241+
&Instruction::ICONST_M1 => format!("iconst_m1"),
242+
&Instruction::ICONST_0 => format!("iconst_0"),
243+
&Instruction::ICONST_1 => format!("iconst_1"),
244+
&Instruction::ICONST_2 => format!("iconst_2"),
245+
&Instruction::ICONST_3 => format!("iconst_3"),
246+
&Instruction::ICONST_4 => format!("iconst_4"),
247+
&Instruction::ICONST_5 => format!("iconst_5"),
248+
&Instruction::IDIV => format!("idiv"),
249+
&Instruction::IF_ACMPEQ(value) => format!("if_acmpeq"),
250+
&Instruction::IF_ACMPNE(value) => format!("if_acmpne"),
251+
&Instruction::IF_ICMPEQ(value) => format!("if_icmpeq"),
252+
&Instruction::IF_ICMPNE(value) => format!("if_icmpne"),
253+
&Instruction::IF_ICMPLT(value) => format!("if_icmplt"),
254+
&Instruction::IF_ICMPGE(value) => format!("if_icmpge"),
255+
&Instruction::IF_ICMPGT(value) => format!("if_icmpgt"),
256+
&Instruction::IF_ICMPLE(value) => format!("if_icmple"),
257+
&Instruction::IFEQ(value) => format!("ifeq"),
258+
&Instruction::IFNE(value) => format!("ifne"),
259+
&Instruction::IFLT(value) => format!("iflt"),
260+
&Instruction::IFGE(value) => format!("ifge"),
261+
&Instruction::IFGT(value) => format!("ifgt"),
262+
&Instruction::IFLE(value) => format!("ifle"),
263+
&Instruction::IFNONNULL(value) => format!("ifnonnull"),
264+
&Instruction::IFNULL(value) => format!("ifnull"),
265+
&Instruction::IINC(value, increment) => format!("iinc"),
266+
&Instruction::ILOAD(value) => format!("iload"),
267+
&Instruction::ILOAD_0 => format!("iload_0"),
268+
&Instruction::ILOAD_1 => format!("iload_1"),
269+
&Instruction::ILOAD_2 => format!("iload_2"),
270+
&Instruction::ILOAD_3 => format!("iload_3"),
271+
&Instruction::IMUL => format!("imul"),
272+
&Instruction::INEG => format!("ineg"),
273+
&Instruction::INSTANCEOF(value) => format!("instanceof"),
274+
&Instruction::INVOKEDYNAMIC(value) => format!("invokedynamic #{}", value),
275+
&Instruction::INVOKEINTERFACE(value, index) => format!("invokeinterface #{}", value),
276+
&Instruction::INVOKESPECIAL(value) => format!("invokespecial {}", ClassfilePrinter::resolve_method_reference(&ConstantPoolIndex::new(value as usize), cp)),
277+
&Instruction::INVOKESTATIC(value) => format!("invokestatic {}", ClassfilePrinter::resolve_method_reference(&ConstantPoolIndex::new(value as usize), cp)),
278+
&Instruction::INVOKEVIRTUAL(value) => format!("invokevirtual {}", ClassfilePrinter::resolve_method_reference(&ConstantPoolIndex::new(value as usize), cp)),
279+
&Instruction::IOR => format!("ior"),
280+
&Instruction::IREM => format!("irem"),
281+
&Instruction::IRETURN => format!("ireturn"),
282+
&Instruction::ISHL => format!("ishl"),
283+
&Instruction::ISHR => format!("ishr"),
284+
&Instruction::ISTORE(value) => format!("istore {}", value),
285+
&Instruction::ISTORE_0 => format!("istore_0"),
286+
&Instruction::ISTORE_1 => format!("istore_1"),
287+
&Instruction::ISTORE_2 => format!("istore_2"),
288+
&Instruction::ISTORE_3 => format!("istore_3"),
289+
&Instruction::ISUB => format!("isub"),
290+
&Instruction::IUSHR => format!("iushr"),
291+
&Instruction::IXOR => format!("ixor"),
292+
&Instruction::JSR(value) => format!("jsr"),
293+
&Instruction::JSR_W(value) => format!("jsr_w"),
294+
&Instruction::L2D => format!("l2d"),
295+
&Instruction::L2F => format!("l2f"),
296+
&Instruction::L2I => format!("l2i"),
297+
&Instruction::LADD => format!("ladd"),
298+
&Instruction::LALOAD => format!("laload"),
299+
&Instruction::LAND => format!("land"),
300+
&Instruction::LASTORE => format!("lastore"),
301+
&Instruction::LCMP => format!("lcmp"),
302+
&Instruction::LCONST_0 => format!("lconst_0"),
303+
&Instruction::LCONST_1 => format!("lconst_1"),
304+
&Instruction::LDC(value) => format!("ldc"),
305+
&Instruction::LDC_W(value) => format!("ldc_w"),
306+
&Instruction::LDC2_W(value) => format!("ldc2_w"),
307+
&Instruction::LDIV => format!("ldiv"),
308+
&Instruction::LLOAD(value) => format!("lload"),
309+
&Instruction::LLOAD_0 => format!("lload_0"),
310+
&Instruction::LLOAD_1 => format!("lload_1"),
311+
&Instruction::LLOAD_2 => format!("lload_2"),
312+
&Instruction::LLOAD_3 => format!("lload_3"),
313+
&Instruction::LMUL => format!("lmul"),
314+
&Instruction::LNEG => format!("lneg"),
315+
&Instruction::LOOKUPSWITCH(value, ref table) => format!("lookupswitch"),
316+
&Instruction::LOR => format!("lor"),
317+
&Instruction::LREM => format!("lrem"),
318+
&Instruction::LRETURN => format!("lreturn"),
319+
&Instruction::LSHL => format!("lshl"),
320+
&Instruction::LSHR => format!("lshr"),
321+
&Instruction::LSTORE(value) => format!("lstore {}", value),
322+
&Instruction::LSTORE_0 => format!("lstore_0"),
323+
&Instruction::LSTORE_1 => format!("lstore_1"),
324+
&Instruction::LSTORE_2 => format!("lstore_2"),
325+
&Instruction::LSTORE_3 => format!("lstore_3"),
326+
&Instruction::LSUB => format!("lsub"),
327+
&Instruction::LUSHR => format!("lushr"),
328+
&Instruction::LXOR => format!("lxor"),
329+
&Instruction::MONITORENTER => format!("monitorenter"),
330+
&Instruction::MONITOREXIT => format!("monitorexit"),
331+
&Instruction::MULTIANEWARRAY(value, size) => format!("multianewarray"),
332+
&Instruction::NEW(value) => format!("new"),
333+
&Instruction::NEWARRAY(value) => format!("newarray"),
334+
&Instruction::NOP => format!("nop"),
335+
&Instruction::POP => format!("pop"),
336+
&Instruction::POP2 => format!("pop2"),
337+
&Instruction::PUTFIELD(value) => format!("putfield"),
338+
&Instruction::PUTSTATIC(value) => format!("putstatic"),
339+
&Instruction::RET(value) => format!("ret"),
340+
&Instruction::RETURN => format!("return"),
341+
&Instruction::SALOAD => format!("saload"),
342+
&Instruction::SASTORE => format!("sastore"),
343+
&Instruction::SIPUSH(value) => format!("sipush {}", value),
344+
&Instruction::SWAP => format!("swap"),
345+
&Instruction::TABLESWITCH(value, _, _, _) => format!("tableswitch"),
346+
&Instruction::IINC_W(value, increment) => format!("iinc_w"),
347+
&Instruction::ILOAD_W(value) => format!("iload_w {}", value),
348+
&Instruction::FLOAD_W(value) => format!("fload_w {}", value),
349+
&Instruction::ALOAD_W(value) => format!("aload_w {}", value),
350+
&Instruction::LLOAD_W(value) => format!("lload_w {}", value),
351+
&Instruction::DLOAD_W(value) => format!("dload_w {}", value),
352+
&Instruction::ISTORE_W(value) => format!("istore_w {}", value),
353+
&Instruction::FSTORE_W(value) => format!("fstore_w {}", value),
354+
&Instruction::ASTORE_W(value) => format!("astore_w {}", value),
355+
&Instruction::LSTORE_W(value) => format!("lstore_w {}", value),
356+
&Instruction::DSTORE_W(value) => format!("dstore_w {}", value),
357+
&Instruction::RET_W(value) => format!("ret_w {}", value),
358+
&Instruction::PADDED_INSTRUCTION(value) => format!("padded_instruction {}", value),
359+
&Instruction::WTF(value) => format!("wtf {}", value),
360+
_ => format!("instr")
361+
})).map(|line| {
362+
lines.push(format!(" {:>4} {}", instr_pointer, line.1));
363+
instr_pointer = instr_pointer + line.0
364+
}).collect();
365+
},
366+
&Attribute::LineNumberTable(ref table) => {
367+
lines.push(String::from(" LineNumberTable"));
368+
369+
let _: Vec<()> = ClassfilePrinter::render_line_number_table(table).iter().map(|line_number| lines.push(format!(" {}", line_number))).collect();
370+
},
371+
&Attribute::ConstantValue(ref cpi) => {
372+
lines.push(format!(" ConstantValue #{}", cpi.idx));
373+
},
374+
&Attribute::StackMapTable(_) => {
375+
lines.push(format!(" StackMapTable"));
376+
},
377+
&Attribute::AnnotationDefault(_) => {
378+
lines.push(format!(" AnnotationDefault"));
379+
},
380+
&Attribute::BootstrapMethods(_) => {
381+
lines.push(format!(" BootstrapMethods"));
382+
},
383+
_ => {
384+
lines.push(format!("RandomAttribute"));
385+
()
386+
},
387+
//Code { max_stack: u16, max_locals: u16, code: Vec<Instruction>, exception_table: Vec<ExceptionHandler>, attributes: Vec<Attribute> },
388+
}
389+
390+
lines
391+
}
392+
393+
pub fn render_line_number_table(table: &Vec<LineNumberTable>) -> Vec<String> {
394+
table.iter().map(|line| format!("{} {}", line.start_pc, line.line_number)).collect()
395+
}
107396
}

0 commit comments

Comments
 (0)