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)
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"
60 #include "java-tree.h"
69 /* Name of output file, if NULL if stdout. */
70 char *output_file
= NULL
;
74 int flag_disassemble_methods
= 0;
75 int flag_print_class_info
= 1;
76 int flag_print_constant_pool
= 0;
77 int flag_print_fields
= 1;
78 int flag_print_methods
= 1;
79 int flag_print_attributes
= 1;
81 /* Print names of classes that have a "main" method. */
82 int flag_print_main
= 0;
84 /* Index in constant pool of this class. */
85 int this_class_index
= 0;
87 int class_access_flags
= 0;
89 /* Print in format similar to javap. VERY INCOMPLETE. */
90 int flag_javap_compatible
= 0;
92 static void print_access_flags (FILE *, uint16
, char);
93 static void print_constant_terse (FILE*, JCF
*, int, int);
94 static void print_constant_terse_with_index (FILE *, JCF
*, int, int);
95 static void print_constant (FILE *, JCF
*, int, int);
96 static void print_constant_ref (FILE *, JCF
*, int);
97 static void disassemble_method (JCF
*, const unsigned char *, int);
98 static void print_name (FILE*, JCF
*, int);
99 static void print_signature (FILE*, JCF
*, int, int);
100 static int utf8_equal_string (struct JCF
*, int, const char *);
101 static void usage (void) ATTRIBUTE_NORETURN
;
102 static void help (void) ATTRIBUTE_NORETURN
;
103 static void version (void) ATTRIBUTE_NORETURN
;
104 static void process_class (struct JCF
*);
105 static void print_constant_pool (struct JCF
*);
106 static void print_exception_table (struct JCF
*, const unsigned char *entries
,
108 static void indent (FILE *, int);
109 static void print_element_value (FILE *, JCF
*, int);
110 static void print_annotation (FILE *, JCF
*, int);
111 static void print_annotations (FILE *, JCF
*, int);
112 static void print_parameter_annotations (FILE *, JCF
*, int);
114 #define PRINT_SIGNATURE_RESULT_ONLY 1
115 #define PRINT_SIGNATURE_ARGS_ONLY 2
118 utf8_equal_string (JCF
*jcf
, int index
, const char * value
)
120 if (CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
)
121 && JPOOL_TAG (jcf
, index
) == CONSTANT_Utf8
)
123 int len
= strlen (value
);
124 if (JPOOL_UTF_LENGTH (jcf
, index
) == len
125 && memcmp (JPOOL_UTF_DATA (jcf
, index
), value
, len
) == 0)
131 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
132 this_class_index = 0; \
133 if (flag_print_class_info) \
135 "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
136 (unsigned long) MAGIC, (long) MINOR, (long) MAJOR)
138 #define HANDLE_START_CONSTANT_POOL(COUNT) \
139 if (flag_print_constant_pool) \
140 fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
142 #define HANDLE_SOURCEFILE(INDEX) \
143 { fprintf (out, "Attribute "); \
144 print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
145 fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
146 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
148 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
149 this_class_index = THIS; \
150 class_access_flags = ACCESS_FLAGS; \
151 if (flag_print_class_info) \
152 { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
153 print_access_flags (out, ACCESS_FLAGS, 'c'); \
155 fprintf (out, "This class: "); \
156 print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
157 if (flag_print_constant_pool || SUPER != 0) \
158 fprintf (out, ", super: "); \
159 if (flag_print_constant_pool) \
161 fprintf (out, "%d", SUPER); \
166 print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
167 fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
170 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
171 (flag_print_attributes <= 0)
173 #define HANDLE_CLASS_INTERFACE(INDEX) \
174 if (flag_print_class_info) \
175 { fprintf (out, "- Implements: "); \
176 print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
179 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
180 if (flag_print_fields) \
181 fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
183 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
184 if (flag_print_fields) \
185 { fprintf (out, "Field name:"); \
186 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
187 print_access_flags (out, ACCESS_FLAGS, 'f'); \
188 fprintf (out, " Descriptor: "); \
189 if (flag_print_constant_pool) \
190 fprintf (out, "%d=", SIGNATURE); \
191 print_signature (out, jcf, SIGNATURE, 0); \
192 fputc ('\n', out); } \
194 flag_print_attributes--;
196 #define HANDLE_END_FIELD() \
197 if (! flag_print_fields) \
198 flag_print_attributes++;
200 #define HANDLE_START_METHODS(METHODS_COUNT) \
201 if (flag_print_methods) \
202 fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
204 flag_print_attributes--;
207 #define HANDLE_END_METHODS() \
208 if (! flag_print_methods) \
209 flag_print_attributes++;
211 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
213 if (flag_print_methods) \
215 if (flag_javap_compatible) \
217 fprintf (out, " "); \
218 print_access_flags (out, ACCESS_FLAGS, 'm'); \
220 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
222 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
223 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
228 fprintf (out, "\nMethod name:"); \
229 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
230 print_access_flags (out, ACCESS_FLAGS, 'm'); \
231 fprintf (out, " Descriptor: "); \
232 if (flag_print_constant_pool) \
233 fprintf (out, "%d=", SIGNATURE); \
234 print_signature (out, jcf, SIGNATURE, 0); \
238 if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
239 && utf8_equal_string (jcf, NAME, "main") \
240 && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
241 && this_class_index > 0 \
242 && (class_access_flags & ACC_PUBLIC)) \
244 print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
249 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
250 ( fprintf (out, "Attribute "), \
251 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
252 fprintf (out, ", length:%ld", (long) LENGTH) )
254 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
255 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
256 fprintf (out, ", value: "), \
257 print_constant_ref (out, jcf, VALUE_INDEX), \
258 fprintf (out, "\n") )
260 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
261 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
262 fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
263 (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
264 disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
266 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
267 print_exception_table (jcf, ENTRIES, COUNT)
269 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
270 { int n = (COUNT); int i; \
271 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
272 fprintf (out, ", count: %d\n", n); \
273 for (i = 0; i < n; i++) {\
274 int ex_index = JCF_readu2 (jcf); \
275 fprintf (out, "%3d: ", i); \
276 print_constant_ref (out, jcf, ex_index); \
277 fputc ('\n', out); } }
279 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
280 { int n = (COUNT); int i; \
281 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
282 fprintf (out, ", count: %d\n", n); \
283 for (i = 0; i < n; i++) {\
284 int start_pc = JCF_readu2 (jcf); \
285 int length = JCF_readu2 (jcf); \
286 int name_index = JCF_readu2 (jcf); \
287 int signature_index = JCF_readu2 (jcf); \
288 int slot = JCF_readu2 (jcf); \
289 fprintf (out, " slot#%d: name: ", slot); \
290 if (flag_print_constant_pool) \
291 fprintf (out, "%d=", name_index); \
292 print_name (out, jcf, name_index); \
293 fprintf (out, ", type: "); \
294 if (flag_print_constant_pool) \
295 fprintf (out, "%d=", signature_index); \
296 print_signature (out, jcf, signature_index, 0); \
297 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
299 #define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT) \
300 { int n = (COUNT); int i; \
301 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
302 fprintf (out, ", count: %d\n", n); \
303 for (i = 0; i < n; i++) { \
304 int start_pc = JCF_readu2 (jcf); \
305 int length = JCF_readu2 (jcf); \
306 int name_index = JCF_readu2 (jcf); \
307 int signature_index = JCF_readu2 (jcf); \
308 int slot = JCF_readu2 (jcf); \
309 fprintf (out, " slot#%d: name: ", slot); \
310 if (flag_print_constant_pool) \
311 fprintf (out, "%d=", name_index); \
312 print_name (out, jcf, name_index); \
313 fprintf (out, ", type: "); \
314 if (flag_print_constant_pool) \
315 fprintf (out, "%d=", signature_index); \
316 print_signature (out, jcf, signature_index, 0); \
317 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
319 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
320 { int n = (COUNT); int i; \
321 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
322 fprintf (out, ", count: %d\n", n); \
323 if (flag_disassemble_methods) \
324 for (i = 0; i < n; i++) {\
325 int start_pc = JCF_readu2 (jcf); \
326 int line_number = JCF_readu2 (jcf); \
327 fprintf (out, " line: %d at pc: %d\n", line_number, start_pc); }\
329 JCF_SKIP (jcf, 4 * n); }
331 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
333 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
336 uint16 inner_class_info_index = JCF_readu2 (jcf); \
337 uint16 outer_class_info_index = JCF_readu2 (jcf); \
338 uint16 inner_name_index = JCF_readu2 (jcf); \
339 uint16 inner_class_access_flags = JCF_readu2 (jcf); \
341 if (flag_print_class_info) \
343 fprintf (out, "\n inner: "); \
344 if (inner_class_info_index == 0) \
345 fprintf (out, " (no inner info index)"); \
347 print_constant_terse_with_index (out, jcf, \
348 inner_class_info_index, \
350 if (inner_name_index == 0) \
351 fprintf (out, " (anonymous)"); \
352 else if (verbose || flag_print_constant_pool) \
354 fprintf (out, " ("); \
355 print_constant_terse_with_index (out, jcf, inner_name_index, \
359 fprintf (out, ", access flags: 0x%x", inner_class_access_flags); \
360 print_access_flags (out, inner_class_access_flags, 'c'); \
361 fprintf (out, ", outer class: "); \
362 if (outer_class_info_index == 0) \
363 fprintf (out, "(not a member)"); \
365 print_constant_terse_with_index (out, jcf, \
366 outer_class_info_index, \
370 if (flag_print_class_info) \
374 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
375 { int i, n = (LENGTH), c = 0; \
376 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
378 for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
379 if (c != '\r' && c != '\n') fputc('\n', out); }
381 #define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE() \
382 { uint16 class_index, method_index; \
383 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
384 class_index = JCF_readu2 (jcf); \
385 method_index = JCF_readu2 (jcf); \
386 fprintf (out, "\n Class: "); \
387 print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
388 fprintf (out, "\n Method: "); \
389 print_constant_terse_with_index (out, jcf, method_index, \
390 CONSTANT_NameAndType); \
394 #define HANDLE_SIGNATURE_ATTRIBUTE() \
397 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
398 signature = JCF_readu2 (jcf); \
399 fprintf (out, "\n Value: "); \
400 print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8); \
404 #define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE() \
406 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
407 print_annotations (out, jcf, 1); \
410 #define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE() \
412 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
413 print_annotations (out, jcf, 1); \
416 #define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
418 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
419 print_parameter_annotations (out, jcf, 1); \
422 #define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
424 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
425 print_parameter_annotations (out, jcf, 1); \
428 #define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE() \
430 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
431 print_element_value (out, jcf, 1); \
434 #define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \
436 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
437 fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \
440 #define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \
443 for (i = 0; i < NUM_METHODS; i++) \
445 bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \
446 fprintf (out, " %d: ", i); \
447 print_constant (out, jcf, m->method_ref, 1); \
448 fprintf (out, "\n"); \
452 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
453 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
454 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
456 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
457 if (flag_print_attributes > 0) \
458 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
465 indent (FILE *stream
, int level
)
468 for (i
= 0; i
< level
; ++i
)
469 fprintf (stream
, " ");
473 print_element_value (FILE *stream
, JCF
*jcf
, int level
)
475 uint8 tag
= JCF_readu (jcf
);
476 indent (stream
, level
);
485 uint16 cindex
= JCF_readu2 (jcf
);
486 print_constant_terse_with_index (stream
, jcf
, cindex
,
492 uint16 cindex
= JCF_readu2 (jcf
);
493 print_constant_terse_with_index (stream
, jcf
, cindex
,
499 uint16 cindex
= JCF_readu2 (jcf
);
500 print_constant_terse_with_index (stream
, jcf
, cindex
,
506 uint16 cindex
= JCF_readu2 (jcf
);
507 print_constant_terse_with_index (stream
, jcf
, cindex
,
513 uint16 cindex
= JCF_readu2 (jcf
);
514 /* Despite what the JVM spec says, compilers generate a Utf8
515 constant here, not a String. */
516 print_constant_terse_with_index (stream
, jcf
, cindex
,
523 uint16 type_name_index
= JCF_readu2 (jcf
);
524 uint16 const_name_index
= JCF_readu2 (jcf
);
525 fprintf (stream
, "enum class: ");
526 print_constant_terse_with_index (stream
, jcf
, type_name_index
,
528 fprintf (stream
, "\n");
529 indent (stream
, level
);
530 fprintf (stream
, "Field: ");
531 print_constant_terse_with_index (stream
, jcf
, const_name_index
,
537 uint16 class_info_index
= JCF_readu2 (jcf
);
538 print_constant_terse_with_index (stream
, jcf
, class_info_index
,
544 fprintf (stream
, "Annotation:\n");
545 print_annotation (stream
, jcf
, level
+ 1);
550 uint16 n_array_elts
= JCF_readu2 (jcf
);
551 fprintf (stream
, "array[%d]: [\n", (int) n_array_elts
);
552 while (n_array_elts
--)
553 print_element_value (stream
, jcf
, level
+ 1);
554 indent (stream
, level
);
555 fprintf (stream
, "]");
559 fprintf (stream
, "Unexpected tag value: %d", (int) tag
);
562 fputc ('\n', stream
);
566 print_annotation (FILE *stream
, JCF
*jcf
, int level
)
568 uint16 type_index
= JCF_readu2 (jcf
);
569 uint16 npairs
= JCF_readu2 (jcf
);
570 fprintf (stream
, "\n");
571 indent (stream
, level
);
572 fprintf (stream
, "Annotation name: ");
573 print_constant_terse_with_index (stream
, jcf
, type_index
,
577 fprintf (stream
, "\n");
580 uint16 name_index
= JCF_readu2 (jcf
);
581 indent (stream
, level
+ 1);
582 fprintf (stream
, "Name: ");
583 print_constant_terse_with_index (stream
, jcf
, name_index
,
585 fprintf (stream
, "\n");
586 print_element_value (stream
, jcf
, level
+ 2);
592 print_annotations (FILE *stream
, JCF
*jcf
, int level
)
594 uint16 num
= JCF_readu2 (jcf
);
596 print_annotation (stream
, jcf
, level
);
600 print_parameter_annotations (FILE *stream
, JCF
*jcf
, int level
)
602 uint8 nparams
= JCF_readu (jcf
);
604 for (i
= 0; i
< nparams
; ++i
)
606 indent (stream
, level
);
607 fprintf (stream
, "Parameter annotations (%d):\n", (int) i
);
608 print_annotations (stream
, jcf
, level
+ 1);
615 print_constant_ref (FILE *stream
, JCF
*jcf
, int index
)
617 if (index
<= 0 || index
>= JPOOL_SIZE(jcf
))
618 fprintf (stream
, "<out of range>");
621 if (flag_print_constant_pool
)
622 fprintf (stream
, "#%d=", index
);
624 print_constant (stream
, jcf
, index
, 1);
629 /* Print the access flags given by FLAGS.
630 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
631 or 'm' (method flags). */
634 print_access_flags (FILE *stream
, uint16 flags
, char context
)
636 if (flags
& ACC_PUBLIC
) fprintf (stream
, " public");
637 if (flags
& ACC_PRIVATE
) fprintf (stream
, " private");
638 if (flags
& ACC_PROTECTED
) fprintf (stream
, " protected");
639 if (flags
& ACC_ABSTRACT
) fprintf (stream
, " abstract");
640 if (flags
& ACC_STATIC
) fprintf (stream
, " static");
641 if (flags
& ACC_FINAL
) fprintf (stream
, " final");
642 if (flags
& ACC_TRANSIENT
)
643 fprintf (stream
, context
== 'm' ? " varargs" : " transient");
644 if (flags
& ACC_VOLATILE
)
645 fprintf (stream
, context
== 'm' ? " bridge" : " volatile");
646 if (flags
& ACC_NATIVE
) fprintf (stream
, " native");
647 if (flags
& ACC_SYNCHRONIZED
)
650 fprintf (stream
, " super");
652 fprintf (stream
, " synchronized");
654 if (flags
& ACC_INTERFACE
)
655 fprintf (stream
, (flags
& ACC_ANNOTATION
) ? " @interface" : " interface");
656 if (flags
& ACC_ENUM
) fprintf (stream
, " enum");
657 if (flags
& ACC_STRICT
) fprintf (stream
, " strictfp");
658 if (flags
& ACC_SYNTHETIC
) fprintf (stream
, " synthetic");
663 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
665 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
666 fprintf (stream
, "<not a UTF8 constant>");
668 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
,name_index
),
669 JPOOL_UTF_LENGTH (jcf
, name_index
));
672 /* If the type of the constant at INDEX matches EXPECTED,
673 print it tersely, otherwise more verbosely. */
676 print_constant_terse (FILE *out
, JCF
*jcf
, int index
, int expected
)
678 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
))
679 fprintf (out
, "<constant pool index %d not in range>", index
);
680 else if (JPOOL_TAG (jcf
, index
) != expected
)
682 fprintf (out
, "<Unexpected constant type ");
683 print_constant (out
, jcf
, index
, 1);
687 print_constant (out
, jcf
, index
, 0);
691 print_constant_terse_with_index (FILE *out
, JCF
*jcf
, int index
, int expected
)
693 if (flag_print_constant_pool
)
694 fprintf (out
, "%d=", index
);
695 print_constant_terse (out
, jcf
, index
, expected
);
698 /* Print the constant at INDEX in JCF's constant pool.
699 If verbosity==0, print very tersely (no extraneous text).
700 If verbosity==1, prefix the type of the constant.
701 If verbosity==2, add more descriptive text. */
704 print_constant (FILE *out
, JCF
*jcf
, int index
, int verbosity
)
709 int kind
= JPOOL_TAG (jcf
, index
);
713 n
= JPOOL_USHORT1 (jcf
, index
);
717 fprintf (out
, "Class name: %d=", n
);
719 fprintf (out
, "Class ");
721 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, n
))
722 fprintf (out
, "<out of range>");
723 else if (verbosity
< 2 && JPOOL_TAG (jcf
, n
) == CONSTANT_Utf8
)
725 int len
= JPOOL_UTF_LENGTH (jcf
, n
);
726 jcf_print_utf8_replace (out
, JPOOL_UTF_DATA(jcf
,n
), len
, '/', '.');
729 print_constant_terse (out
, jcf
, n
, CONSTANT_Utf8
);
731 case CONSTANT_Fieldref
:
732 str
= "Field"; goto field_or_method
;
733 case CONSTANT_Methodref
:
734 str
= "Method"; goto field_or_method
;
735 case CONSTANT_InterfaceMethodref
:
736 str
= "InterfaceMethod"; goto field_or_method
;
739 uint16 tclass
= JPOOL_USHORT1 (jcf
, index
);
740 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
742 fprintf (out
, "%sref class: %d=", str
, tclass
);
743 else if (verbosity
> 0)
744 fprintf (out
, "%s ", str
);
745 print_constant_terse (out
, jcf
, tclass
, CONSTANT_Class
);
749 fprintf (out
, " name_and_type: %d=<", name_and_type
);
750 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
755 case CONSTANT_String
:
756 j
= JPOOL_USHORT1 (jcf
, index
);
760 fprintf (out
, "String %d=", j
);
762 fprintf (out
, "String ");
764 print_constant_terse (out
, jcf
, j
, CONSTANT_Utf8
);
766 case CONSTANT_Integer
:
768 fprintf (out
, "Integer ");
769 num
= JPOOL_INT (jcf
, index
);
773 fprintf (out
, "Long ");
774 num
= JPOOL_LONG (jcf
, index
);
779 format_int (buffer
, num
, 10);
780 fprintf (out
, "%s", buffer
);
783 format_uint (buffer
, (uint64
)num
, 16);
784 fprintf (out
, "=0x%s", buffer
);
790 jfloat fnum
= JPOOL_FLOAT (jcf
, index
);
793 fputs ("Float ", out
);
798 if (JFLOAT_FINITE (fnum
))
801 int exponent
= fnum
.exponent
- JFLOAT_EXP_BIAS
;
803 uint32 mantissa
= fnum
.mantissa
;
804 if (fnum
.exponent
== 0)
808 /* Normal; add the implicit bit. */
809 mantissa
|= ((uint32
)1 << 23);
811 f
= frexp ((float) mantissa
, &dummy
);
812 f
= ldexp (f
, exponent
+ 1);
813 fprintf (out
, "%.10g", f
);
817 if (fnum
.mantissa
== 0)
819 else if (fnum
.mantissa
& JFLOAT_QNAN_MASK
)
820 fprintf (out
, "QNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
822 fprintf (out
, "SNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
826 fprintf (out
, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf
, index
));
830 case CONSTANT_Double
:
832 jdouble dnum
= JPOOL_DOUBLE (jcf
, index
);
835 fputs ("Double ", out
);
840 if (JDOUBLE_FINITE (dnum
))
843 int exponent
= dnum
.exponent
- JDOUBLE_EXP_BIAS
;
845 uint64 mantissa
= ((((uint64
) dnum
.mantissa0
) << 32)
847 if (dnum
.exponent
== 0)
851 /* Normal; add the implicit bit. */
852 mantissa
|= ((uint64
)1 << 52);
854 d
= frexp ((double) mantissa
, &dummy
);
855 d
= ldexp (d
, exponent
+ 1);
856 fprintf (out
, "%.20g", d
);
860 uint64 mantissa
= dnum
.mantissa0
& ~JDOUBLE_QNAN_MASK
;
861 mantissa
= (mantissa
<< 32) + dnum
.mantissa1
;
863 if (dnum
.mantissa0
== 0 && dnum
.mantissa1
== 0)
865 else if (dnum
.mantissa0
& JDOUBLE_QNAN_MASK
)
866 fprintf (out
, "QNaN(%" HOST_LONG_LONG_FORMAT
"u)",
867 (unsigned long long)mantissa
);
869 fprintf (out
, "SNaN(%" HOST_LONG_LONG_FORMAT
"u)",
870 (unsigned long long)mantissa
);
875 hi
= JPOOL_UINT (jcf
, index
);
876 lo
= JPOOL_UINT (jcf
, index
+ 1);
877 fprintf (out
, ", bits = 0x%08lx%08lx", (unsigned long) hi
,
882 case CONSTANT_NameAndType
:
884 uint16 name
= JPOOL_USHORT1 (jcf
, index
);
885 uint16 sig
= JPOOL_USHORT2 (jcf
, index
);
889 fprintf (out
, "NameAndType name: %d=", name
);
891 fprintf (out
, "NameAndType ");
893 print_name (out
, jcf
, name
);
897 fprintf (out
, ", signature: %d=", sig
);
898 print_signature (out
, jcf
, sig
, 0);
903 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, index
);
904 int length
= JPOOL_UTF_LENGTH (jcf
, index
);
906 { /* Print as 8-bit bytes. */
907 fputs ("Utf8: \"", out
);
908 while (--length
>= 0)
909 jcf_print_char (out
, *str
++);
912 { /* Print as Unicode. */
914 jcf_print_utf8 (out
, str
, length
);
919 case CONSTANT_MethodHandle
:
921 int kind
= JPOOL_USHORT1 (jcf
, index
);
923 fprintf (out
, "MethodHandle kind: %d=", kind
);
930 fprintf (out
, "Fieldref: %ld=", (long) JPOOL_USHORT2 (jcf
, index
));
931 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
937 fprintf (out
, "Methodref: %ld=", (long) JPOOL_USHORT2 (jcf
, index
));
938 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
942 fprintf (out
, "InterfaceMethodref: %ld=",
943 (long) JPOOL_USHORT2 (jcf
, index
));
944 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
949 case CONSTANT_MethodType
:
951 fprintf (out
, "MethodType %ld: ", (long) JPOOL_USHORT1 (jcf
, index
));
952 print_signature (out
, jcf
, JPOOL_USHORT1 (jcf
, index
), 0);
954 case CONSTANT_InvokeDynamic
:
956 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
958 fprintf (out
, "InvokeDynamic: ");
959 fprintf (out
, "bootstrap_method: %ld ",
960 (long) JPOOL_USHORT1 (jcf
, index
));
962 fprintf (out
, " name_and_type: %d=<", name_and_type
);
963 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
969 fprintf (out
, "(Unknown constant type %d)", kind
);
974 print_constant_pool (JCF
*jcf
)
977 for (i
= 1; i
< JPOOL_SIZE(jcf
); i
++)
979 int kind
= JPOOL_TAG (jcf
, i
);
980 fprintf (out
, "#%d: ", i
);
981 print_constant (out
, jcf
, i
, 2);
983 if (kind
== CONSTANT_Double
|| kind
== CONSTANT_Long
)
984 i
++; /* These take up two slots in the constant table */
989 print_signature_type (FILE* stream
, const unsigned char **ptr
,
990 const unsigned char *limit
)
999 for ((*ptr
)++; (*ptr
) < limit
&& ISDIGIT (**ptr
); (*ptr
)++)
1001 array_size
= (array_size
< 0 ? 0 : 10 * array_size
) + *(*ptr
) - '0';
1003 print_signature_type (stream
, ptr
, limit
);
1004 if (array_size
== -1)
1005 fprintf (stream
, "[]");
1007 fprintf (stream
, "[%d]", array_size
);
1012 fputc (*(*ptr
)++, stream
);
1013 for (; **ptr
!= ')' && *ptr
< limit
; nargs
++)
1016 fputc (',', stream
);
1017 print_signature_type (stream
, ptr
, limit
);
1021 fputc (*(*ptr
)++, stream
);
1022 print_signature_type (stream
, ptr
, limit
);
1025 fprintf (stream
, "???");
1029 case 'B': fprintf (stream
, "byte"); (*ptr
)++; break;
1030 case 'C': fprintf (stream
, "char"); (*ptr
)++; break;
1031 case 'D': fprintf (stream
, "double"); (*ptr
)++; break;
1032 case 'F': fprintf (stream
, "float"); (*ptr
)++; break;
1033 case 'S': fprintf (stream
, "short"); (*ptr
)++; break;
1034 case 'I': fprintf (stream
, "int"); (*ptr
)++; break;
1035 case 'J': fprintf (stream
, "long"); (*ptr
)++; break;
1036 case 'Z': fprintf (stream
, "boolean"); (*ptr
)++; break;
1037 case 'V': fprintf (stream
, "void"); (*ptr
)++; break;
1040 for ((*ptr
)++; (*ptr
)<limit
&& *(*ptr
) != ';'; (*ptr
)++)
1041 jcf_print_char (stream
, *(*ptr
) == '/' ? '.' : *(*ptr
));
1046 jcf_print_char (stream
, *(*ptr
)++);
1051 print_signature (FILE* stream
, JCF
*jcf
, int signature_index
, int options
)
1053 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1054 print_constant_terse (out
, jcf
, signature_index
, CONSTANT_Utf8
);
1057 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, signature_index
);
1058 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1059 const unsigned char *limit
;
1060 limit
= str
+ length
;
1062 fprintf (stream
, "<empty signature string>");
1065 if (options
& PRINT_SIGNATURE_RESULT_ONLY
)
1067 while (str
< limit
&& *str
++ != ')') ;
1069 if (options
& PRINT_SIGNATURE_ARGS_ONLY
)
1072 fputc ('(', stream
);
1073 while (str
< limit
&& *str
!= ')')
1075 print_signature_type (stream
, &str
, limit
);
1077 fputs (", ", stream
);
1079 fputc (')', stream
);
1083 print_signature_type (stream
, &str
, limit
);
1086 fprintf (stream
, "<junk:");
1087 jcf_print_utf8 (stream
, str
, limit
- str
);
1088 fputc ('>', stream
);
1097 print_exception_table (JCF
*jcf
, const unsigned char *entries
, int count
)
1099 /* Print exception table. */
1103 const unsigned char *ptr
= entries
;
1104 fprintf (out
, "Exceptions (count: %d):\n", i
);
1105 for (; --i
>= 0; ptr
+= 8)
1107 int start_pc
= GET_u2 (ptr
);
1108 int end_pc
= GET_u2 (ptr
+2);
1109 int handler_pc
= GET_u2 (ptr
+4);
1110 int catch_type
= GET_u2 (ptr
+6);
1111 fprintf (out
, " start: %d, end: %d, handler: %d, type: ",
1112 start_pc
, end_pc
, handler_pc
);
1113 if (catch_type
== 0)
1114 fputs ("0 /* finally */", out
);
1116 print_constant_terse_with_index (out
, jcf
,
1117 catch_type
, CONSTANT_Class
);
1123 #include "jcf-reader.c"
1126 process_class (JCF
*jcf
)
1129 if (jcf_parse_preamble (jcf
) != 0)
1130 fprintf (stderr
, _("Not a valid Java .class file.\n"));
1132 /* Parse and possibly print constant pool */
1133 code
= jcf_parse_constant_pool (jcf
);
1136 fprintf (stderr
, _("error while parsing constant pool\n"));
1137 exit (FATAL_EXIT_CODE
);
1139 code
= verify_constant_pool (jcf
);
1142 fprintf (stderr
, _("error in constant pool entry #%d\n"), code
);
1143 exit (FATAL_EXIT_CODE
);
1145 if (flag_print_constant_pool
)
1146 print_constant_pool (jcf
);
1148 jcf_parse_class (jcf
);
1149 code
= jcf_parse_fields (jcf
);
1152 fprintf (stderr
, _("error while parsing fields\n"));
1153 exit (FATAL_EXIT_CODE
);
1155 code
= jcf_parse_methods (jcf
);
1158 fprintf (stderr
, _("error while parsing methods\n"));
1159 exit (FATAL_EXIT_CODE
);
1161 code
= jcf_parse_final_attributes (jcf
);
1164 fprintf (stderr
, _("error while parsing final attributes\n"));
1165 exit (FATAL_EXIT_CODE
);
1167 jcf
->filename
= NULL
;
1172 /* This is used to mark options with no short value. */
1173 #define LONG_OPT(Num) ((Num) + 128)
1175 #define OPT_classpath LONG_OPT (0)
1176 #define OPT_CLASSPATH OPT_classpath
1177 #define OPT_bootclasspath LONG_OPT (1)
1178 #define OPT_extdirs LONG_OPT (2)
1179 #define OPT_HELP LONG_OPT (3)
1180 #define OPT_VERSION LONG_OPT (4)
1181 #define OPT_JAVAP LONG_OPT (5)
1183 static const struct option options
[] =
1185 { "classpath", required_argument
, NULL
, OPT_classpath
},
1186 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
1187 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
1188 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
1189 { "help", no_argument
, NULL
, OPT_HELP
},
1190 { "verbose", no_argument
, NULL
, 'v' },
1191 { "version", no_argument
, NULL
, OPT_VERSION
},
1192 { "javap", no_argument
, NULL
, OPT_JAVAP
},
1193 { "print-main", no_argument
, &flag_print_main
, 1 },
1194 { "print-constants", no_argument
, &flag_print_constant_pool
, 1 },
1195 { NULL
, no_argument
, NULL
, 0 }
1201 fprintf (stderr
, _("Try 'jcf-dump --help' for more information.\n"));
1208 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
1209 printf (_("Display contents of a class file in readable form.\n\n"));
1210 printf (_(" -c Disassemble method bodies\n"));
1211 printf (_(" --javap Generate output in 'javap' format\n"));
1213 printf (_(" --classpath PATH Set path to find .class files\n"));
1214 printf (_(" -IDIR Append directory to class path\n"));
1215 printf (_(" --bootclasspath PATH Override built-in class path\n"));
1216 printf (_(" --extdirs PATH Set extensions directory path\n"));
1217 printf (_(" -o FILE Set output file name\n"));
1219 printf (_(" --help Print this help, then exit\n"));
1220 printf (_(" --version Print version number, then exit\n"));
1221 printf (_(" -v, --verbose Print extra information while running\n"));
1223 printf (_("For bug reporting instructions, please see:\n"
1224 "%s.\n"), bug_report_url
);
1231 printf ("jcf-dump %s%s\n\n", pkgversion_string
, version_string
);
1232 printf ("Copyright %s 2015 Free Software Foundation, Inc.\n", _("(C)"));
1233 printf (_("This is free software; see the source for copying conditions. There is NO\n"
1234 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
1239 main (int argc
, char** argv
)
1245 p
= argv
[0] + strlen (argv
[0]);
1246 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
1250 xmalloc_set_program_name (progname
);
1252 /* Unlock the stdio streams. */
1253 unlock_std_streams ();
1255 gcc_init_libintl ();
1257 diagnostic_initialize (global_dc
, 0);
1261 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1267 /* We use getopt_long_only to allow single `-' long options. For
1268 some of our options this is more natural. */
1269 while ((opt
= getopt_long_only (argc
, argv
, "o:I:vc", options
, NULL
)) != -1)
1274 /* Already handled. */
1278 output_file
= optarg
;
1282 jcf_path_include_arg (optarg
);
1290 flag_disassemble_methods
= 1;
1294 jcf_path_classpath_arg (optarg
);
1297 case OPT_bootclasspath
:
1298 jcf_path_bootclasspath_arg (optarg
);
1302 jcf_path_extdirs_arg (optarg
);
1314 flag_javap_compatible
++;
1315 flag_print_constant_pool
= 0;
1316 flag_print_attributes
= 0;
1324 if (verbose
&& ! flag_javap_compatible
)
1325 flag_print_constant_pool
= 1;
1329 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1333 jcf_path_seal (verbose
);
1335 if (flag_print_main
)
1337 flag_print_fields
= 0;
1338 flag_print_methods
= 0;
1339 flag_print_constant_pool
= 0;
1340 flag_print_attributes
= 0;
1341 flag_print_class_info
= 0;
1346 out
= fopen (output_file
, "w");
1349 fprintf (stderr
, _("Cannot open '%s' for output.\n"), output_file
);
1350 return FATAL_EXIT_CODE
;
1358 fprintf (out
, "Reading .class from <standard input>.\n");
1359 open_class ("<stdio>", jcf
, 0, NULL
);
1360 process_class (jcf
);
1364 for (argi
= optind
; argi
< argc
; argi
++)
1366 char *arg
= argv
[argi
];
1367 const char *class_filename
= find_class (arg
, strlen (arg
), jcf
);
1368 if (class_filename
== NULL
)
1369 class_filename
= find_classfile (arg
, jcf
, NULL
);
1370 if (class_filename
== NULL
)
1372 perror ("Could not find class");
1373 return FATAL_EXIT_CODE
;
1376 if (GET_u4 (jcf
->read_ptr
) == ZIPMAGIC
)
1378 long compressed_size
, member_size
;
1379 int compression_method
, filename_length
, extra_length
;
1380 const char *filename
;
1382 if (flag_print_class_info
)
1383 fprintf (out
, "Reading classes from archive %s.\n",
1388 jcf_filbuf_t save_filbuf
= jcf
->filbuf
;
1389 long magic
= JCF_readu4_le (jcf
);
1390 if (magic
== 0x02014b50 || magic
== 0x06054b50)
1391 break; /* got to central directory */
1392 if (magic
!= 0x04034b50) /* ZIPMAGIC (little-endian) */
1394 fprintf (stderr
, _("bad format of .zip/.jar archive\n"));
1395 return FATAL_EXIT_CODE
;
1399 (void) /* general_purpose_bits = */ JCF_readu2_le (jcf
);
1400 compression_method
= JCF_readu2_le (jcf
);
1402 compressed_size
= JCF_readu4_le (jcf
);
1403 member_size
= JCF_readu4_le (jcf
);
1404 filename_length
= JCF_readu2_le (jcf
);
1405 extra_length
= JCF_readu2_le (jcf
);
1406 total_length
= filename_length
+ extra_length
1408 if (jcf
->read_end
- jcf
->read_ptr
< total_length
)
1409 jcf_trim_old_input (jcf
);
1410 JCF_FILL (jcf
, total_length
);
1411 filename
= (const char *) jcf
->read_ptr
;
1412 JCF_SKIP (jcf
, filename_length
);
1413 JCF_SKIP (jcf
, extra_length
);
1414 if (filename_length
> 0
1415 && filename
[filename_length
-1] == '/')
1417 if (flag_print_class_info
)
1418 fprintf (out
, "[Skipping directory %.*s]\n",
1419 filename_length
, filename
);
1422 else if (compression_method
!= 0)
1424 if (flag_print_class_info
)
1425 fprintf (out
, "[Skipping compressed file %.*s]\n",
1426 filename_length
, filename
);
1429 else if (member_size
< 4
1430 || GET_u4 (jcf
->read_ptr
) != 0xcafebabe)
1432 if (flag_print_class_info
)
1433 fprintf (out
, "[Skipping non-.class member %.*s]\n",
1434 filename_length
, filename
);
1439 if (flag_print_class_info
)
1440 fprintf (out
, "Reading class member: %.*s.\n",
1441 filename_length
, filename
);
1445 JCF_SKIP (jcf
, compressed_size
);
1449 unsigned char *save_end
;
1450 jcf
->filbuf
= jcf_unexpected_eof
;
1451 save_end
= jcf
->read_end
;
1452 jcf
->read_end
= jcf
->read_ptr
+ compressed_size
;
1453 process_class (jcf
);
1454 jcf
->filbuf
= save_filbuf
;
1455 jcf
->read_end
= save_end
;
1461 if (flag_print_class_info
)
1462 fprintf (out
, "Reading .class from %s.\n", class_filename
);
1463 process_class (jcf
);
1469 return SUCCESS_EXIT_CODE
;
1475 disassemble_method (JCF
* jcf
, const unsigned char *byte_ops
, int len
)
1481 if (flag_disassemble_methods
== 0)
1483 #define BCODE byte_ops
1484 for (PC
= 0; PC
< len
;)
1489 switch (byte_ops
[PC
++])
1492 /* This is the actual code emitted for each of opcodes in javaops.def.
1493 The actual opcode-specific stuff is handled by the OPKIND macro.
1494 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1495 Those macros are defined below. The OPKINDs that do not have any
1496 inline parameters (such as BINOP) and therefore do mot need anything
1497 else to me printed out just use an empty body. */
1499 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1501 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1502 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1503 fputc ('\n', out); \
1506 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1507 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1508 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1509 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1511 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1512 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1514 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1515 These all push a constant onto the opcode stack. */
1516 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1517 saw_index = 0, i = (OPERAND_VALUE); \
1518 if (oldpc+1 == PC) /* nothing */; \
1519 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1520 else fprintf (out, " %d", i);
1522 /* Print out operand (a local variable index) for LOAD opcodes.
1523 These all push local variable onto the opcode stack. */
1524 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1525 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1527 /* Handle STORE opcodes same as LOAD opcodes.
1528 These all store a value from the opcode stack in a local variable. */
1531 /* Handle more kind of opcodes. */
1532 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1533 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1534 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1535 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1536 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1537 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1538 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1540 /* Handle putfield and getfield opcodes, with static versions. */
1541 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1542 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1544 /* Print operand for invoke opcodes. */
1545 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1546 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1547 if (OPERAND_VALUE) /* for invokeinterface */ \
1548 { int nargs = IMMEDIATE_u1; PC++; \
1549 fprintf (out, " nargs:%d", nargs); }
1551 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1552 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1554 #define ARRAY(OPERAND_TYPE, SUBOP) \
1555 ARRAY_##SUBOP(OPERAND_TYPE)
1556 /* Handle sub-categories of ARRAY opcodes. */
1557 #define ARRAY_LOAD(TYPE) /* nothing */
1558 #define ARRAY_STORE(TYPE) /* nothing */
1559 #define ARRAY_LENGTH(TYPE) /* nothing */
1560 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1561 #define ARRAY_NEW_NUM \
1562 INT_temp = IMMEDIATE_u1; \
1563 { switch ((int) INT_temp) { \
1564 case 4: fputs (" boolean", out); break; \
1565 case 5: fputs (" char", out); break; \
1566 case 6: fputs (" float", out); break; \
1567 case 7: fputs (" double", out); break; \
1568 case 8: fputs (" byte", out); break; \
1569 case 9: fputs (" short", out); break; \
1570 case 10: fputs (" int", out); break; \
1571 case 11: fputs (" long", out); break; \
1572 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1575 #define ARRAY_NEW_PTR \
1576 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1578 #define ARRAY_NEW_MULTI \
1579 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1580 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1582 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1583 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1585 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1586 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1587 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1589 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1590 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1591 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1593 #undef RET /* Defined by config/i386/i386.h */
1594 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1595 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1597 fprintf (out, " %ld", (long) INT_temp);
1599 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1600 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1602 #define LOOKUP_SWITCH \
1603 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1604 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1605 while (--npairs >= 0) { \
1606 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1607 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1610 #define TABLE_SWITCH \
1611 { jint default_offset = IMMEDIATE_s4; \
1612 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1613 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1614 (long) low, (long) high, (long) default_offset+oldpc); \
1615 for (; low <= high; low++) { \
1616 jint offset = IMMEDIATE_s4; \
1617 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1620 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1621 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1623 #define SPECIAL_IINC(OPERAND_TYPE) \
1624 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1625 fprintf (out, " %d", i); \
1626 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1628 fprintf (out, " %d", i)
1630 #define SPECIAL_WIDE(OPERAND_TYPE) \
1633 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1634 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1635 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1636 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1638 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1639 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1641 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1642 TEST(OPERAND_TYPE, OPERAND_VALUE)
1644 #include "javaop.def"
1647 if (oldpc
+1 == PC
) /* nothing - local index implied by opcode */;
1651 fprintf (out
, " %ld", (long) INT_temp
);
1657 fprintf (out
, "%3d: unknown(%3d)\n", oldpc
, byte_ops
[PC
]);