1 /* Program to dump out a Java(TM) .class file.
2 Functionally similar to Sun's javap.
4 Copyright (C) 1996-2013 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)
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
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
39 Dis-assemble each method.
43 Print nothing if there is no valid "main" method;
44 otherwise, print only the class name.
46 Print output in the style of Sun's javap program. VERY UNFINISHED.
52 #include "coretypes.h"
54 #include "diagnostic.h"
58 #include "java-tree.h"
67 /* Name of output file, if NULL if stdout. */
68 char *output_file
= NULL
;
72 int flag_disassemble_methods
= 0;
73 int flag_print_class_info
= 1;
74 int flag_print_constant_pool
= 0;
75 int flag_print_fields
= 1;
76 int flag_print_methods
= 1;
77 int flag_print_attributes
= 1;
79 /* Print names of classes that have a "main" method. */
80 int flag_print_main
= 0;
82 /* Index in constant pool of this class. */
83 int this_class_index
= 0;
85 int class_access_flags
= 0;
87 /* Print in format similar to javap. VERY INCOMPLETE. */
88 int flag_javap_compatible
= 0;
90 static void print_access_flags (FILE *, uint16
, char);
91 static void print_constant_terse (FILE*, JCF
*, int, int);
92 static void print_constant_terse_with_index (FILE *, JCF
*, int, int);
93 static void print_constant (FILE *, JCF
*, int, int);
94 static void print_constant_ref (FILE *, JCF
*, int);
95 static void disassemble_method (JCF
*, const unsigned char *, int);
96 static void print_name (FILE*, JCF
*, int);
97 static void print_signature (FILE*, JCF
*, int, int);
98 static int utf8_equal_string (struct JCF
*, int, const char *);
99 static void usage (void) ATTRIBUTE_NORETURN
;
100 static void help (void) ATTRIBUTE_NORETURN
;
101 static void version (void) ATTRIBUTE_NORETURN
;
102 static void process_class (struct JCF
*);
103 static void print_constant_pool (struct JCF
*);
104 static void print_exception_table (struct JCF
*, const unsigned char *entries
,
106 static void indent (FILE *, int);
107 static void print_element_value (FILE *, JCF
*, int);
108 static void print_annotation (FILE *, JCF
*, int);
109 static void print_annotations (FILE *, JCF
*, int);
110 static void print_parameter_annotations (FILE *, JCF
*, int);
112 #define PRINT_SIGNATURE_RESULT_ONLY 1
113 #define PRINT_SIGNATURE_ARGS_ONLY 2
116 utf8_equal_string (JCF
*jcf
, int index
, const char * value
)
118 if (CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
)
119 && JPOOL_TAG (jcf
, index
) == CONSTANT_Utf8
)
121 int len
= strlen (value
);
122 if (JPOOL_UTF_LENGTH (jcf
, index
) == len
123 && memcmp (JPOOL_UTF_DATA (jcf
, index
), value
, len
) == 0)
129 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
130 this_class_index = 0; \
131 if (flag_print_class_info) \
133 "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
134 (unsigned long) MAGIC, (long) MINOR, (long) MAJOR)
136 #define HANDLE_START_CONSTANT_POOL(COUNT) \
137 if (flag_print_constant_pool) \
138 fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
140 #define HANDLE_SOURCEFILE(INDEX) \
141 { fprintf (out, "Attribute "); \
142 print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
143 fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
144 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
146 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
147 this_class_index = THIS; \
148 class_access_flags = ACCESS_FLAGS; \
149 if (flag_print_class_info) \
150 { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
151 print_access_flags (out, ACCESS_FLAGS, 'c'); \
153 fprintf (out, "This class: "); \
154 print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
155 if (flag_print_constant_pool || SUPER != 0) \
156 fprintf (out, ", super: "); \
157 if (flag_print_constant_pool) \
159 fprintf (out, "%d", SUPER); \
164 print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
165 fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
168 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
169 (flag_print_attributes <= 0)
171 #define HANDLE_CLASS_INTERFACE(INDEX) \
172 if (flag_print_class_info) \
173 { fprintf (out, "- Implements: "); \
174 print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
177 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
178 if (flag_print_fields) \
179 fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
181 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
182 if (flag_print_fields) \
183 { fprintf (out, "Field name:"); \
184 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
185 print_access_flags (out, ACCESS_FLAGS, 'f'); \
186 fprintf (out, " Descriptor: "); \
187 if (flag_print_constant_pool) \
188 fprintf (out, "%d=", SIGNATURE); \
189 print_signature (out, jcf, SIGNATURE, 0); \
190 fputc ('\n', out); } \
192 flag_print_attributes--;
194 #define HANDLE_END_FIELD() \
195 if (! flag_print_fields) \
196 flag_print_attributes++;
198 #define HANDLE_START_METHODS(METHODS_COUNT) \
199 if (flag_print_methods) \
200 fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
202 flag_print_attributes--;
205 #define HANDLE_END_METHODS() \
206 if (! flag_print_methods) \
207 flag_print_attributes++;
209 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
211 if (flag_print_methods) \
213 if (flag_javap_compatible) \
215 fprintf (out, " "); \
216 print_access_flags (out, ACCESS_FLAGS, 'm'); \
218 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
220 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
221 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
226 fprintf (out, "\nMethod name:"); \
227 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
228 print_access_flags (out, ACCESS_FLAGS, 'm'); \
229 fprintf (out, " Descriptor: "); \
230 if (flag_print_constant_pool) \
231 fprintf (out, "%d=", SIGNATURE); \
232 print_signature (out, jcf, SIGNATURE, 0); \
236 if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
237 && utf8_equal_string (jcf, NAME, "main") \
238 && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
239 && this_class_index > 0 \
240 && (class_access_flags & ACC_PUBLIC)) \
242 print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
247 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
248 ( fprintf (out, "Attribute "), \
249 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
250 fprintf (out, ", length:%ld", (long) LENGTH) )
252 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
253 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
254 fprintf (out, ", value: "), \
255 print_constant_ref (out, jcf, VALUE_INDEX), \
256 fprintf (out, "\n") )
258 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
259 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
260 fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
261 (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
262 disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
264 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
265 print_exception_table (jcf, ENTRIES, COUNT)
267 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
268 { int n = (COUNT); int i; \
269 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
270 fprintf (out, ", count: %d\n", n); \
271 for (i = 0; i < n; i++) {\
272 int ex_index = JCF_readu2 (jcf); \
273 fprintf (out, "%3d: ", i); \
274 print_constant_ref (out, jcf, ex_index); \
275 fputc ('\n', out); } }
277 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
278 { int n = (COUNT); int i; \
279 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
280 fprintf (out, ", count: %d\n", n); \
281 for (i = 0; i < n; i++) {\
282 int start_pc = JCF_readu2 (jcf); \
283 int length = JCF_readu2 (jcf); \
284 int name_index = JCF_readu2 (jcf); \
285 int signature_index = JCF_readu2 (jcf); \
286 int slot = JCF_readu2 (jcf); \
287 fprintf (out, " slot#%d: name: ", slot); \
288 if (flag_print_constant_pool) \
289 fprintf (out, "%d=", name_index); \
290 print_name (out, jcf, name_index); \
291 fprintf (out, ", type: "); \
292 if (flag_print_constant_pool) \
293 fprintf (out, "%d=", signature_index); \
294 print_signature (out, jcf, signature_index, 0); \
295 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
297 #define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT) \
298 { int n = (COUNT); int i; \
299 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
300 fprintf (out, ", count: %d\n", n); \
301 for (i = 0; i < n; i++) { \
302 int start_pc = JCF_readu2 (jcf); \
303 int length = JCF_readu2 (jcf); \
304 int name_index = JCF_readu2 (jcf); \
305 int signature_index = JCF_readu2 (jcf); \
306 int slot = JCF_readu2 (jcf); \
307 fprintf (out, " slot#%d: name: ", slot); \
308 if (flag_print_constant_pool) \
309 fprintf (out, "%d=", name_index); \
310 print_name (out, jcf, name_index); \
311 fprintf (out, ", type: "); \
312 if (flag_print_constant_pool) \
313 fprintf (out, "%d=", signature_index); \
314 print_signature (out, jcf, signature_index, 0); \
315 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
317 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
318 { int n = (COUNT); int i; \
319 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
320 fprintf (out, ", count: %d\n", n); \
321 if (flag_disassemble_methods) \
322 for (i = 0; i < n; i++) {\
323 int start_pc = JCF_readu2 (jcf); \
324 int line_number = JCF_readu2 (jcf); \
325 fprintf (out, " line: %d at pc: %d\n", line_number, start_pc); }\
327 JCF_SKIP (jcf, 4 * n); }
329 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
331 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
334 uint16 inner_class_info_index = JCF_readu2 (jcf); \
335 uint16 outer_class_info_index = JCF_readu2 (jcf); \
336 uint16 inner_name_index = JCF_readu2 (jcf); \
337 uint16 inner_class_access_flags = JCF_readu2 (jcf); \
339 if (flag_print_class_info) \
341 fprintf (out, "\n inner: "); \
342 if (inner_class_info_index == 0) \
343 fprintf (out, " (no inner info index)"); \
345 print_constant_terse_with_index (out, jcf, \
346 inner_class_info_index, \
348 if (inner_name_index == 0) \
349 fprintf (out, " (anonymous)"); \
350 else if (verbose || flag_print_constant_pool) \
352 fprintf (out, " ("); \
353 print_constant_terse_with_index (out, jcf, inner_name_index, \
357 fprintf (out, ", access flags: 0x%x", inner_class_access_flags); \
358 print_access_flags (out, inner_class_access_flags, 'c'); \
359 fprintf (out, ", outer class: "); \
360 if (outer_class_info_index == 0) \
361 fprintf (out, "(not a member)"); \
363 print_constant_terse_with_index (out, jcf, \
364 outer_class_info_index, \
368 if (flag_print_class_info) \
372 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
373 { int i, n = (LENGTH), c = 0; \
374 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
376 for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
377 if (c != '\r' && c != '\n') fputc('\n', out); }
379 #define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE() \
380 { uint16 class_index, method_index; \
381 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
382 class_index = JCF_readu2 (jcf); \
383 method_index = JCF_readu2 (jcf); \
384 fprintf (out, "\n Class: "); \
385 print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
386 fprintf (out, "\n Method: "); \
387 print_constant_terse_with_index (out, jcf, method_index, \
388 CONSTANT_NameAndType); \
392 #define HANDLE_SIGNATURE_ATTRIBUTE() \
395 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
396 signature = JCF_readu2 (jcf); \
397 fprintf (out, "\n Value: "); \
398 print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8); \
402 #define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE() \
404 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
405 print_annotations (out, jcf, 1); \
408 #define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE() \
410 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
411 print_annotations (out, jcf, 1); \
414 #define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
416 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
417 print_parameter_annotations (out, jcf, 1); \
420 #define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
422 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
423 print_parameter_annotations (out, jcf, 1); \
426 #define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE() \
428 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
429 print_element_value (out, jcf, 1); \
432 #define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \
434 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
435 fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \
438 #define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \
441 for (i = 0; i < NUM_METHODS; i++) \
443 bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \
444 fprintf (out, " %d: ", i); \
445 print_constant (out, jcf, m->method_ref, 1); \
446 fprintf (out, "\n"); \
450 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
451 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
452 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
454 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
455 if (flag_print_attributes > 0) \
456 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
463 indent (FILE *stream
, int level
)
466 for (i
= 0; i
< level
; ++i
)
467 fprintf (stream
, " ");
471 print_element_value (FILE *stream
, JCF
*jcf
, int level
)
473 uint8 tag
= JCF_readu (jcf
);
474 indent (stream
, level
);
483 uint16 cindex
= JCF_readu2 (jcf
);
484 print_constant_terse_with_index (stream
, jcf
, cindex
,
490 uint16 cindex
= JCF_readu2 (jcf
);
491 print_constant_terse_with_index (stream
, jcf
, cindex
,
497 uint16 cindex
= JCF_readu2 (jcf
);
498 print_constant_terse_with_index (stream
, jcf
, cindex
,
504 uint16 cindex
= JCF_readu2 (jcf
);
505 print_constant_terse_with_index (stream
, jcf
, cindex
,
511 uint16 cindex
= JCF_readu2 (jcf
);
512 /* Despite what the JVM spec says, compilers generate a Utf8
513 constant here, not a String. */
514 print_constant_terse_with_index (stream
, jcf
, cindex
,
521 uint16 type_name_index
= JCF_readu2 (jcf
);
522 uint16 const_name_index
= JCF_readu2 (jcf
);
523 fprintf (stream
, "enum class: ");
524 print_constant_terse_with_index (stream
, jcf
, type_name_index
,
526 fprintf (stream
, "\n");
527 indent (stream
, level
);
528 fprintf (stream
, "Field: ");
529 print_constant_terse_with_index (stream
, jcf
, const_name_index
,
535 uint16 class_info_index
= JCF_readu2 (jcf
);
536 print_constant_terse_with_index (stream
, jcf
, class_info_index
,
542 fprintf (stream
, "Annotation:\n");
543 print_annotation (stream
, jcf
, level
+ 1);
548 uint16 n_array_elts
= JCF_readu2 (jcf
);
549 fprintf (stream
, "array[%d]: [\n", (int) n_array_elts
);
550 while (n_array_elts
--)
551 print_element_value (stream
, jcf
, level
+ 1);
552 indent (stream
, level
);
553 fprintf (stream
, "]");
557 fprintf (stream
, "Unexpected tag value: %d", (int) tag
);
560 fputc ('\n', stream
);
564 print_annotation (FILE *stream
, JCF
*jcf
, int level
)
566 uint16 type_index
= JCF_readu2 (jcf
);
567 uint16 npairs
= JCF_readu2 (jcf
);
568 fprintf (stream
, "\n");
569 indent (stream
, level
);
570 fprintf (stream
, "Annotation name: ");
571 print_constant_terse_with_index (stream
, jcf
, type_index
,
575 fprintf (stream
, "\n");
578 uint16 name_index
= JCF_readu2 (jcf
);
579 indent (stream
, level
+ 1);
580 fprintf (stream
, "Name: ");
581 print_constant_terse_with_index (stream
, jcf
, name_index
,
583 fprintf (stream
, "\n");
584 print_element_value (stream
, jcf
, level
+ 2);
590 print_annotations (FILE *stream
, JCF
*jcf
, int level
)
592 uint16 num
= JCF_readu2 (jcf
);
594 print_annotation (stream
, jcf
, level
);
598 print_parameter_annotations (FILE *stream
, JCF
*jcf
, int level
)
600 uint8 nparams
= JCF_readu (jcf
);
602 for (i
= 0; i
< nparams
; ++i
)
604 indent (stream
, level
);
605 fprintf (stream
, "Parameter annotations (%d):\n", (int) i
);
606 print_annotations (stream
, jcf
, level
+ 1);
613 print_constant_ref (FILE *stream
, JCF
*jcf
, int index
)
615 if (index
<= 0 || index
>= JPOOL_SIZE(jcf
))
616 fprintf (stream
, "<out of range>");
619 if (flag_print_constant_pool
)
620 fprintf (stream
, "#%d=", index
);
622 print_constant (stream
, jcf
, index
, 1);
627 /* Print the access flags given by FLAGS.
628 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
629 or 'm' (method flags). */
632 print_access_flags (FILE *stream
, uint16 flags
, char context
)
634 if (flags
& ACC_PUBLIC
) fprintf (stream
, " public");
635 if (flags
& ACC_PRIVATE
) fprintf (stream
, " private");
636 if (flags
& ACC_PROTECTED
) fprintf (stream
, " protected");
637 if (flags
& ACC_ABSTRACT
) fprintf (stream
, " abstract");
638 if (flags
& ACC_STATIC
) fprintf (stream
, " static");
639 if (flags
& ACC_FINAL
) fprintf (stream
, " final");
640 if (flags
& ACC_TRANSIENT
)
641 fprintf (stream
, context
== 'm' ? " varargs" : " transient");
642 if (flags
& ACC_VOLATILE
)
643 fprintf (stream
, context
== 'm' ? " bridge" : " volatile");
644 if (flags
& ACC_NATIVE
) fprintf (stream
, " native");
645 if (flags
& ACC_SYNCHRONIZED
)
648 fprintf (stream
, " super");
650 fprintf (stream
, " synchronized");
652 if (flags
& ACC_INTERFACE
)
653 fprintf (stream
, (flags
& ACC_ANNOTATION
) ? " @interface" : " interface");
654 if (flags
& ACC_ENUM
) fprintf (stream
, " enum");
655 if (flags
& ACC_STRICT
) fprintf (stream
, " strictfp");
656 if (flags
& ACC_SYNTHETIC
) fprintf (stream
, " synthetic");
661 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
663 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
664 fprintf (stream
, "<not a UTF8 constant>");
666 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
,name_index
),
667 JPOOL_UTF_LENGTH (jcf
, name_index
));
670 /* If the type of the constant at INDEX matches EXPECTED,
671 print it tersely, otherwise more verbosely. */
674 print_constant_terse (FILE *out
, JCF
*jcf
, int index
, int expected
)
676 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
))
677 fprintf (out
, "<constant pool index %d not in range>", index
);
678 else if (JPOOL_TAG (jcf
, index
) != expected
)
680 fprintf (out
, "<Unexpected constant type ");
681 print_constant (out
, jcf
, index
, 1);
685 print_constant (out
, jcf
, index
, 0);
689 print_constant_terse_with_index (FILE *out
, JCF
*jcf
, int index
, int expected
)
691 if (flag_print_constant_pool
)
692 fprintf (out
, "%d=", index
);
693 print_constant_terse (out
, jcf
, index
, expected
);
696 /* Print the constant at INDEX in JCF's constant pool.
697 If verbosity==0, print very tersely (no extraneous text).
698 If verbosity==1, prefix the type of the constant.
699 If verbosity==2, add more descriptive text. */
702 print_constant (FILE *out
, JCF
*jcf
, int index
, int verbosity
)
707 int kind
= JPOOL_TAG (jcf
, index
);
711 n
= JPOOL_USHORT1 (jcf
, index
);
715 fprintf (out
, "Class name: %d=", n
);
717 fprintf (out
, "Class ");
719 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, n
))
720 fprintf (out
, "<out of range>");
721 else if (verbosity
< 2 && JPOOL_TAG (jcf
, n
) == CONSTANT_Utf8
)
723 int len
= JPOOL_UTF_LENGTH (jcf
, n
);
724 jcf_print_utf8_replace (out
, JPOOL_UTF_DATA(jcf
,n
), len
, '/', '.');
727 print_constant_terse (out
, jcf
, n
, CONSTANT_Utf8
);
729 case CONSTANT_Fieldref
:
730 str
= "Field"; goto field_or_method
;
731 case CONSTANT_Methodref
:
732 str
= "Method"; goto field_or_method
;
733 case CONSTANT_InterfaceMethodref
:
734 str
= "InterfaceMethod"; goto field_or_method
;
737 uint16 tclass
= JPOOL_USHORT1 (jcf
, index
);
738 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
740 fprintf (out
, "%sref class: %d=", str
, tclass
);
741 else if (verbosity
> 0)
742 fprintf (out
, "%s ", str
);
743 print_constant_terse (out
, jcf
, tclass
, CONSTANT_Class
);
747 fprintf (out
, " name_and_type: %d=<", name_and_type
);
748 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
753 case CONSTANT_String
:
754 j
= JPOOL_USHORT1 (jcf
, index
);
758 fprintf (out
, "String %d=", j
);
760 fprintf (out
, "String ");
762 print_constant_terse (out
, jcf
, j
, CONSTANT_Utf8
);
764 case CONSTANT_Integer
:
766 fprintf (out
, "Integer ");
767 num
= JPOOL_INT (jcf
, index
);
771 fprintf (out
, "Long ");
772 num
= JPOOL_LONG (jcf
, index
);
777 format_int (buffer
, num
, 10);
778 fprintf (out
, "%s", buffer
);
781 format_uint (buffer
, (uint64
)num
, 16);
782 fprintf (out
, "=0x%s", buffer
);
788 jfloat fnum
= JPOOL_FLOAT (jcf
, index
);
791 fputs ("Float ", out
);
796 if (JFLOAT_FINITE (fnum
))
799 int exponent
= fnum
.exponent
- JFLOAT_EXP_BIAS
;
801 uint32 mantissa
= fnum
.mantissa
;
802 if (fnum
.exponent
== 0)
806 /* Normal; add the implicit bit. */
807 mantissa
|= ((uint32
)1 << 23);
809 f
= frexp ((float) mantissa
, &dummy
);
810 f
= ldexp (f
, exponent
+ 1);
811 fprintf (out
, "%.10g", f
);
815 if (fnum
.mantissa
== 0)
817 else if (fnum
.mantissa
& JFLOAT_QNAN_MASK
)
818 fprintf (out
, "QNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
820 fprintf (out
, "SNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
824 fprintf (out
, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf
, index
));
828 case CONSTANT_Double
:
830 jdouble dnum
= JPOOL_DOUBLE (jcf
, index
);
833 fputs ("Double ", out
);
838 if (JDOUBLE_FINITE (dnum
))
841 int exponent
= dnum
.exponent
- JDOUBLE_EXP_BIAS
;
843 uint64 mantissa
= ((((uint64
) dnum
.mantissa0
) << 32)
845 if (dnum
.exponent
== 0)
849 /* Normal; add the implicit bit. */
850 mantissa
|= ((uint64
)1 << 52);
852 d
= frexp ((double) mantissa
, &dummy
);
853 d
= ldexp (d
, exponent
+ 1);
854 fprintf (out
, "%.20g", d
);
858 uint64 mantissa
= dnum
.mantissa0
& ~JDOUBLE_QNAN_MASK
;
859 mantissa
= (mantissa
<< 32) + dnum
.mantissa1
;
861 if (dnum
.mantissa0
== 0 && dnum
.mantissa1
== 0)
863 else if (dnum
.mantissa0
& JDOUBLE_QNAN_MASK
)
864 fprintf (out
, "QNaN(%" HOST_LONG_LONG_FORMAT
"u)",
865 (unsigned long long)mantissa
);
867 fprintf (out
, "SNaN(%" HOST_LONG_LONG_FORMAT
"u)",
868 (unsigned long long)mantissa
);
873 hi
= JPOOL_UINT (jcf
, index
);
874 lo
= JPOOL_UINT (jcf
, index
+ 1);
875 fprintf (out
, ", bits = 0x%08lx%08lx", (unsigned long) hi
,
880 case CONSTANT_NameAndType
:
882 uint16 name
= JPOOL_USHORT1 (jcf
, index
);
883 uint16 sig
= JPOOL_USHORT2 (jcf
, index
);
887 fprintf (out
, "NameAndType name: %d=", name
);
889 fprintf (out
, "NameAndType ");
891 print_name (out
, jcf
, name
);
895 fprintf (out
, ", signature: %d=", sig
);
896 print_signature (out
, jcf
, sig
, 0);
901 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, index
);
902 int length
= JPOOL_UTF_LENGTH (jcf
, index
);
904 { /* Print as 8-bit bytes. */
905 fputs ("Utf8: \"", out
);
906 while (--length
>= 0)
907 jcf_print_char (out
, *str
++);
910 { /* Print as Unicode. */
912 jcf_print_utf8 (out
, str
, length
);
917 case CONSTANT_MethodHandle
:
919 int kind
= JPOOL_USHORT1 (jcf
, index
);
921 fprintf (out
, "MethodHandle kind: %d=", kind
);
928 fprintf (out
, "Fieldref: %ld=", (long) JPOOL_USHORT2 (jcf
, index
));
929 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
935 fprintf (out
, "Methodref: %ld=", (long) JPOOL_USHORT2 (jcf
, index
));
936 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
940 fprintf (out
, "InterfaceMethodref: %ld=",
941 (long) JPOOL_USHORT2 (jcf
, index
));
942 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
947 case CONSTANT_MethodType
:
949 fprintf (out
, "MethodType %ld: ", (long) JPOOL_USHORT1 (jcf
, index
));
950 print_signature (out
, jcf
, JPOOL_USHORT1 (jcf
, index
), 0);
952 case CONSTANT_InvokeDynamic
:
954 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
956 fprintf (out
, "InvokeDynamic: ");
957 fprintf (out
, "bootstrap_method: %ld ",
958 (long) JPOOL_USHORT1 (jcf
, index
));
960 fprintf (out
, " name_and_type: %d=<", name_and_type
);
961 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
967 fprintf (out
, "(Unknown constant type %d)", kind
);
972 print_constant_pool (JCF
*jcf
)
975 for (i
= 1; i
< JPOOL_SIZE(jcf
); i
++)
977 int kind
= JPOOL_TAG (jcf
, i
);
978 fprintf (out
, "#%d: ", i
);
979 print_constant (out
, jcf
, i
, 2);
981 if (kind
== CONSTANT_Double
|| kind
== CONSTANT_Long
)
982 i
++; /* These take up two slots in the constant table */
987 print_signature_type (FILE* stream
, const unsigned char **ptr
,
988 const unsigned char *limit
)
997 for ((*ptr
)++; (*ptr
) < limit
&& ISDIGIT (**ptr
); (*ptr
)++)
999 array_size
= (array_size
< 0 ? 0 : 10 * array_size
) + *(*ptr
) - '0';
1001 print_signature_type (stream
, ptr
, limit
);
1002 if (array_size
== -1)
1003 fprintf (stream
, "[]");
1005 fprintf (stream
, "[%d]", array_size
);
1010 fputc (*(*ptr
)++, stream
);
1011 for (; **ptr
!= ')' && *ptr
< limit
; nargs
++)
1014 fputc (',', stream
);
1015 print_signature_type (stream
, ptr
, limit
);
1019 fputc (*(*ptr
)++, stream
);
1020 print_signature_type (stream
, ptr
, limit
);
1023 fprintf (stream
, "???");
1027 case 'B': fprintf (stream
, "byte"); (*ptr
)++; break;
1028 case 'C': fprintf (stream
, "char"); (*ptr
)++; break;
1029 case 'D': fprintf (stream
, "double"); (*ptr
)++; break;
1030 case 'F': fprintf (stream
, "float"); (*ptr
)++; break;
1031 case 'S': fprintf (stream
, "short"); (*ptr
)++; break;
1032 case 'I': fprintf (stream
, "int"); (*ptr
)++; break;
1033 case 'J': fprintf (stream
, "long"); (*ptr
)++; break;
1034 case 'Z': fprintf (stream
, "boolean"); (*ptr
)++; break;
1035 case 'V': fprintf (stream
, "void"); (*ptr
)++; break;
1038 for ((*ptr
)++; (*ptr
)<limit
&& *(*ptr
) != ';'; (*ptr
)++)
1039 jcf_print_char (stream
, *(*ptr
) == '/' ? '.' : *(*ptr
));
1044 jcf_print_char (stream
, *(*ptr
)++);
1049 print_signature (FILE* stream
, JCF
*jcf
, int signature_index
, int options
)
1051 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1052 print_constant_terse (out
, jcf
, signature_index
, CONSTANT_Utf8
);
1055 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, signature_index
);
1056 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1057 const unsigned char *limit
;
1058 limit
= str
+ length
;
1060 fprintf (stream
, "<empty signature string>");
1063 if (options
& PRINT_SIGNATURE_RESULT_ONLY
)
1065 while (str
< limit
&& *str
++ != ')') ;
1067 if (options
& PRINT_SIGNATURE_ARGS_ONLY
)
1070 fputc ('(', stream
);
1071 while (str
< limit
&& *str
!= ')')
1073 print_signature_type (stream
, &str
, limit
);
1075 fputs (", ", stream
);
1077 fputc (')', stream
);
1081 print_signature_type (stream
, &str
, limit
);
1084 fprintf (stream
, "<junk:");
1085 jcf_print_utf8 (stream
, str
, limit
- str
);
1086 fputc ('>', stream
);
1095 print_exception_table (JCF
*jcf
, const unsigned char *entries
, int count
)
1097 /* Print exception table. */
1101 const unsigned char *ptr
= entries
;
1102 fprintf (out
, "Exceptions (count: %d):\n", i
);
1103 for (; --i
>= 0; ptr
+= 8)
1105 int start_pc
= GET_u2 (ptr
);
1106 int end_pc
= GET_u2 (ptr
+2);
1107 int handler_pc
= GET_u2 (ptr
+4);
1108 int catch_type
= GET_u2 (ptr
+6);
1109 fprintf (out
, " start: %d, end: %d, handler: %d, type: ",
1110 start_pc
, end_pc
, handler_pc
);
1111 if (catch_type
== 0)
1112 fputs ("0 /* finally */", out
);
1114 print_constant_terse_with_index (out
, jcf
,
1115 catch_type
, CONSTANT_Class
);
1121 #include "jcf-reader.c"
1124 process_class (JCF
*jcf
)
1127 if (jcf_parse_preamble (jcf
) != 0)
1128 fprintf (stderr
, _("Not a valid Java .class file.\n"));
1130 /* Parse and possibly print constant pool */
1131 code
= jcf_parse_constant_pool (jcf
);
1134 fprintf (stderr
, _("error while parsing constant pool\n"));
1135 exit (FATAL_EXIT_CODE
);
1137 code
= verify_constant_pool (jcf
);
1140 fprintf (stderr
, _("error in constant pool entry #%d\n"), code
);
1141 exit (FATAL_EXIT_CODE
);
1143 if (flag_print_constant_pool
)
1144 print_constant_pool (jcf
);
1146 jcf_parse_class (jcf
);
1147 code
= jcf_parse_fields (jcf
);
1150 fprintf (stderr
, _("error while parsing fields\n"));
1151 exit (FATAL_EXIT_CODE
);
1153 code
= jcf_parse_methods (jcf
);
1156 fprintf (stderr
, _("error while parsing methods\n"));
1157 exit (FATAL_EXIT_CODE
);
1159 code
= jcf_parse_final_attributes (jcf
);
1162 fprintf (stderr
, _("error while parsing final attributes\n"));
1163 exit (FATAL_EXIT_CODE
);
1165 jcf
->filename
= NULL
;
1170 /* This is used to mark options with no short value. */
1171 #define LONG_OPT(Num) ((Num) + 128)
1173 #define OPT_classpath LONG_OPT (0)
1174 #define OPT_CLASSPATH OPT_classpath
1175 #define OPT_bootclasspath LONG_OPT (1)
1176 #define OPT_extdirs LONG_OPT (2)
1177 #define OPT_HELP LONG_OPT (3)
1178 #define OPT_VERSION LONG_OPT (4)
1179 #define OPT_JAVAP LONG_OPT (5)
1181 static const struct option options
[] =
1183 { "classpath", required_argument
, NULL
, OPT_classpath
},
1184 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
1185 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
1186 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
1187 { "help", no_argument
, NULL
, OPT_HELP
},
1188 { "verbose", no_argument
, NULL
, 'v' },
1189 { "version", no_argument
, NULL
, OPT_VERSION
},
1190 { "javap", no_argument
, NULL
, OPT_JAVAP
},
1191 { "print-main", no_argument
, &flag_print_main
, 1 },
1192 { "print-constants", no_argument
, &flag_print_constant_pool
, 1 },
1193 { NULL
, no_argument
, NULL
, 0 }
1199 fprintf (stderr
, _("Try 'jcf-dump --help' for more information.\n"));
1206 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
1207 printf (_("Display contents of a class file in readable form.\n\n"));
1208 printf (_(" -c Disassemble method bodies\n"));
1209 printf (_(" --javap Generate output in 'javap' format\n"));
1211 printf (_(" --classpath PATH Set path to find .class files\n"));
1212 printf (_(" -IDIR Append directory to class path\n"));
1213 printf (_(" --bootclasspath PATH Override built-in class path\n"));
1214 printf (_(" --extdirs PATH Set extensions directory path\n"));
1215 printf (_(" -o FILE Set output file name\n"));
1217 printf (_(" --help Print this help, then exit\n"));
1218 printf (_(" --version Print version number, then exit\n"));
1219 printf (_(" -v, --verbose Print extra information while running\n"));
1221 printf (_("For bug reporting instructions, please see:\n"
1222 "%s.\n"), bug_report_url
);
1229 printf ("jcf-dump %s%s\n\n", pkgversion_string
, version_string
);
1230 printf ("Copyright %s 2013 Free Software Foundation, Inc.\n", _("(C)"));
1231 printf (_("This is free software; see the source for copying conditions. There is NO\n"
1232 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
1237 main (int argc
, char** argv
)
1243 p
= argv
[0] + strlen (argv
[0]);
1244 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
1248 xmalloc_set_program_name (progname
);
1250 /* Unlock the stdio streams. */
1251 unlock_std_streams ();
1253 gcc_init_libintl ();
1255 diagnostic_initialize (global_dc
, 0);
1259 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1265 /* We use getopt_long_only to allow single `-' long options. For
1266 some of our options this is more natural. */
1267 while ((opt
= getopt_long_only (argc
, argv
, "o:I:vc", options
, NULL
)) != -1)
1272 /* Already handled. */
1276 output_file
= optarg
;
1280 jcf_path_include_arg (optarg
);
1288 flag_disassemble_methods
= 1;
1292 jcf_path_classpath_arg (optarg
);
1295 case OPT_bootclasspath
:
1296 jcf_path_bootclasspath_arg (optarg
);
1300 jcf_path_extdirs_arg (optarg
);
1312 flag_javap_compatible
++;
1313 flag_print_constant_pool
= 0;
1314 flag_print_attributes
= 0;
1322 if (verbose
&& ! flag_javap_compatible
)
1323 flag_print_constant_pool
= 1;
1327 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1331 jcf_path_seal (verbose
);
1333 if (flag_print_main
)
1335 flag_print_fields
= 0;
1336 flag_print_methods
= 0;
1337 flag_print_constant_pool
= 0;
1338 flag_print_attributes
= 0;
1339 flag_print_class_info
= 0;
1344 out
= fopen (output_file
, "w");
1347 fprintf (stderr
, _("Cannot open '%s' for output.\n"), output_file
);
1348 return FATAL_EXIT_CODE
;
1356 fprintf (out
, "Reading .class from <standard input>.\n");
1357 open_class ("<stdio>", jcf
, 0, NULL
);
1358 process_class (jcf
);
1362 for (argi
= optind
; argi
< argc
; argi
++)
1364 char *arg
= argv
[argi
];
1365 const char *class_filename
= find_class (arg
, strlen (arg
), jcf
);
1366 if (class_filename
== NULL
)
1367 class_filename
= find_classfile (arg
, jcf
, NULL
);
1368 if (class_filename
== NULL
)
1370 perror ("Could not find class");
1371 return FATAL_EXIT_CODE
;
1374 if (GET_u4 (jcf
->read_ptr
) == ZIPMAGIC
)
1376 long compressed_size
, member_size
;
1377 int compression_method
, filename_length
, extra_length
;
1378 const char *filename
;
1380 if (flag_print_class_info
)
1381 fprintf (out
, "Reading classes from archive %s.\n",
1386 jcf_filbuf_t save_filbuf
= jcf
->filbuf
;
1387 long magic
= JCF_readu4_le (jcf
);
1388 if (magic
== 0x02014b50 || magic
== 0x06054b50)
1389 break; /* got to central directory */
1390 if (magic
!= 0x04034b50) /* ZIPMAGIC (little-endian) */
1392 fprintf (stderr
, _("bad format of .zip/.jar archive\n"));
1393 return FATAL_EXIT_CODE
;
1397 (void) /* general_purpose_bits = */ JCF_readu2_le (jcf
);
1398 compression_method
= JCF_readu2_le (jcf
);
1400 compressed_size
= JCF_readu4_le (jcf
);
1401 member_size
= JCF_readu4_le (jcf
);
1402 filename_length
= JCF_readu2_le (jcf
);
1403 extra_length
= JCF_readu2_le (jcf
);
1404 total_length
= filename_length
+ extra_length
1406 if (jcf
->read_end
- jcf
->read_ptr
< total_length
)
1407 jcf_trim_old_input (jcf
);
1408 JCF_FILL (jcf
, total_length
);
1409 filename
= (const char *) jcf
->read_ptr
;
1410 JCF_SKIP (jcf
, filename_length
);
1411 JCF_SKIP (jcf
, extra_length
);
1412 if (filename_length
> 0
1413 && filename
[filename_length
-1] == '/')
1415 if (flag_print_class_info
)
1416 fprintf (out
, "[Skipping directory %.*s]\n",
1417 filename_length
, filename
);
1420 else if (compression_method
!= 0)
1422 if (flag_print_class_info
)
1423 fprintf (out
, "[Skipping compressed file %.*s]\n",
1424 filename_length
, filename
);
1427 else if (member_size
< 4
1428 || GET_u4 (jcf
->read_ptr
) != 0xcafebabe)
1430 if (flag_print_class_info
)
1431 fprintf (out
, "[Skipping non-.class member %.*s]\n",
1432 filename_length
, filename
);
1437 if (flag_print_class_info
)
1438 fprintf (out
, "Reading class member: %.*s.\n",
1439 filename_length
, filename
);
1443 JCF_SKIP (jcf
, compressed_size
);
1447 unsigned char *save_end
;
1448 jcf
->filbuf
= jcf_unexpected_eof
;
1449 save_end
= jcf
->read_end
;
1450 jcf
->read_end
= jcf
->read_ptr
+ compressed_size
;
1451 process_class (jcf
);
1452 jcf
->filbuf
= save_filbuf
;
1453 jcf
->read_end
= save_end
;
1459 if (flag_print_class_info
)
1460 fprintf (out
, "Reading .class from %s.\n", class_filename
);
1461 process_class (jcf
);
1467 return SUCCESS_EXIT_CODE
;
1473 disassemble_method (JCF
* jcf
, const unsigned char *byte_ops
, int len
)
1479 if (flag_disassemble_methods
== 0)
1481 #define BCODE byte_ops
1482 for (PC
= 0; PC
< len
;)
1487 switch (byte_ops
[PC
++])
1490 /* This is the actual code emitted for each of opcodes in javaops.def.
1491 The actual opcode-specific stuff is handled by the OPKIND macro.
1492 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1493 Those macros are defined below. The OPKINDs that do not have any
1494 inline parameters (such as BINOP) and therefore do mot need anything
1495 else to me printed out just use an empty body. */
1497 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1499 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1500 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1501 fputc ('\n', out); \
1504 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1505 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1506 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1507 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1509 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1510 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1512 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1513 These all push a constant onto the opcode stack. */
1514 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1515 saw_index = 0, i = (OPERAND_VALUE); \
1516 if (oldpc+1 == PC) /* nothing */; \
1517 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1518 else fprintf (out, " %d", i);
1520 /* Print out operand (a local variable index) for LOAD opcodes.
1521 These all push local variable onto the opcode stack. */
1522 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1523 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1525 /* Handle STORE opcodes same as LOAD opcodes.
1526 These all store a value from the opcode stack in a local variable. */
1529 /* Handle more kind of opcodes. */
1530 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1531 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1532 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1533 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1534 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1535 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1536 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1538 /* Handle putfield and getfield opcodes, with static versions. */
1539 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1540 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1542 /* Print operand for invoke opcodes. */
1543 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1544 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1545 if (OPERAND_VALUE) /* for invokeinterface */ \
1546 { int nargs = IMMEDIATE_u1; PC++; \
1547 fprintf (out, " nargs:%d", nargs); }
1549 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1550 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1552 #define ARRAY(OPERAND_TYPE, SUBOP) \
1553 ARRAY_##SUBOP(OPERAND_TYPE)
1554 /* Handle sub-categories of ARRAY opcodes. */
1555 #define ARRAY_LOAD(TYPE) /* nothing */
1556 #define ARRAY_STORE(TYPE) /* nothing */
1557 #define ARRAY_LENGTH(TYPE) /* nothing */
1558 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1559 #define ARRAY_NEW_NUM \
1560 INT_temp = IMMEDIATE_u1; \
1561 { switch ((int) INT_temp) { \
1562 case 4: fputs (" boolean", out); break; \
1563 case 5: fputs (" char", out); break; \
1564 case 6: fputs (" float", out); break; \
1565 case 7: fputs (" double", out); break; \
1566 case 8: fputs (" byte", out); break; \
1567 case 9: fputs (" short", out); break; \
1568 case 10: fputs (" int", out); break; \
1569 case 11: fputs (" long", out); break; \
1570 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1573 #define ARRAY_NEW_PTR \
1574 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1576 #define ARRAY_NEW_MULTI \
1577 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1578 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1580 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1581 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1583 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1584 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1585 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1587 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1588 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1589 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1591 #undef RET /* Defined by config/i386/i386.h */
1592 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1593 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1595 fprintf (out, " %ld", (long) INT_temp);
1597 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1598 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1600 #define LOOKUP_SWITCH \
1601 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1602 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1603 while (--npairs >= 0) { \
1604 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1605 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1608 #define TABLE_SWITCH \
1609 { jint default_offset = IMMEDIATE_s4; \
1610 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1611 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1612 (long) low, (long) high, (long) default_offset+oldpc); \
1613 for (; low <= high; low++) { \
1614 jint offset = IMMEDIATE_s4; \
1615 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1618 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1619 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1621 #define SPECIAL_IINC(OPERAND_TYPE) \
1622 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1623 fprintf (out, " %d", i); \
1624 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1626 fprintf (out, " %d", i)
1628 #define SPECIAL_WIDE(OPERAND_TYPE) \
1631 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1632 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1633 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1634 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1636 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1637 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1639 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1640 TEST(OPERAND_TYPE, OPERAND_VALUE)
1642 #include "javaop.def"
1645 if (oldpc
+1 == PC
) /* nothing - local index implied by opcode */;
1649 fprintf (out
, " %ld", (long) INT_temp
);
1655 fprintf (out
, "%3d: unknown(%3d)\n", oldpc
, byte_ops
[PC
]);