@@ -22,6 +22,13 @@ impl ClassfilePrinter {
22
22
. map ( |line| lines. push ( line) )
23
23
. collect ( ) ;
24
24
25
+ let _: Vec < ( ) > = ClassfilePrinter :: render_methods ( & classfile) . iter ( )
26
+ . map ( |method| {
27
+ format ! ( "{}" , method)
28
+ } )
29
+ . map ( |line| lines. push ( line) )
30
+ . collect ( ) ;
31
+
25
32
lines
26
33
}
27
34
@@ -90,6 +97,13 @@ impl ClassfilePrinter {
90
97
} ) . unwrap_or ( String :: from ( "<Not found>" ) )
91
98
}
92
99
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
+
93
107
pub fn resolve_reference_kind ( kind : & ReferenceKind ) -> String {
94
108
String :: from ( match kind {
95
109
& ReferenceKind :: GetField => "GetField" ,
@@ -104,4 +118,279 @@ impl ClassfilePrinter {
104
118
_ => "Unknown"
105
119
} )
106
120
}
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
+ }
107
396
}
0 commit comments