* config/pa/linux-atomic.c (__kernel_cmpxchg): Reorder arguments to
[official-gcc.git] / gcc / java / jcf-dump.c
blob83299f2a7757c14de33ecb57d041202594bcc434
1 /* Program to dump out a Java(TM) .class file.
2 Functionally similar to Sun's javap.
4 Copyright (C) 1996-2015 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>.
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc. */
26 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
29 jcf-dump is a program to print out the contents of class files.
30 Usage: jcf-dump [FLAGS] CLASS
31 Each CLASS is either:
32 + the name of a class in the CLASSPATH (e.g "java.lang.String"), or
33 + the name of a class *file* (e.g. "/home/me/work/package/Foo.class").
34 + The name of a .zip or .jar file (which prints all the classes in the
35 archive).
37 OPTIONS:
39 Dis-assemble each method.
40 -classpath PATH
41 Overrides $CLASSPATH.
42 --print-main
43 Print nothing if there is no valid "main" method;
44 otherwise, print only the class name.
45 --javap
46 Print output in the style of Sun's javap program. VERY UNFINISHED.
50 #include "config.h"
51 #include "system.h"
52 #include "coretypes.h"
53 #include "intl.h"
54 #include "diagnostic.h"
56 #include "jcf.h"
57 #include "alias.h"
58 #include "symtab.h"
59 #include "options.h"
60 #include "tree.h"
61 #include "java-tree.h"
63 #include "version.h"
65 #include <getopt.h>
66 #include <math.h>
68 /* Output file. */
69 FILE *out;
70 /* Name of output file, if NULL if stdout. */
71 char *output_file = NULL;
73 int verbose = 0;
75 int flag_disassemble_methods = 0;
76 int flag_print_class_info = 1;
77 int flag_print_constant_pool = 0;
78 int flag_print_fields = 1;
79 int flag_print_methods = 1;
80 int flag_print_attributes = 1;
82 /* Print names of classes that have a "main" method. */
83 int flag_print_main = 0;
85 /* Index in constant pool of this class. */
86 int this_class_index = 0;
88 int class_access_flags = 0;
90 /* Print in format similar to javap. VERY INCOMPLETE. */
91 int flag_javap_compatible = 0;
93 static void print_access_flags (FILE *, uint16, char);
94 static void print_constant_terse (FILE*, JCF*, int, int);
95 static void print_constant_terse_with_index (FILE *, JCF *, int, int);
96 static void print_constant (FILE *, JCF *, int, int);
97 static void print_constant_ref (FILE *, JCF *, int);
98 static void disassemble_method (JCF*, const unsigned char *, int);
99 static void print_name (FILE*, JCF*, int);
100 static void print_signature (FILE*, JCF*, int, int);
101 static int utf8_equal_string (struct JCF*, int, const char *);
102 static void usage (void) ATTRIBUTE_NORETURN;
103 static void help (void) ATTRIBUTE_NORETURN;
104 static void version (void) ATTRIBUTE_NORETURN;
105 static void process_class (struct JCF *);
106 static void print_constant_pool (struct JCF *);
107 static void print_exception_table (struct JCF *, const unsigned char *entries,
108 int);
109 static void indent (FILE *, int);
110 static void print_element_value (FILE *, JCF *, int);
111 static void print_annotation (FILE *, JCF *, int);
112 static void print_annotations (FILE *, JCF *, int);
113 static void print_parameter_annotations (FILE *, JCF *, int);
115 #define PRINT_SIGNATURE_RESULT_ONLY 1
116 #define PRINT_SIGNATURE_ARGS_ONLY 2
118 static int
119 utf8_equal_string (JCF *jcf, int index, const char * value)
121 if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index)
122 && JPOOL_TAG (jcf, index) == CONSTANT_Utf8)
124 int len = strlen (value);
125 if (JPOOL_UTF_LENGTH (jcf, index) == len
126 && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0)
127 return 1;
129 return 0;
132 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
133 this_class_index = 0; \
134 if (flag_print_class_info) \
135 fprintf (out, \
136 "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
137 (unsigned long) MAGIC, (long) MINOR, (long) MAJOR)
139 #define HANDLE_START_CONSTANT_POOL(COUNT) \
140 if (flag_print_constant_pool) \
141 fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
143 #define HANDLE_SOURCEFILE(INDEX) \
144 { fprintf (out, "Attribute "); \
145 print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
146 fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
147 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
149 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
150 this_class_index = THIS; \
151 class_access_flags = ACCESS_FLAGS; \
152 if (flag_print_class_info) \
153 { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
154 print_access_flags (out, ACCESS_FLAGS, 'c'); \
155 fputc ('\n', out); \
156 fprintf (out, "This class: "); \
157 print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
158 if (flag_print_constant_pool || SUPER != 0) \
159 fprintf (out, ", super: "); \
160 if (flag_print_constant_pool) \
162 fprintf (out, "%d", SUPER); \
163 if (SUPER != 0) \
164 fputc ('=', out); \
166 if (SUPER != 0) \
167 print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
168 fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
171 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
172 (flag_print_attributes <= 0)
174 #define HANDLE_CLASS_INTERFACE(INDEX) \
175 if (flag_print_class_info) \
176 { fprintf (out, "- Implements: "); \
177 print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
178 fputc ('\n', out); }
180 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
181 if (flag_print_fields) \
182 fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
184 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
185 if (flag_print_fields) \
186 { fprintf (out, "Field name:"); \
187 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
188 print_access_flags (out, ACCESS_FLAGS, 'f'); \
189 fprintf (out, " Descriptor: "); \
190 if (flag_print_constant_pool) \
191 fprintf (out, "%d=", SIGNATURE); \
192 print_signature (out, jcf, SIGNATURE, 0); \
193 fputc ('\n', out); } \
194 else \
195 flag_print_attributes--;
197 #define HANDLE_END_FIELD() \
198 if (! flag_print_fields) \
199 flag_print_attributes++;
201 #define HANDLE_START_METHODS(METHODS_COUNT) \
202 if (flag_print_methods) \
203 fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
204 else \
205 flag_print_attributes--;
208 #define HANDLE_END_METHODS() \
209 if (! flag_print_methods) \
210 flag_print_attributes++;
212 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
214 if (flag_print_methods) \
216 if (flag_javap_compatible) \
218 fprintf (out, " "); \
219 print_access_flags (out, ACCESS_FLAGS, 'm'); \
220 fputc (' ', out); \
221 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
222 fputc (' ', out); \
223 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
224 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
225 fputc ('\n', out); \
227 else \
229 fprintf (out, "\nMethod name:"); \
230 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
231 print_access_flags (out, ACCESS_FLAGS, 'm'); \
232 fprintf (out, " Descriptor: "); \
233 if (flag_print_constant_pool) \
234 fprintf (out, "%d=", SIGNATURE); \
235 print_signature (out, jcf, SIGNATURE, 0); \
236 fputc ('\n', out); \
239 if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
240 && utf8_equal_string (jcf, NAME, "main") \
241 && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
242 && this_class_index > 0 \
243 && (class_access_flags & ACC_PUBLIC)) \
245 print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
246 fputc ('\n', out); \
250 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
251 ( fprintf (out, "Attribute "), \
252 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
253 fprintf (out, ", length:%ld", (long) LENGTH) )
255 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
256 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
257 fprintf (out, ", value: "), \
258 print_constant_ref (out, jcf, VALUE_INDEX), \
259 fprintf (out, "\n") )
261 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
262 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
263 fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
264 (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
265 disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
267 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
268 print_exception_table (jcf, ENTRIES, COUNT)
270 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
271 { int n = (COUNT); int i; \
272 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
273 fprintf (out, ", count: %d\n", n); \
274 for (i = 0; i < n; i++) {\
275 int ex_index = JCF_readu2 (jcf); \
276 fprintf (out, "%3d: ", i); \
277 print_constant_ref (out, jcf, ex_index); \
278 fputc ('\n', out); } }
280 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
281 { int n = (COUNT); int i; \
282 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
283 fprintf (out, ", count: %d\n", n); \
284 for (i = 0; i < n; i++) {\
285 int start_pc = JCF_readu2 (jcf); \
286 int length = JCF_readu2 (jcf); \
287 int name_index = JCF_readu2 (jcf); \
288 int signature_index = JCF_readu2 (jcf); \
289 int slot = JCF_readu2 (jcf); \
290 fprintf (out, " slot#%d: name: ", slot); \
291 if (flag_print_constant_pool) \
292 fprintf (out, "%d=", name_index); \
293 print_name (out, jcf, name_index); \
294 fprintf (out, ", type: "); \
295 if (flag_print_constant_pool) \
296 fprintf (out, "%d=", signature_index); \
297 print_signature (out, jcf, signature_index, 0); \
298 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
300 #define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT) \
301 { int n = (COUNT); int i; \
302 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
303 fprintf (out, ", count: %d\n", n); \
304 for (i = 0; i < n; i++) { \
305 int start_pc = JCF_readu2 (jcf); \
306 int length = JCF_readu2 (jcf); \
307 int name_index = JCF_readu2 (jcf); \
308 int signature_index = JCF_readu2 (jcf); \
309 int slot = JCF_readu2 (jcf); \
310 fprintf (out, " slot#%d: name: ", slot); \
311 if (flag_print_constant_pool) \
312 fprintf (out, "%d=", name_index); \
313 print_name (out, jcf, name_index); \
314 fprintf (out, ", type: "); \
315 if (flag_print_constant_pool) \
316 fprintf (out, "%d=", signature_index); \
317 print_signature (out, jcf, signature_index, 0); \
318 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
320 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
321 { int n = (COUNT); int i; \
322 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
323 fprintf (out, ", count: %d\n", n); \
324 if (flag_disassemble_methods) \
325 for (i = 0; i < n; i++) {\
326 int start_pc = JCF_readu2 (jcf); \
327 int line_number = JCF_readu2 (jcf); \
328 fprintf (out, " line: %d at pc: %d\n", line_number, start_pc); }\
329 else \
330 JCF_SKIP (jcf, 4 * n); }
332 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
333 { int n = (COUNT); \
334 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
335 while (n--) \
337 uint16 inner_class_info_index = JCF_readu2 (jcf); \
338 uint16 outer_class_info_index = JCF_readu2 (jcf); \
339 uint16 inner_name_index = JCF_readu2 (jcf); \
340 uint16 inner_class_access_flags = JCF_readu2 (jcf); \
342 if (flag_print_class_info) \
344 fprintf (out, "\n inner: "); \
345 if (inner_class_info_index == 0) \
346 fprintf (out, " (no inner info index)"); \
347 else \
348 print_constant_terse_with_index (out, jcf, \
349 inner_class_info_index, \
350 CONSTANT_Class); \
351 if (inner_name_index == 0) \
352 fprintf (out, " (anonymous)"); \
353 else if (verbose || flag_print_constant_pool) \
355 fprintf (out, " ("); \
356 print_constant_terse_with_index (out, jcf, inner_name_index, \
357 CONSTANT_Utf8); \
358 fputc (')', out); \
360 fprintf (out, ", access flags: 0x%x", inner_class_access_flags); \
361 print_access_flags (out, inner_class_access_flags, 'c'); \
362 fprintf (out, ", outer class: "); \
363 if (outer_class_info_index == 0) \
364 fprintf (out, "(not a member)"); \
365 else \
366 print_constant_terse_with_index (out, jcf, \
367 outer_class_info_index, \
368 CONSTANT_Class); \
371 if (flag_print_class_info) \
372 fputc ('\n', out); \
375 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
376 { int i, n = (LENGTH), c = 0; \
377 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
378 fputc ('\n', out); \
379 for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
380 if (c != '\r' && c != '\n') fputc('\n', out); }
382 #define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE() \
383 { uint16 class_index, method_index; \
384 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
385 class_index = JCF_readu2 (jcf); \
386 method_index = JCF_readu2 (jcf); \
387 fprintf (out, "\n Class: "); \
388 print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
389 fprintf (out, "\n Method: "); \
390 print_constant_terse_with_index (out, jcf, method_index, \
391 CONSTANT_NameAndType); \
392 fputc ('\n', out); \
395 #define HANDLE_SIGNATURE_ATTRIBUTE() \
397 uint16 signature; \
398 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
399 signature = JCF_readu2 (jcf); \
400 fprintf (out, "\n Value: "); \
401 print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8); \
402 fputc ('\n', out); \
405 #define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE() \
407 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
408 print_annotations (out, jcf, 1); \
411 #define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE() \
413 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
414 print_annotations (out, jcf, 1); \
417 #define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
419 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
420 print_parameter_annotations (out, jcf, 1); \
423 #define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
425 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
426 print_parameter_annotations (out, jcf, 1); \
429 #define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE() \
431 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
432 print_element_value (out, jcf, 1); \
435 #define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \
437 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
438 fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \
441 #define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \
443 int i; \
444 for (i = 0; i < NUM_METHODS; i++) \
446 bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \
447 fprintf (out, " %d: ", i); \
448 print_constant (out, jcf, m->method_ref, 1); \
449 fprintf (out, "\n"); \
453 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
454 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
455 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
457 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
458 if (flag_print_attributes > 0) \
459 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
461 #include "javaop.h"
465 static void
466 indent (FILE *stream, int level)
468 int i;
469 for (i = 0; i < level; ++i)
470 fprintf (stream, " ");
473 static void
474 print_element_value (FILE *stream, JCF *jcf, int level)
476 uint8 tag = JCF_readu (jcf);
477 indent (stream, level);
478 switch (tag)
480 case 'B':
481 case 'C':
482 case 'S':
483 case 'Z':
484 case 'I':
486 uint16 cindex = JCF_readu2 (jcf);
487 print_constant_terse_with_index (stream, jcf, cindex,
488 CONSTANT_Integer);
490 break;
491 case 'D':
493 uint16 cindex = JCF_readu2 (jcf);
494 print_constant_terse_with_index (stream, jcf, cindex,
495 CONSTANT_Double);
497 break;
498 case 'F':
500 uint16 cindex = JCF_readu2 (jcf);
501 print_constant_terse_with_index (stream, jcf, cindex,
502 CONSTANT_Float);
504 break;
505 case 'J':
507 uint16 cindex = JCF_readu2 (jcf);
508 print_constant_terse_with_index (stream, jcf, cindex,
509 CONSTANT_Long);
511 break;
512 case 's':
514 uint16 cindex = JCF_readu2 (jcf);
515 /* Despite what the JVM spec says, compilers generate a Utf8
516 constant here, not a String. */
517 print_constant_terse_with_index (stream, jcf, cindex,
518 CONSTANT_Utf8);
520 break;
522 case 'e':
524 uint16 type_name_index = JCF_readu2 (jcf);
525 uint16 const_name_index = JCF_readu2 (jcf);
526 fprintf (stream, "enum class: ");
527 print_constant_terse_with_index (stream, jcf, type_name_index,
528 CONSTANT_Utf8);
529 fprintf (stream, "\n");
530 indent (stream, level);
531 fprintf (stream, "Field: ");
532 print_constant_terse_with_index (stream, jcf, const_name_index,
533 CONSTANT_Utf8);
535 break;
536 case 'c':
538 uint16 class_info_index = JCF_readu2 (jcf);
539 print_constant_terse_with_index (stream, jcf, class_info_index,
540 CONSTANT_Utf8);
542 break;
543 case '@':
545 fprintf (stream, "Annotation:\n");
546 print_annotation (stream, jcf, level + 1);
548 break;
549 case '[':
551 uint16 n_array_elts = JCF_readu2 (jcf);
552 fprintf (stream, "array[%d]: [\n", (int) n_array_elts);
553 while (n_array_elts--)
554 print_element_value (stream, jcf, level + 1);
555 indent (stream, level);
556 fprintf (stream, "]");
558 break;
559 default:
560 fprintf (stream, "Unexpected tag value: %d", (int) tag);
561 break;
563 fputc ('\n', stream);
566 static void
567 print_annotation (FILE *stream, JCF *jcf, int level)
569 uint16 type_index = JCF_readu2 (jcf);
570 uint16 npairs = JCF_readu2 (jcf);
571 fprintf (stream, "\n");
572 indent (stream, level);
573 fprintf (stream, "Annotation name: ");
574 print_constant_terse_with_index (stream, jcf, type_index,
575 CONSTANT_Utf8);
576 if (npairs)
578 fprintf (stream, "\n");
579 while (npairs--)
581 uint16 name_index = JCF_readu2 (jcf);
582 indent (stream, level + 1);
583 fprintf (stream, "Name: ");
584 print_constant_terse_with_index (stream, jcf, name_index,
585 CONSTANT_Utf8);
586 fprintf (stream, "\n");
587 print_element_value (stream, jcf, level + 2);
592 static void
593 print_annotations (FILE *stream, JCF *jcf, int level)
595 uint16 num = JCF_readu2 (jcf);
596 while (num--)
597 print_annotation (stream, jcf, level);
600 static void
601 print_parameter_annotations (FILE *stream, JCF *jcf, int level)
603 uint8 nparams = JCF_readu (jcf);
604 uint8 i;
605 for (i = 0; i < nparams; ++i)
607 indent (stream, level);
608 fprintf (stream, "Parameter annotations (%d):\n", (int) i);
609 print_annotations (stream, jcf, level + 1);
615 static void
616 print_constant_ref (FILE *stream, JCF *jcf, int index)
618 if (index <= 0 || index >= JPOOL_SIZE(jcf))
619 fprintf (stream, "<out of range>");
620 else
622 if (flag_print_constant_pool)
623 fprintf (stream, "#%d=", index);
624 fputc ('<', stream);
625 print_constant (stream, jcf, index, 1);
626 fputc ('>', stream);
630 /* Print the access flags given by FLAGS.
631 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
632 or 'm' (method flags). */
634 static void
635 print_access_flags (FILE *stream, uint16 flags, char context)
637 if (flags & ACC_PUBLIC) fprintf (stream, " public");
638 if (flags & ACC_PRIVATE) fprintf (stream, " private");
639 if (flags & ACC_PROTECTED) fprintf (stream, " protected");
640 if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
641 if (flags & ACC_STATIC) fprintf (stream, " static");
642 if (flags & ACC_FINAL) fprintf (stream, " final");
643 if (flags & ACC_TRANSIENT)
644 fprintf (stream, context == 'm' ? " varargs" : " transient");
645 if (flags & ACC_VOLATILE)
646 fprintf (stream, context == 'm' ? " bridge" : " volatile");
647 if (flags & ACC_NATIVE) fprintf (stream, " native");
648 if (flags & ACC_SYNCHRONIZED)
650 if (context == 'c')
651 fprintf (stream, " super");
652 else
653 fprintf (stream, " synchronized");
655 if (flags & ACC_INTERFACE)
656 fprintf (stream, (flags & ACC_ANNOTATION) ? " @interface" : " interface");
657 if (flags & ACC_ENUM) fprintf (stream, " enum");
658 if (flags & ACC_STRICT) fprintf (stream, " strictfp");
659 if (flags & ACC_SYNTHETIC) fprintf (stream, " synthetic");
663 static void
664 print_name (FILE* stream, JCF* jcf, int name_index)
666 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
667 fprintf (stream, "<not a UTF8 constant>");
668 else
669 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
670 JPOOL_UTF_LENGTH (jcf, name_index));
673 /* If the type of the constant at INDEX matches EXPECTED,
674 print it tersely, otherwise more verbosely. */
676 static void
677 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
679 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
680 fprintf (out, "<constant pool index %d not in range>", index);
681 else if (JPOOL_TAG (jcf, index) != expected)
683 fprintf (out, "<Unexpected constant type ");
684 print_constant (out, jcf, index, 1);
685 fprintf (out, ">");
687 else
688 print_constant (out, jcf, index, 0);
691 static void
692 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
694 if (flag_print_constant_pool)
695 fprintf (out, "%d=", index);
696 print_constant_terse (out, jcf, index, expected);
699 /* Print the constant at INDEX in JCF's constant pool.
700 If verbosity==0, print very tersely (no extraneous text).
701 If verbosity==1, prefix the type of the constant.
702 If verbosity==2, add more descriptive text. */
704 static void
705 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
707 int j, n;
708 jlong num;
709 const char *str;
710 int kind = JPOOL_TAG (jcf, index);
711 switch (kind)
713 case CONSTANT_Class:
714 n = JPOOL_USHORT1 (jcf, index);
715 if (verbosity > 0)
717 if (verbosity > 1)
718 fprintf (out, "Class name: %d=", n);
719 else
720 fprintf (out, "Class ");
722 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
723 fprintf (out, "<out of range>");
724 else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
726 int len = JPOOL_UTF_LENGTH (jcf, n);
727 jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
729 else
730 print_constant_terse (out, jcf, n, CONSTANT_Utf8);
731 break;
732 case CONSTANT_Fieldref:
733 str = "Field"; goto field_or_method;
734 case CONSTANT_Methodref:
735 str = "Method"; goto field_or_method;
736 case CONSTANT_InterfaceMethodref:
737 str = "InterfaceMethod"; goto field_or_method;
738 field_or_method:
740 uint16 tclass = JPOOL_USHORT1 (jcf, index);
741 uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
742 if (verbosity == 2)
743 fprintf (out, "%sref class: %d=", str, tclass);
744 else if (verbosity > 0)
745 fprintf (out, "%s ", str);
746 print_constant_terse (out, jcf, tclass, CONSTANT_Class);
747 if (verbosity < 2)
748 fprintf (out, ".");
749 else
750 fprintf (out, " name_and_type: %d=<", name_and_type);
751 print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
752 if (verbosity == 2)
753 fputc ('>', out);
755 break;
756 case CONSTANT_String:
757 j = JPOOL_USHORT1 (jcf, index);
758 if (verbosity > 0)
760 if (verbosity > 1)
761 fprintf (out, "String %d=", j);
762 else
763 fprintf (out, "String ");
765 print_constant_terse (out, jcf, j, CONSTANT_Utf8);
766 break;
767 case CONSTANT_Integer:
768 if (verbosity > 0)
769 fprintf (out, "Integer ");
770 num = JPOOL_INT (jcf, index);
771 goto integer;
772 case CONSTANT_Long:
773 if (verbosity > 0)
774 fprintf (out, "Long ");
775 num = JPOOL_LONG (jcf, index);
776 goto integer;
777 integer:
779 char buffer[25];
780 format_int (buffer, num, 10);
781 fprintf (out, "%s", buffer);
782 if (verbosity > 1)
784 format_uint (buffer, (uint64)num, 16);
785 fprintf (out, "=0x%s", buffer);
788 break;
789 case CONSTANT_Float:
791 jfloat fnum = JPOOL_FLOAT (jcf, index);
793 if (verbosity > 0)
794 fputs ("Float ", out);
796 if (fnum.negative)
797 putc ('-', out);
799 if (JFLOAT_FINITE (fnum))
801 int dummy;
802 int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
803 double f;
804 uint32 mantissa = fnum.mantissa;
805 if (fnum.exponent == 0)
806 /* Denormal. */
807 exponent++;
808 else
809 /* Normal; add the implicit bit. */
810 mantissa |= ((uint32)1 << 23);
812 f = frexp ((float) mantissa, &dummy);
813 f = ldexp (f, exponent + 1);
814 fprintf (out, "%.10g", f);
816 else
818 if (fnum.mantissa == 0)
819 fputs ("Inf", out);
820 else if (fnum.mantissa & JFLOAT_QNAN_MASK)
821 fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
822 else
823 fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
826 if (verbosity > 1)
827 fprintf (out, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf, index));
829 break;
831 case CONSTANT_Double:
833 jdouble dnum = JPOOL_DOUBLE (jcf, index);
835 if (verbosity > 0)
836 fputs ("Double ", out);
838 if (dnum.negative)
839 putc ('-', out);
841 if (JDOUBLE_FINITE (dnum))
843 int dummy;
844 int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
845 double d;
846 uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
847 + dnum.mantissa1);
848 if (dnum.exponent == 0)
849 /* Denormal. */
850 exponent++;
851 else
852 /* Normal; add the implicit bit. */
853 mantissa |= ((uint64)1 << 52);
855 d = frexp ((double) mantissa, &dummy);
856 d = ldexp (d, exponent + 1);
857 fprintf (out, "%.20g", d);
859 else
861 uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
862 mantissa = (mantissa << 32) + dnum.mantissa1;
864 if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
865 fputs ("Inf", out);
866 else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
867 fprintf (out, "QNaN(%" HOST_LONG_LONG_FORMAT "u)",
868 (unsigned long long)mantissa);
869 else
870 fprintf (out, "SNaN(%" HOST_LONG_LONG_FORMAT "u)",
871 (unsigned long long)mantissa);
873 if (verbosity > 1)
875 int32 hi, lo;
876 hi = JPOOL_UINT (jcf, index);
877 lo = JPOOL_UINT (jcf, index + 1);
878 fprintf (out, ", bits = 0x%08lx%08lx", (unsigned long) hi,
879 (unsigned long) lo);
881 break;
883 case CONSTANT_NameAndType:
885 uint16 name = JPOOL_USHORT1 (jcf, index);
886 uint16 sig = JPOOL_USHORT2 (jcf, index);
887 if (verbosity > 0)
889 if (verbosity > 1)
890 fprintf (out, "NameAndType name: %d=", name);
891 else
892 fprintf (out, "NameAndType ");
894 print_name (out, jcf, name);
895 if (verbosity <= 1)
896 fputc (' ', out);
897 else
898 fprintf (out, ", signature: %d=", sig);
899 print_signature (out, jcf, sig, 0);
901 break;
902 case CONSTANT_Utf8:
904 const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
905 int length = JPOOL_UTF_LENGTH (jcf, index);
906 if (verbosity > 0)
907 { /* Print as 8-bit bytes. */
908 fputs ("Utf8: \"", out);
909 while (--length >= 0)
910 jcf_print_char (out, *str++);
912 else
913 { /* Print as Unicode. */
914 fputc ('\"', out);
915 jcf_print_utf8 (out, str, length);
917 fputc ('\"', out);
919 break;
920 case CONSTANT_MethodHandle:
922 int kind = JPOOL_USHORT1 (jcf, index);
923 if (verbosity > 0)
924 fprintf (out, "MethodHandle kind: %d=", kind);
925 switch(kind) {
926 case 1:
927 case 2:
928 case 3:
929 case 4:
930 if (verbosity > 0)
931 fprintf (out, "Fieldref: %ld=", (long) JPOOL_USHORT2 (jcf, index));
932 print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0);
933 case 5:
934 case 6:
935 case 7:
936 case 8:
937 if (verbosity > 0)
938 fprintf (out, "Methodref: %ld=", (long) JPOOL_USHORT2 (jcf, index));
939 print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0);
940 break;
941 case 9:
942 if (verbosity > 0)
943 fprintf (out, "InterfaceMethodref: %ld=",
944 (long) JPOOL_USHORT2 (jcf, index));
945 print_constant (out, jcf, JPOOL_USHORT2 (jcf, index), 0);
946 break;
948 break;
950 case CONSTANT_MethodType:
951 if (verbosity > 0)
952 fprintf (out, "MethodType %ld: ", (long) JPOOL_USHORT1 (jcf, index));
953 print_signature (out, jcf, JPOOL_USHORT1 (jcf, index), 0);
954 break;
955 case CONSTANT_InvokeDynamic:
957 uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
958 if (verbosity > 0)
959 fprintf (out, "InvokeDynamic: ");
960 fprintf (out, "bootstrap_method: %ld ",
961 (long) JPOOL_USHORT1 (jcf, index));
962 if (verbosity == 2)
963 fprintf (out, " name_and_type: %d=<", name_and_type);
964 print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
965 if (verbosity == 2)
966 fputc ('>', out);
967 break;
969 default:
970 fprintf (out, "(Unknown constant type %d)", kind);
974 static void
975 print_constant_pool (JCF *jcf)
977 int i;
978 for (i = 1; i < JPOOL_SIZE(jcf); i++)
980 int kind = JPOOL_TAG (jcf, i);
981 fprintf (out, "#%d: ", i);
982 print_constant (out, jcf, i, 2);
983 fprintf (out, "\n");
984 if (kind == CONSTANT_Double || kind == CONSTANT_Long)
985 i++; /* These take up two slots in the constant table */
989 static void
990 print_signature_type (FILE* stream, const unsigned char **ptr,
991 const unsigned char *limit)
993 int array_size;
994 if ((*ptr) >= limit)
995 return;
996 switch (*(*ptr))
998 case '[':
999 array_size = -1;
1000 for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
1002 array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
1004 print_signature_type (stream, ptr, limit);
1005 if (array_size == -1)
1006 fprintf (stream, "[]");
1007 else
1008 fprintf (stream, "[%d]", array_size);
1009 break;
1010 case '(':
1012 int nargs = 0;
1013 fputc (*(*ptr)++, stream);
1014 for (; **ptr != ')' && *ptr < limit; nargs++)
1016 if (nargs > 0)
1017 fputc (',', stream);
1018 print_signature_type (stream, ptr, limit);
1020 if (*ptr < limit)
1022 fputc (*(*ptr)++, stream);
1023 print_signature_type (stream, ptr, limit);
1025 else
1026 fprintf (stream, "???");
1028 break;
1030 case 'B': fprintf (stream, "byte"); (*ptr)++; break;
1031 case 'C': fprintf (stream, "char"); (*ptr)++; break;
1032 case 'D': fprintf (stream, "double"); (*ptr)++; break;
1033 case 'F': fprintf (stream, "float"); (*ptr)++; break;
1034 case 'S': fprintf (stream, "short"); (*ptr)++; break;
1035 case 'I': fprintf (stream, "int"); (*ptr)++; break;
1036 case 'J': fprintf (stream, "long"); (*ptr)++; break;
1037 case 'Z': fprintf (stream, "boolean"); (*ptr)++; break;
1038 case 'V': fprintf (stream, "void"); (*ptr)++; break;
1040 case 'L':
1041 for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
1042 jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
1043 if (*(*ptr) == ';')
1044 (*ptr)++;
1045 break;
1046 default:
1047 jcf_print_char (stream, *(*ptr)++);
1051 static void
1052 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
1054 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1055 print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
1056 else
1058 const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
1059 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1060 const unsigned char *limit;
1061 limit = str + length;
1062 if (str >= limit)
1063 fprintf (stream, "<empty signature string>");
1064 else
1066 if (options & PRINT_SIGNATURE_RESULT_ONLY)
1068 while (str < limit && *str++ != ')') ;
1070 if (options & PRINT_SIGNATURE_ARGS_ONLY)
1072 str++;
1073 fputc ('(', stream);
1074 while (str < limit && *str != ')')
1076 print_signature_type (stream, &str, limit);
1077 if (*str != ')')
1078 fputs (", ", stream);
1080 fputc (')', stream);
1082 else
1084 print_signature_type (stream, &str, limit);
1085 if (str < limit)
1087 fprintf (stream, "<junk:");
1088 jcf_print_utf8 (stream, str, limit - str);
1089 fputc ('>', stream);
1097 static void
1098 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
1100 /* Print exception table. */
1101 int i = count;
1102 if (i > 0)
1104 const unsigned char *ptr = entries;
1105 fprintf (out, "Exceptions (count: %d):\n", i);
1106 for (; --i >= 0; ptr+= 8)
1108 int start_pc = GET_u2 (ptr);
1109 int end_pc = GET_u2 (ptr+2);
1110 int handler_pc = GET_u2 (ptr+4);
1111 int catch_type = GET_u2 (ptr+6);
1112 fprintf (out, " start: %d, end: %d, handler: %d, type: ",
1113 start_pc, end_pc, handler_pc);
1114 if (catch_type == 0)
1115 fputs ("0 /* finally */", out);
1116 else
1117 print_constant_terse_with_index (out, jcf,
1118 catch_type, CONSTANT_Class);
1119 fputc ('\n', out);
1124 #include "jcf-reader.c"
1126 static void
1127 process_class (JCF *jcf)
1129 int code;
1130 if (jcf_parse_preamble (jcf) != 0)
1131 fprintf (stderr, _("Not a valid Java .class file.\n"));
1133 /* Parse and possibly print constant pool */
1134 code = jcf_parse_constant_pool (jcf);
1135 if (code != 0)
1137 fprintf (stderr, _("error while parsing constant pool\n"));
1138 exit (FATAL_EXIT_CODE);
1140 code = verify_constant_pool (jcf);
1141 if (code > 0)
1143 fprintf (stderr, _("error in constant pool entry #%d\n"), code);
1144 exit (FATAL_EXIT_CODE);
1146 if (flag_print_constant_pool)
1147 print_constant_pool (jcf);
1149 jcf_parse_class (jcf);
1150 code = jcf_parse_fields (jcf);
1151 if (code != 0)
1153 fprintf (stderr, _("error while parsing fields\n"));
1154 exit (FATAL_EXIT_CODE);
1156 code = jcf_parse_methods (jcf);
1157 if (code != 0)
1159 fprintf (stderr, _("error while parsing methods\n"));
1160 exit (FATAL_EXIT_CODE);
1162 code = jcf_parse_final_attributes (jcf);
1163 if (code != 0)
1165 fprintf (stderr, _("error while parsing final attributes\n"));
1166 exit (FATAL_EXIT_CODE);
1168 jcf->filename = NULL;
1173 /* This is used to mark options with no short value. */
1174 #define LONG_OPT(Num) ((Num) + 128)
1176 #define OPT_classpath LONG_OPT (0)
1177 #define OPT_CLASSPATH OPT_classpath
1178 #define OPT_bootclasspath LONG_OPT (1)
1179 #define OPT_extdirs LONG_OPT (2)
1180 #define OPT_HELP LONG_OPT (3)
1181 #define OPT_VERSION LONG_OPT (4)
1182 #define OPT_JAVAP LONG_OPT (5)
1184 static const struct option options[] =
1186 { "classpath", required_argument, NULL, OPT_classpath },
1187 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
1188 { "extdirs", required_argument, NULL, OPT_extdirs },
1189 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
1190 { "help", no_argument, NULL, OPT_HELP },
1191 { "verbose", no_argument, NULL, 'v' },
1192 { "version", no_argument, NULL, OPT_VERSION },
1193 { "javap", no_argument, NULL, OPT_JAVAP },
1194 { "print-main", no_argument, &flag_print_main, 1 },
1195 { "print-constants", no_argument, &flag_print_constant_pool, 1 },
1196 { NULL, no_argument, NULL, 0 }
1199 static void
1200 usage (void)
1202 fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
1203 exit (1);
1206 static void
1207 help (void)
1209 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
1210 printf (_("Display contents of a class file in readable form.\n\n"));
1211 printf (_(" -c Disassemble method bodies\n"));
1212 printf (_(" --javap Generate output in 'javap' format\n"));
1213 printf ("\n");
1214 printf (_(" --classpath PATH Set path to find .class files\n"));
1215 printf (_(" -IDIR Append directory to class path\n"));
1216 printf (_(" --bootclasspath PATH Override built-in class path\n"));
1217 printf (_(" --extdirs PATH Set extensions directory path\n"));
1218 printf (_(" -o FILE Set output file name\n"));
1219 printf ("\n");
1220 printf (_(" --help Print this help, then exit\n"));
1221 printf (_(" --version Print version number, then exit\n"));
1222 printf (_(" -v, --verbose Print extra information while running\n"));
1223 printf ("\n");
1224 printf (_("For bug reporting instructions, please see:\n"
1225 "%s.\n"), bug_report_url);
1226 exit (0);
1229 static void
1230 version (void)
1232 printf ("jcf-dump %s%s\n\n", pkgversion_string, version_string);
1233 printf ("Copyright %s 2015 Free Software Foundation, Inc.\n", _("(C)"));
1234 printf (_("This is free software; see the source for copying conditions. There is NO\n"
1235 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
1236 exit (0);
1240 main (int argc, char** argv)
1242 JCF jcf[1];
1243 int argi, opt;
1244 const char *p;
1246 p = argv[0] + strlen (argv[0]);
1247 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
1248 --p;
1249 progname = p;
1251 xmalloc_set_program_name (progname);
1253 /* Unlock the stdio streams. */
1254 unlock_std_streams ();
1256 gcc_init_libintl ();
1258 diagnostic_initialize (global_dc, 0);
1260 if (argc <= 1)
1262 fprintf (stderr, _("jcf-dump: no classes specified\n"));
1263 usage ();
1266 jcf_path_init ();
1268 /* We use getopt_long_only to allow single `-' long options. For
1269 some of our options this is more natural. */
1270 while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
1272 switch (opt)
1274 case 0:
1275 /* Already handled. */
1276 break;
1278 case 'o':
1279 output_file = optarg;
1280 break;
1282 case 'I':
1283 jcf_path_include_arg (optarg);
1284 break;
1286 case 'v':
1287 verbose++;
1288 break;
1290 case 'c':
1291 flag_disassemble_methods = 1;
1292 break;
1294 case OPT_classpath:
1295 jcf_path_classpath_arg (optarg);
1296 break;
1298 case OPT_bootclasspath:
1299 jcf_path_bootclasspath_arg (optarg);
1300 break;
1302 case OPT_extdirs:
1303 jcf_path_extdirs_arg (optarg);
1304 break;
1306 case OPT_HELP:
1307 help ();
1308 break;
1310 case OPT_VERSION:
1311 version ();
1312 break;
1314 case OPT_JAVAP:
1315 flag_javap_compatible++;
1316 flag_print_constant_pool = 0;
1317 flag_print_attributes = 0;
1318 break;
1320 default:
1321 usage ();
1325 if (verbose && ! flag_javap_compatible)
1326 flag_print_constant_pool = 1;
1328 if (optind == argc)
1330 fprintf (stderr, _("jcf-dump: no classes specified\n"));
1331 usage ();
1334 jcf_path_seal (verbose);
1336 if (flag_print_main)
1338 flag_print_fields = 0;
1339 flag_print_methods = 0;
1340 flag_print_constant_pool = 0;
1341 flag_print_attributes = 0;
1342 flag_print_class_info = 0;
1345 if (output_file)
1347 out = fopen (output_file, "w");
1348 if (! out)
1350 fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1351 return FATAL_EXIT_CODE;
1354 else
1355 out = stdout;
1357 if (optind >= argc)
1359 fprintf (out, "Reading .class from <standard input>.\n");
1360 open_class ("<stdio>", jcf, 0, NULL);
1361 process_class (jcf);
1363 else
1365 for (argi = optind; argi < argc; argi++)
1367 char *arg = argv[argi];
1368 const char *class_filename = find_class (arg, strlen (arg), jcf);
1369 if (class_filename == NULL)
1370 class_filename = find_classfile (arg, jcf, NULL);
1371 if (class_filename == NULL)
1373 perror ("Could not find class");
1374 return FATAL_EXIT_CODE;
1376 JCF_FILL (jcf, 4);
1377 if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1379 long compressed_size, member_size;
1380 int compression_method, filename_length, extra_length;
1381 const char *filename;
1382 int total_length;
1383 if (flag_print_class_info)
1384 fprintf (out, "Reading classes from archive %s.\n",
1385 class_filename);
1386 for (;;)
1388 int skip = 0;
1389 jcf_filbuf_t save_filbuf = jcf->filbuf;
1390 long magic = JCF_readu4_le (jcf);
1391 if (magic == 0x02014b50 || magic == 0x06054b50)
1392 break; /* got to central directory */
1393 if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1395 fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1396 return FATAL_EXIT_CODE;
1398 JCF_FILL (jcf, 26);
1399 JCF_SKIP (jcf, 2);
1400 (void) /* general_purpose_bits = */ JCF_readu2_le (jcf);
1401 compression_method = JCF_readu2_le (jcf);
1402 JCF_SKIP (jcf, 8);
1403 compressed_size = JCF_readu4_le (jcf);
1404 member_size = JCF_readu4_le (jcf);
1405 filename_length = JCF_readu2_le (jcf);
1406 extra_length = JCF_readu2_le (jcf);
1407 total_length = filename_length + extra_length
1408 + compressed_size;
1409 if (jcf->read_end - jcf->read_ptr < total_length)
1410 jcf_trim_old_input (jcf);
1411 JCF_FILL (jcf, total_length);
1412 filename = (const char *) jcf->read_ptr;
1413 JCF_SKIP (jcf, filename_length);
1414 JCF_SKIP (jcf, extra_length);
1415 if (filename_length > 0
1416 && filename[filename_length-1] == '/')
1418 if (flag_print_class_info)
1419 fprintf (out, "[Skipping directory %.*s]\n",
1420 filename_length, filename);
1421 skip = 1;
1423 else if (compression_method != 0)
1425 if (flag_print_class_info)
1426 fprintf (out, "[Skipping compressed file %.*s]\n",
1427 filename_length, filename);
1428 skip = 1;
1430 else if (member_size < 4
1431 || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1433 if (flag_print_class_info)
1434 fprintf (out, "[Skipping non-.class member %.*s]\n",
1435 filename_length, filename);
1436 skip = 1;
1438 else
1440 if (flag_print_class_info)
1441 fprintf (out, "Reading class member: %.*s.\n",
1442 filename_length, filename);
1444 if (skip)
1446 JCF_SKIP (jcf, compressed_size);
1448 else
1450 unsigned char *save_end;
1451 jcf->filbuf = jcf_unexpected_eof;
1452 save_end = jcf->read_end;
1453 jcf->read_end = jcf->read_ptr + compressed_size;
1454 process_class (jcf);
1455 jcf->filbuf = save_filbuf;
1456 jcf->read_end = save_end;
1460 else
1462 if (flag_print_class_info)
1463 fprintf (out, "Reading .class from %s.\n", class_filename);
1464 process_class (jcf);
1466 JCF_FINISH(jcf);
1470 return SUCCESS_EXIT_CODE;
1475 static void
1476 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1478 #undef PTR
1479 int PC;
1480 int i;
1481 int saw_wide = 0;
1482 if (flag_disassemble_methods == 0)
1483 return;
1484 #define BCODE byte_ops
1485 for (PC = 0; PC < len;)
1487 int oldpc = PC;
1488 int saw_index;
1489 jint INT_temp;
1490 switch (byte_ops[PC++])
1493 /* This is the actual code emitted for each of opcodes in javaops.def.
1494 The actual opcode-specific stuff is handled by the OPKIND macro.
1495 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1496 Those macros are defined below. The OPKINDs that do not have any
1497 inline parameters (such as BINOP) and therefore do mot need anything
1498 else to me printed out just use an empty body. */
1500 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1501 case OPCODE: \
1502 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1503 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1504 fputc ('\n', out); \
1505 break;
1507 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1508 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1509 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1510 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1512 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1513 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1515 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1516 These all push a constant onto the opcode stack. */
1517 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1518 saw_index = 0, i = (OPERAND_VALUE); \
1519 if (oldpc+1 == PC) /* nothing */; \
1520 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1521 else fprintf (out, " %d", i);
1523 /* Print out operand (a local variable index) for LOAD opcodes.
1524 These all push local variable onto the opcode stack. */
1525 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1526 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1528 /* Handle STORE opcodes same as LOAD opcodes.
1529 These all store a value from the opcode stack in a local variable. */
1530 #define STORE LOAD
1532 /* Handle more kind of opcodes. */
1533 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1534 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1535 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1536 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1537 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1538 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1539 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1541 /* Handle putfield and getfield opcodes, with static versions. */
1542 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1543 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1545 /* Print operand for invoke opcodes. */
1546 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1547 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1548 if (OPERAND_VALUE) /* for invokeinterface */ \
1549 { int nargs = IMMEDIATE_u1; PC++; \
1550 fprintf (out, " nargs:%d", nargs); }
1552 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1553 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1555 #define ARRAY(OPERAND_TYPE, SUBOP) \
1556 ARRAY_##SUBOP(OPERAND_TYPE)
1557 /* Handle sub-categories of ARRAY opcodes. */
1558 #define ARRAY_LOAD(TYPE) /* nothing */
1559 #define ARRAY_STORE(TYPE) /* nothing */
1560 #define ARRAY_LENGTH(TYPE) /* nothing */
1561 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1562 #define ARRAY_NEW_NUM \
1563 INT_temp = IMMEDIATE_u1; \
1564 { switch ((int) INT_temp) { \
1565 case 4: fputs (" boolean", out); break; \
1566 case 5: fputs (" char", out); break; \
1567 case 6: fputs (" float", out); break; \
1568 case 7: fputs (" double", out); break; \
1569 case 8: fputs (" byte", out); break; \
1570 case 9: fputs (" short", out); break; \
1571 case 10: fputs (" int", out); break; \
1572 case 11: fputs (" long", out); break; \
1573 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1576 #define ARRAY_NEW_PTR \
1577 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1579 #define ARRAY_NEW_MULTI \
1580 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1581 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1583 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1584 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1586 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1587 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1588 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1590 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1591 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1592 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1594 #undef RET /* Defined by config/i386/i386.h */
1595 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1596 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1597 saw_wide = 0; \
1598 fprintf (out, " %ld", (long) INT_temp);
1600 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1601 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1603 #define LOOKUP_SWITCH \
1604 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1605 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1606 while (--npairs >= 0) { \
1607 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1608 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1611 #define TABLE_SWITCH \
1612 { jint default_offset = IMMEDIATE_s4; \
1613 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1614 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1615 (long) low, (long) high, (long) default_offset+oldpc); \
1616 for (; low <= high; low++) { \
1617 jint offset = IMMEDIATE_s4; \
1618 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1621 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1622 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1624 #define SPECIAL_IINC(OPERAND_TYPE) \
1625 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1626 fprintf (out, " %d", i); \
1627 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1628 saw_wide = 0; \
1629 fprintf (out, " %d", i)
1631 #define SPECIAL_WIDE(OPERAND_TYPE) \
1632 saw_wide = 1;
1634 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1635 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1636 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1637 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1639 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1640 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1642 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1643 TEST(OPERAND_TYPE, OPERAND_VALUE)
1645 #include "javaop.def"
1647 load_store:
1648 if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1649 else
1651 saw_wide = 0;
1652 fprintf (out, " %ld", (long) INT_temp);
1654 fputc ('\n', out);
1655 break;
1657 default:
1658 fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);