1 /* Program to dump out a Java(TM) .class file.
2 Functionally similar to Sun's javap.
4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>.
23 Java and all Java-based marks are trademarks or registered trademarks
24 of Sun Microsystems, Inc. in the United States and other countries.
25 The Free Software Foundation is independent of Sun Microsystems, Inc. */
27 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
30 jcf-dump is a program to print out the contents of class files.
31 Usage: jcf-dump [FLAGS] CLASS
33 + the name of a class in the CLASSPATH (e.g "java.lang.String"), or
34 + the name of a class *file* (e.g. "/home/me/work/package/Foo.class").
35 + The name of a .zip or .jar file (which prints all the classes in the
40 Dis-assemble each method.
44 Print nothing if there is no valid "main" method;
45 otherwise, print only the class name.
47 Print output in the style of Sun's javap program. VERY UNFINISHED.
53 #include "coretypes.h"
55 #include "diagnostic.h"
59 #include "java-tree.h"
68 /* Name of output file, if NULL if stdout. */
69 char *output_file
= NULL
;
73 int flag_disassemble_methods
= 0;
74 int flag_print_class_info
= 1;
75 int flag_print_constant_pool
= 0;
76 int flag_print_fields
= 1;
77 int flag_print_methods
= 1;
78 int flag_print_attributes
= 1;
80 /* Print names of classes that have a "main" method. */
81 int flag_print_main
= 0;
83 /* Index in constant pool of this class. */
84 int this_class_index
= 0;
86 int class_access_flags
= 0;
88 /* Print in format similar to javap. VERY INCOMPLETE. */
89 int flag_javap_compatible
= 0;
91 static void print_access_flags (FILE *, uint16
, char);
92 static void print_constant_terse (FILE*, JCF
*, int, int);
93 static void print_constant_terse_with_index (FILE *, JCF
*, int, int);
94 static void print_constant (FILE *, JCF
*, int, int);
95 static void print_constant_ref (FILE *, JCF
*, int);
96 static void disassemble_method (JCF
*, const unsigned char *, int);
97 static void print_name (FILE*, JCF
*, int);
98 static void print_signature (FILE*, JCF
*, int, int);
99 static int utf8_equal_string (struct JCF
*, int, const char *);
100 static void usage (void) ATTRIBUTE_NORETURN
;
101 static void help (void) ATTRIBUTE_NORETURN
;
102 static void version (void) ATTRIBUTE_NORETURN
;
103 static void process_class (struct JCF
*);
104 static void print_constant_pool (struct JCF
*);
105 static void print_exception_table (struct JCF
*, const unsigned char *entries
,
107 static void indent (FILE *, int);
108 static void print_element_value (FILE *, JCF
*, int);
109 static void print_annotation (FILE *, JCF
*, int);
110 static void print_annotations (FILE *, JCF
*, int);
111 static void print_parameter_annotations (FILE *, JCF
*, int);
113 #define PRINT_SIGNATURE_RESULT_ONLY 1
114 #define PRINT_SIGNATURE_ARGS_ONLY 2
117 utf8_equal_string (JCF
*jcf
, int index
, const char * value
)
119 if (CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
)
120 && JPOOL_TAG (jcf
, index
) == CONSTANT_Utf8
)
122 int len
= strlen (value
);
123 if (JPOOL_UTF_LENGTH (jcf
, index
) == len
124 && memcmp (JPOOL_UTF_DATA (jcf
, index
), value
, len
) == 0)
130 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
131 this_class_index = 0; \
132 if (flag_print_class_info) \
134 "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
135 (unsigned long) MAGIC, (long) MINOR, (long) MAJOR)
137 #define HANDLE_START_CONSTANT_POOL(COUNT) \
138 if (flag_print_constant_pool) \
139 fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
141 #define HANDLE_SOURCEFILE(INDEX) \
142 { fprintf (out, "Attribute "); \
143 print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
144 fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
145 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
147 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
148 this_class_index = THIS; \
149 class_access_flags = ACCESS_FLAGS; \
150 if (flag_print_class_info) \
151 { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
152 print_access_flags (out, ACCESS_FLAGS, 'c'); \
154 fprintf (out, "This class: "); \
155 print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
156 if (flag_print_constant_pool || SUPER != 0) \
157 fprintf (out, ", super: "); \
158 if (flag_print_constant_pool) \
160 fprintf (out, "%d", SUPER); \
165 print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
166 fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
169 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
170 (flag_print_attributes <= 0)
172 #define HANDLE_CLASS_INTERFACE(INDEX) \
173 if (flag_print_class_info) \
174 { fprintf (out, "- Implements: "); \
175 print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
178 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
179 if (flag_print_fields) \
180 fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
182 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
183 if (flag_print_fields) \
184 { fprintf (out, "Field name:"); \
185 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
186 print_access_flags (out, ACCESS_FLAGS, 'f'); \
187 fprintf (out, " Descriptor: "); \
188 if (flag_print_constant_pool) \
189 fprintf (out, "%d=", SIGNATURE); \
190 print_signature (out, jcf, SIGNATURE, 0); \
191 fputc ('\n', out); } \
193 flag_print_attributes--;
195 #define HANDLE_END_FIELD() \
196 if (! flag_print_fields) \
197 flag_print_attributes++;
199 #define HANDLE_START_METHODS(METHODS_COUNT) \
200 if (flag_print_methods) \
201 fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
203 flag_print_attributes--;
206 #define HANDLE_END_METHODS() \
207 if (! flag_print_methods) \
208 flag_print_attributes++;
210 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
212 if (flag_print_methods) \
214 if (flag_javap_compatible) \
216 fprintf (out, " "); \
217 print_access_flags (out, ACCESS_FLAGS, 'm'); \
219 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
221 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
222 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
227 fprintf (out, "\nMethod name:"); \
228 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
229 print_access_flags (out, ACCESS_FLAGS, 'm'); \
230 fprintf (out, " Descriptor: "); \
231 if (flag_print_constant_pool) \
232 fprintf (out, "%d=", SIGNATURE); \
233 print_signature (out, jcf, SIGNATURE, 0); \
237 if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
238 && utf8_equal_string (jcf, NAME, "main") \
239 && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
240 && this_class_index > 0 \
241 && (class_access_flags & ACC_PUBLIC)) \
243 print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
248 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
249 ( fprintf (out, "Attribute "), \
250 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
251 fprintf (out, ", length:%ld", (long) LENGTH) )
253 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
254 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
255 fprintf (out, ", value: "), \
256 print_constant_ref (out, jcf, VALUE_INDEX), \
257 fprintf (out, "\n") )
259 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
260 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
261 fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
262 (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
263 disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
265 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
266 print_exception_table (jcf, ENTRIES, COUNT)
268 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
269 { int n = (COUNT); int i; \
270 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
271 fprintf (out, ", count: %d\n", n); \
272 for (i = 0; i < n; i++) {\
273 int ex_index = JCF_readu2 (jcf); \
274 fprintf (out, "%3d: ", i); \
275 print_constant_ref (out, jcf, ex_index); \
276 fputc ('\n', out); } }
278 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
279 { int n = (COUNT); int i; \
280 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
281 fprintf (out, ", count: %d\n", n); \
282 for (i = 0; i < n; i++) {\
283 int start_pc = JCF_readu2 (jcf); \
284 int length = JCF_readu2 (jcf); \
285 int name_index = JCF_readu2 (jcf); \
286 int signature_index = JCF_readu2 (jcf); \
287 int slot = JCF_readu2 (jcf); \
288 fprintf (out, " slot#%d: name: ", slot); \
289 if (flag_print_constant_pool) \
290 fprintf (out, "%d=", name_index); \
291 print_name (out, jcf, name_index); \
292 fprintf (out, ", type: "); \
293 if (flag_print_constant_pool) \
294 fprintf (out, "%d=", signature_index); \
295 print_signature (out, jcf, signature_index, 0); \
296 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
298 #define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT) \
299 { int n = (COUNT); int i; \
300 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
301 fprintf (out, ", count: %d\n", n); \
302 for (i = 0; i < n; i++) { \
303 int start_pc = JCF_readu2 (jcf); \
304 int length = JCF_readu2 (jcf); \
305 int name_index = JCF_readu2 (jcf); \
306 int signature_index = JCF_readu2 (jcf); \
307 int slot = JCF_readu2 (jcf); \
308 fprintf (out, " slot#%d: name: ", slot); \
309 if (flag_print_constant_pool) \
310 fprintf (out, "%d=", name_index); \
311 print_name (out, jcf, name_index); \
312 fprintf (out, ", type: "); \
313 if (flag_print_constant_pool) \
314 fprintf (out, "%d=", signature_index); \
315 print_signature (out, jcf, signature_index, 0); \
316 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
318 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
319 { int n = (COUNT); int i; \
320 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
321 fprintf (out, ", count: %d\n", n); \
322 if (flag_disassemble_methods) \
323 for (i = 0; i < n; i++) {\
324 int start_pc = JCF_readu2 (jcf); \
325 int line_number = JCF_readu2 (jcf); \
326 fprintf (out, " line: %d at pc: %d\n", line_number, start_pc); }\
328 JCF_SKIP (jcf, 4 * n); }
330 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
332 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
335 uint16 inner_class_info_index = JCF_readu2 (jcf); \
336 uint16 outer_class_info_index = JCF_readu2 (jcf); \
337 uint16 inner_name_index = JCF_readu2 (jcf); \
338 uint16 inner_class_access_flags = JCF_readu2 (jcf); \
340 if (flag_print_class_info) \
342 fprintf (out, "\n inner: "); \
343 if (inner_class_info_index == 0) \
344 fprintf (out, " (no inner info index)"); \
346 print_constant_terse_with_index (out, jcf, \
347 inner_class_info_index, \
349 if (inner_name_index == 0) \
350 fprintf (out, " (anonymous)"); \
351 else if (verbose || flag_print_constant_pool) \
353 fprintf (out, " ("); \
354 print_constant_terse_with_index (out, jcf, inner_name_index, \
358 fprintf (out, ", access flags: 0x%x", inner_class_access_flags); \
359 print_access_flags (out, inner_class_access_flags, 'c'); \
360 fprintf (out, ", outer class: "); \
361 if (outer_class_info_index == 0) \
362 fprintf (out, "(not a member)"); \
364 print_constant_terse_with_index (out, jcf, \
365 outer_class_info_index, \
369 if (flag_print_class_info) \
373 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
374 { int i, n = (LENGTH), c = 0; \
375 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
377 for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
378 if (c != '\r' && c != '\n') fputc('\n', out); }
380 #define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE() \
381 { uint16 class_index, method_index; \
382 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
383 class_index = JCF_readu2 (jcf); \
384 method_index = JCF_readu2 (jcf); \
385 fprintf (out, "\n Class: "); \
386 print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
387 fprintf (out, "\n Method: "); \
388 print_constant_terse_with_index (out, jcf, method_index, \
389 CONSTANT_NameAndType); \
393 #define HANDLE_SIGNATURE_ATTRIBUTE() \
396 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
397 signature = JCF_readu2 (jcf); \
398 fprintf (out, "\n Value: "); \
399 print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8); \
403 #define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE() \
405 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
406 print_annotations (out, jcf, 1); \
409 #define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE() \
411 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
412 print_annotations (out, jcf, 1); \
415 #define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
417 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
418 print_parameter_annotations (out, jcf, 1); \
421 #define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
423 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
424 print_parameter_annotations (out, jcf, 1); \
427 #define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE() \
429 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
430 print_element_value (out, jcf, 1); \
433 #define HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE() \
435 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
436 fputc ('\n', out); jcf_parse_bootstrap_methods (jcf, attribute_length); \
439 #define HANDLE_END_BOOTSTRAP_METHODS(NUM_METHODS) \
442 for (i = 0; i < NUM_METHODS; i++) \
444 bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; \
445 fprintf (out, " %d: ", i); \
446 print_constant (out, jcf, m->method_ref, 1); \
447 fprintf (out, "\n"); \
451 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
452 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
453 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
455 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
456 if (flag_print_attributes > 0) \
457 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
464 indent (FILE *stream
, int level
)
467 for (i
= 0; i
< level
; ++i
)
468 fprintf (stream
, " ");
472 print_element_value (FILE *stream
, JCF
*jcf
, int level
)
474 uint8 tag
= JCF_readu (jcf
);
475 indent (stream
, level
);
484 uint16 cindex
= JCF_readu2 (jcf
);
485 print_constant_terse_with_index (stream
, jcf
, cindex
,
491 uint16 cindex
= JCF_readu2 (jcf
);
492 print_constant_terse_with_index (stream
, jcf
, cindex
,
498 uint16 cindex
= JCF_readu2 (jcf
);
499 print_constant_terse_with_index (stream
, jcf
, cindex
,
505 uint16 cindex
= JCF_readu2 (jcf
);
506 print_constant_terse_with_index (stream
, jcf
, cindex
,
512 uint16 cindex
= JCF_readu2 (jcf
);
513 /* Despite what the JVM spec says, compilers generate a Utf8
514 constant here, not a String. */
515 print_constant_terse_with_index (stream
, jcf
, cindex
,
522 uint16 type_name_index
= JCF_readu2 (jcf
);
523 uint16 const_name_index
= JCF_readu2 (jcf
);
524 fprintf (stream
, "enum class: ");
525 print_constant_terse_with_index (stream
, jcf
, type_name_index
,
527 fprintf (stream
, "\n");
528 indent (stream
, level
);
529 fprintf (stream
, "Field: ");
530 print_constant_terse_with_index (stream
, jcf
, const_name_index
,
536 uint16 class_info_index
= JCF_readu2 (jcf
);
537 print_constant_terse_with_index (stream
, jcf
, class_info_index
,
543 fprintf (stream
, "Annotation:\n");
544 print_annotation (stream
, jcf
, level
+ 1);
549 uint16 n_array_elts
= JCF_readu2 (jcf
);
550 fprintf (stream
, "array[%d]: [\n", (int) n_array_elts
);
551 while (n_array_elts
--)
552 print_element_value (stream
, jcf
, level
+ 1);
553 indent (stream
, level
);
554 fprintf (stream
, "]");
558 fprintf (stream
, "Unexpected tag value: %d", (int) tag
);
561 fputc ('\n', stream
);
565 print_annotation (FILE *stream
, JCF
*jcf
, int level
)
567 uint16 type_index
= JCF_readu2 (jcf
);
568 uint16 npairs
= JCF_readu2 (jcf
);
569 fprintf (stream
, "\n");
570 indent (stream
, level
);
571 fprintf (stream
, "Annotation name: ");
572 print_constant_terse_with_index (stream
, jcf
, type_index
,
576 fprintf (stream
, "\n");
579 uint16 name_index
= JCF_readu2 (jcf
);
580 indent (stream
, level
+ 1);
581 fprintf (stream
, "Name: ");
582 print_constant_terse_with_index (stream
, jcf
, name_index
,
584 fprintf (stream
, "\n");
585 print_element_value (stream
, jcf
, level
+ 2);
591 print_annotations (FILE *stream
, JCF
*jcf
, int level
)
593 uint16 num
= JCF_readu2 (jcf
);
595 print_annotation (stream
, jcf
, level
);
599 print_parameter_annotations (FILE *stream
, JCF
*jcf
, int level
)
601 uint8 nparams
= JCF_readu (jcf
);
603 for (i
= 0; i
< nparams
; ++i
)
605 indent (stream
, level
);
606 fprintf (stream
, "Parameter annotations (%d):\n", (int) i
);
607 print_annotations (stream
, jcf
, level
+ 1);
614 print_constant_ref (FILE *stream
, JCF
*jcf
, int index
)
616 if (index
<= 0 || index
>= JPOOL_SIZE(jcf
))
617 fprintf (stream
, "<out of range>");
620 if (flag_print_constant_pool
)
621 fprintf (stream
, "#%d=", index
);
623 print_constant (stream
, jcf
, index
, 1);
628 /* Print the access flags given by FLAGS.
629 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
630 or 'm' (method flags). */
633 print_access_flags (FILE *stream
, uint16 flags
, char context
)
635 if (flags
& ACC_PUBLIC
) fprintf (stream
, " public");
636 if (flags
& ACC_PRIVATE
) fprintf (stream
, " private");
637 if (flags
& ACC_PROTECTED
) fprintf (stream
, " protected");
638 if (flags
& ACC_ABSTRACT
) fprintf (stream
, " abstract");
639 if (flags
& ACC_STATIC
) fprintf (stream
, " static");
640 if (flags
& ACC_FINAL
) fprintf (stream
, " final");
641 if (flags
& ACC_TRANSIENT
)
642 fprintf (stream
, context
== 'm' ? " varargs" : " transient");
643 if (flags
& ACC_VOLATILE
)
644 fprintf (stream
, context
== 'm' ? " bridge" : " volatile");
645 if (flags
& ACC_NATIVE
) fprintf (stream
, " native");
646 if (flags
& ACC_SYNCHRONIZED
)
649 fprintf (stream
, " super");
651 fprintf (stream
, " synchronized");
653 if (flags
& ACC_INTERFACE
)
654 fprintf (stream
, (flags
& ACC_ANNOTATION
) ? " @interface" : " interface");
655 if (flags
& ACC_ENUM
) fprintf (stream
, " enum");
656 if (flags
& ACC_STRICT
) fprintf (stream
, " strictfp");
657 if (flags
& ACC_SYNTHETIC
) fprintf (stream
, " synthetic");
662 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
664 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
665 fprintf (stream
, "<not a UTF8 constant>");
667 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
,name_index
),
668 JPOOL_UTF_LENGTH (jcf
, name_index
));
671 /* If the type of the constant at INDEX matches EXPECTED,
672 print it tersely, otherwise more verbosely. */
675 print_constant_terse (FILE *out
, JCF
*jcf
, int index
, int expected
)
677 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
))
678 fprintf (out
, "<constant pool index %d not in range>", index
);
679 else if (JPOOL_TAG (jcf
, index
) != expected
)
681 fprintf (out
, "<Unexpected constant type ");
682 print_constant (out
, jcf
, index
, 1);
686 print_constant (out
, jcf
, index
, 0);
690 print_constant_terse_with_index (FILE *out
, JCF
*jcf
, int index
, int expected
)
692 if (flag_print_constant_pool
)
693 fprintf (out
, "%d=", index
);
694 print_constant_terse (out
, jcf
, index
, expected
);
697 /* Print the constant at INDEX in JCF's constant pool.
698 If verbosity==0, print very tersely (no extraneous text).
699 If verbosity==1, prefix the type of the constant.
700 If verbosity==2, add more descriptive text. */
703 print_constant (FILE *out
, JCF
*jcf
, int index
, int verbosity
)
708 int kind
= JPOOL_TAG (jcf
, index
);
712 n
= JPOOL_USHORT1 (jcf
, index
);
716 fprintf (out
, "Class name: %d=", n
);
718 fprintf (out
, "Class ");
720 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, n
))
721 fprintf (out
, "<out of range>");
722 else if (verbosity
< 2 && JPOOL_TAG (jcf
, n
) == CONSTANT_Utf8
)
724 int len
= JPOOL_UTF_LENGTH (jcf
, n
);
725 jcf_print_utf8_replace (out
, JPOOL_UTF_DATA(jcf
,n
), len
, '/', '.');
728 print_constant_terse (out
, jcf
, n
, CONSTANT_Utf8
);
730 case CONSTANT_Fieldref
:
731 str
= "Field"; goto field_or_method
;
732 case CONSTANT_Methodref
:
733 str
= "Method"; goto field_or_method
;
734 case CONSTANT_InterfaceMethodref
:
735 str
= "InterfaceMethod"; goto field_or_method
;
738 uint16 tclass
= JPOOL_USHORT1 (jcf
, index
);
739 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
741 fprintf (out
, "%sref class: %d=", str
, tclass
);
742 else if (verbosity
> 0)
743 fprintf (out
, "%s ", str
);
744 print_constant_terse (out
, jcf
, tclass
, CONSTANT_Class
);
748 fprintf (out
, " name_and_type: %d=<", name_and_type
);
749 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
754 case CONSTANT_String
:
755 j
= JPOOL_USHORT1 (jcf
, index
);
759 fprintf (out
, "String %d=", j
);
761 fprintf (out
, "String ");
763 print_constant_terse (out
, jcf
, j
, CONSTANT_Utf8
);
765 case CONSTANT_Integer
:
767 fprintf (out
, "Integer ");
768 num
= JPOOL_INT (jcf
, index
);
772 fprintf (out
, "Long ");
773 num
= JPOOL_LONG (jcf
, index
);
778 format_int (buffer
, num
, 10);
779 fprintf (out
, "%s", buffer
);
782 format_uint (buffer
, (uint64
)num
, 16);
783 fprintf (out
, "=0x%s", buffer
);
789 jfloat fnum
= JPOOL_FLOAT (jcf
, index
);
792 fputs ("Float ", out
);
797 if (JFLOAT_FINITE (fnum
))
800 int exponent
= fnum
.exponent
- JFLOAT_EXP_BIAS
;
802 uint32 mantissa
= fnum
.mantissa
;
803 if (fnum
.exponent
== 0)
807 /* Normal; add the implicit bit. */
808 mantissa
|= ((uint32
)1 << 23);
810 f
= frexp ((float) mantissa
, &dummy
);
811 f
= ldexp (f
, exponent
+ 1);
812 fprintf (out
, "%.10g", f
);
816 if (fnum
.mantissa
== 0)
818 else if (fnum
.mantissa
& JFLOAT_QNAN_MASK
)
819 fprintf (out
, "QNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
821 fprintf (out
, "SNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
825 fprintf (out
, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf
, index
));
829 case CONSTANT_Double
:
831 jdouble dnum
= JPOOL_DOUBLE (jcf
, index
);
834 fputs ("Double ", out
);
839 if (JDOUBLE_FINITE (dnum
))
842 int exponent
= dnum
.exponent
- JDOUBLE_EXP_BIAS
;
844 uint64 mantissa
= ((((uint64
) dnum
.mantissa0
) << 32)
846 if (dnum
.exponent
== 0)
850 /* Normal; add the implicit bit. */
851 mantissa
|= ((uint64
)1 << 52);
853 d
= frexp ((double) mantissa
, &dummy
);
854 d
= ldexp (d
, exponent
+ 1);
855 fprintf (out
, "%.20g", d
);
859 uint64 mantissa
= dnum
.mantissa0
& ~JDOUBLE_QNAN_MASK
;
860 mantissa
= (mantissa
<< 32) + dnum
.mantissa1
;
862 if (dnum
.mantissa0
== 0 && dnum
.mantissa1
== 0)
864 else if (dnum
.mantissa0
& JDOUBLE_QNAN_MASK
)
865 fprintf (out
, "QNaN(%" HOST_LONG_LONG_FORMAT
"u)",
866 (unsigned long long)mantissa
);
868 fprintf (out
, "SNaN(%" HOST_LONG_LONG_FORMAT
"u)",
869 (unsigned long long)mantissa
);
874 hi
= JPOOL_UINT (jcf
, index
);
875 lo
= JPOOL_UINT (jcf
, index
+ 1);
876 fprintf (out
, ", bits = 0x%08lx%08lx", (unsigned long) hi
,
881 case CONSTANT_NameAndType
:
883 uint16 name
= JPOOL_USHORT1 (jcf
, index
);
884 uint16 sig
= JPOOL_USHORT2 (jcf
, index
);
888 fprintf (out
, "NameAndType name: %d=", name
);
890 fprintf (out
, "NameAndType ");
892 print_name (out
, jcf
, name
);
896 fprintf (out
, ", signature: %d=", sig
);
897 print_signature (out
, jcf
, sig
, 0);
902 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, index
);
903 int length
= JPOOL_UTF_LENGTH (jcf
, index
);
905 { /* Print as 8-bit bytes. */
906 fputs ("Utf8: \"", out
);
907 while (--length
>= 0)
908 jcf_print_char (out
, *str
++);
911 { /* Print as Unicode. */
913 jcf_print_utf8 (out
, str
, length
);
918 case CONSTANT_MethodHandle
:
920 int kind
= JPOOL_USHORT1 (jcf
, index
);
922 fprintf (out
, "MethodHandle kind: %d=", kind
);
929 fprintf (out
, "Fieldref: %ld=", (long) JPOOL_USHORT2 (jcf
, index
));
930 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
936 fprintf (out
, "Methodref: %ld=", (long) JPOOL_USHORT2 (jcf
, index
));
937 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
941 fprintf (out
, "InterfaceMethodref: %ld=",
942 (long) JPOOL_USHORT2 (jcf
, index
));
943 print_constant (out
, jcf
, JPOOL_USHORT2 (jcf
, index
), 0);
948 case CONSTANT_MethodType
:
950 fprintf (out
, "MethodType %ld: ", (long) JPOOL_USHORT1 (jcf
, index
));
951 print_signature (out
, jcf
, JPOOL_USHORT1 (jcf
, index
), 0);
953 case CONSTANT_InvokeDynamic
:
955 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
957 fprintf (out
, "InvokeDynamic: ");
958 fprintf (out
, "bootstrap_method: %ld ",
959 (long) JPOOL_USHORT1 (jcf
, index
));
961 fprintf (out
, " name_and_type: %d=<", name_and_type
);
962 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
968 fprintf (out
, "(Unknown constant type %d)", kind
);
973 print_constant_pool (JCF
*jcf
)
976 for (i
= 1; i
< JPOOL_SIZE(jcf
); i
++)
978 int kind
= JPOOL_TAG (jcf
, i
);
979 fprintf (out
, "#%d: ", i
);
980 print_constant (out
, jcf
, i
, 2);
982 if (kind
== CONSTANT_Double
|| kind
== CONSTANT_Long
)
983 i
++; /* These take up two slots in the constant table */
988 print_signature_type (FILE* stream
, const unsigned char **ptr
,
989 const unsigned char *limit
)
998 for ((*ptr
)++; (*ptr
) < limit
&& ISDIGIT (**ptr
); (*ptr
)++)
1000 array_size
= (array_size
< 0 ? 0 : 10 * array_size
) + *(*ptr
) - '0';
1002 print_signature_type (stream
, ptr
, limit
);
1003 if (array_size
== -1)
1004 fprintf (stream
, "[]");
1006 fprintf (stream
, "[%d]", array_size
);
1011 fputc (*(*ptr
)++, stream
);
1012 for (; **ptr
!= ')' && *ptr
< limit
; nargs
++)
1015 fputc (',', stream
);
1016 print_signature_type (stream
, ptr
, limit
);
1020 fputc (*(*ptr
)++, stream
);
1021 print_signature_type (stream
, ptr
, limit
);
1024 fprintf (stream
, "???");
1028 case 'B': fprintf (stream
, "byte"); (*ptr
)++; break;
1029 case 'C': fprintf (stream
, "char"); (*ptr
)++; break;
1030 case 'D': fprintf (stream
, "double"); (*ptr
)++; break;
1031 case 'F': fprintf (stream
, "float"); (*ptr
)++; break;
1032 case 'S': fprintf (stream
, "short"); (*ptr
)++; break;
1033 case 'I': fprintf (stream
, "int"); (*ptr
)++; break;
1034 case 'J': fprintf (stream
, "long"); (*ptr
)++; break;
1035 case 'Z': fprintf (stream
, "boolean"); (*ptr
)++; break;
1036 case 'V': fprintf (stream
, "void"); (*ptr
)++; break;
1039 for ((*ptr
)++; (*ptr
)<limit
&& *(*ptr
) != ';'; (*ptr
)++)
1040 jcf_print_char (stream
, *(*ptr
) == '/' ? '.' : *(*ptr
));
1045 jcf_print_char (stream
, *(*ptr
)++);
1050 print_signature (FILE* stream
, JCF
*jcf
, int signature_index
, int options
)
1052 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1053 print_constant_terse (out
, jcf
, signature_index
, CONSTANT_Utf8
);
1056 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, signature_index
);
1057 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1058 const unsigned char *limit
;
1059 limit
= str
+ length
;
1061 fprintf (stream
, "<empty signature string>");
1064 if (options
& PRINT_SIGNATURE_RESULT_ONLY
)
1066 while (str
< limit
&& *str
++ != ')') ;
1068 if (options
& PRINT_SIGNATURE_ARGS_ONLY
)
1071 fputc ('(', stream
);
1072 while (str
< limit
&& *str
!= ')')
1074 print_signature_type (stream
, &str
, limit
);
1076 fputs (", ", stream
);
1078 fputc (')', stream
);
1082 print_signature_type (stream
, &str
, limit
);
1085 fprintf (stream
, "<junk:");
1086 jcf_print_utf8 (stream
, str
, limit
- str
);
1087 fputc ('>', stream
);
1096 print_exception_table (JCF
*jcf
, const unsigned char *entries
, int count
)
1098 /* Print exception table. */
1102 const unsigned char *ptr
= entries
;
1103 fprintf (out
, "Exceptions (count: %d):\n", i
);
1104 for (; --i
>= 0; ptr
+= 8)
1106 int start_pc
= GET_u2 (ptr
);
1107 int end_pc
= GET_u2 (ptr
+2);
1108 int handler_pc
= GET_u2 (ptr
+4);
1109 int catch_type
= GET_u2 (ptr
+6);
1110 fprintf (out
, " start: %d, end: %d, handler: %d, type: ",
1111 start_pc
, end_pc
, handler_pc
);
1112 if (catch_type
== 0)
1113 fputs ("0 /* finally */", out
);
1115 print_constant_terse_with_index (out
, jcf
,
1116 catch_type
, CONSTANT_Class
);
1122 #include "jcf-reader.c"
1125 process_class (JCF
*jcf
)
1128 if (jcf_parse_preamble (jcf
) != 0)
1129 fprintf (stderr
, _("Not a valid Java .class file.\n"));
1131 /* Parse and possibly print constant pool */
1132 code
= jcf_parse_constant_pool (jcf
);
1135 fprintf (stderr
, _("error while parsing constant pool\n"));
1136 exit (FATAL_EXIT_CODE
);
1138 code
= verify_constant_pool (jcf
);
1141 fprintf (stderr
, _("error in constant pool entry #%d\n"), code
);
1142 exit (FATAL_EXIT_CODE
);
1144 if (flag_print_constant_pool
)
1145 print_constant_pool (jcf
);
1147 jcf_parse_class (jcf
);
1148 code
= jcf_parse_fields (jcf
);
1151 fprintf (stderr
, _("error while parsing fields\n"));
1152 exit (FATAL_EXIT_CODE
);
1154 code
= jcf_parse_methods (jcf
);
1157 fprintf (stderr
, _("error while parsing methods\n"));
1158 exit (FATAL_EXIT_CODE
);
1160 code
= jcf_parse_final_attributes (jcf
);
1163 fprintf (stderr
, _("error while parsing final attributes\n"));
1164 exit (FATAL_EXIT_CODE
);
1166 jcf
->filename
= NULL
;
1171 /* This is used to mark options with no short value. */
1172 #define LONG_OPT(Num) ((Num) + 128)
1174 #define OPT_classpath LONG_OPT (0)
1175 #define OPT_CLASSPATH OPT_classpath
1176 #define OPT_bootclasspath LONG_OPT (1)
1177 #define OPT_extdirs LONG_OPT (2)
1178 #define OPT_HELP LONG_OPT (3)
1179 #define OPT_VERSION LONG_OPT (4)
1180 #define OPT_JAVAP LONG_OPT (5)
1182 static const struct option options
[] =
1184 { "classpath", required_argument
, NULL
, OPT_classpath
},
1185 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
1186 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
1187 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
1188 { "help", no_argument
, NULL
, OPT_HELP
},
1189 { "verbose", no_argument
, NULL
, 'v' },
1190 { "version", no_argument
, NULL
, OPT_VERSION
},
1191 { "javap", no_argument
, NULL
, OPT_JAVAP
},
1192 { "print-main", no_argument
, &flag_print_main
, 1 },
1193 { "print-constants", no_argument
, &flag_print_constant_pool
, 1 },
1194 { NULL
, no_argument
, NULL
, 0 }
1200 fprintf (stderr
, _("Try 'jcf-dump --help' for more information.\n"));
1207 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
1208 printf (_("Display contents of a class file in readable form.\n\n"));
1209 printf (_(" -c Disassemble method bodies\n"));
1210 printf (_(" --javap Generate output in 'javap' format\n"));
1212 printf (_(" --classpath PATH Set path to find .class files\n"));
1213 printf (_(" -IDIR Append directory to class path\n"));
1214 printf (_(" --bootclasspath PATH Override built-in class path\n"));
1215 printf (_(" --extdirs PATH Set extensions directory path\n"));
1216 printf (_(" -o FILE Set output file name\n"));
1218 printf (_(" --help Print this help, then exit\n"));
1219 printf (_(" --version Print version number, then exit\n"));
1220 printf (_(" -v, --verbose Print extra information while running\n"));
1222 printf (_("For bug reporting instructions, please see:\n"
1223 "%s.\n"), bug_report_url
);
1230 printf ("jcf-dump %s%s\n\n", pkgversion_string
, version_string
);
1231 printf ("Copyright %s 2012 Free Software Foundation, Inc.\n", _("(C)"));
1232 printf (_("This is free software; see the source for copying conditions. There is NO\n"
1233 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
1238 main (int argc
, char** argv
)
1244 p
= argv
[0] + strlen (argv
[0]);
1245 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
1249 xmalloc_set_program_name (progname
);
1251 /* Unlock the stdio streams. */
1252 unlock_std_streams ();
1254 gcc_init_libintl ();
1256 diagnostic_initialize (global_dc
, 0);
1260 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1266 /* We use getopt_long_only to allow single `-' long options. For
1267 some of our options this is more natural. */
1268 while ((opt
= getopt_long_only (argc
, argv
, "o:I:vc", options
, NULL
)) != -1)
1273 /* Already handled. */
1277 output_file
= optarg
;
1281 jcf_path_include_arg (optarg
);
1289 flag_disassemble_methods
= 1;
1293 jcf_path_classpath_arg (optarg
);
1296 case OPT_bootclasspath
:
1297 jcf_path_bootclasspath_arg (optarg
);
1301 jcf_path_extdirs_arg (optarg
);
1313 flag_javap_compatible
++;
1314 flag_print_constant_pool
= 0;
1315 flag_print_attributes
= 0;
1323 if (verbose
&& ! flag_javap_compatible
)
1324 flag_print_constant_pool
= 1;
1328 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1332 jcf_path_seal (verbose
);
1334 if (flag_print_main
)
1336 flag_print_fields
= 0;
1337 flag_print_methods
= 0;
1338 flag_print_constant_pool
= 0;
1339 flag_print_attributes
= 0;
1340 flag_print_class_info
= 0;
1345 out
= fopen (output_file
, "w");
1348 fprintf (stderr
, _("Cannot open '%s' for output.\n"), output_file
);
1349 return FATAL_EXIT_CODE
;
1357 fprintf (out
, "Reading .class from <standard input>.\n");
1358 open_class ("<stdio>", jcf
, 0, NULL
);
1359 process_class (jcf
);
1363 for (argi
= optind
; argi
< argc
; argi
++)
1365 char *arg
= argv
[argi
];
1366 const char *class_filename
= find_class (arg
, strlen (arg
), jcf
);
1367 if (class_filename
== NULL
)
1368 class_filename
= find_classfile (arg
, jcf
, NULL
);
1369 if (class_filename
== NULL
)
1371 perror ("Could not find class");
1372 return FATAL_EXIT_CODE
;
1375 if (GET_u4 (jcf
->read_ptr
) == ZIPMAGIC
)
1377 long compressed_size
, member_size
;
1378 int compression_method
, filename_length
, extra_length
;
1379 const char *filename
;
1381 if (flag_print_class_info
)
1382 fprintf (out
, "Reading classes from archive %s.\n",
1387 jcf_filbuf_t save_filbuf
= jcf
->filbuf
;
1388 long magic
= JCF_readu4_le (jcf
);
1389 if (magic
== 0x02014b50 || magic
== 0x06054b50)
1390 break; /* got to central directory */
1391 if (magic
!= 0x04034b50) /* ZIPMAGIC (little-endian) */
1393 fprintf (stderr
, _("bad format of .zip/.jar archive\n"));
1394 return FATAL_EXIT_CODE
;
1398 (void) /* general_purpose_bits = */ JCF_readu2_le (jcf
);
1399 compression_method
= JCF_readu2_le (jcf
);
1401 compressed_size
= JCF_readu4_le (jcf
);
1402 member_size
= JCF_readu4_le (jcf
);
1403 filename_length
= JCF_readu2_le (jcf
);
1404 extra_length
= JCF_readu2_le (jcf
);
1405 total_length
= filename_length
+ extra_length
1407 if (jcf
->read_end
- jcf
->read_ptr
< total_length
)
1408 jcf_trim_old_input (jcf
);
1409 JCF_FILL (jcf
, total_length
);
1410 filename
= (const char *) jcf
->read_ptr
;
1411 JCF_SKIP (jcf
, filename_length
);
1412 JCF_SKIP (jcf
, extra_length
);
1413 if (filename_length
> 0
1414 && filename
[filename_length
-1] == '/')
1416 if (flag_print_class_info
)
1417 fprintf (out
, "[Skipping directory %.*s]\n",
1418 filename_length
, filename
);
1421 else if (compression_method
!= 0)
1423 if (flag_print_class_info
)
1424 fprintf (out
, "[Skipping compressed file %.*s]\n",
1425 filename_length
, filename
);
1428 else if (member_size
< 4
1429 || GET_u4 (jcf
->read_ptr
) != 0xcafebabe)
1431 if (flag_print_class_info
)
1432 fprintf (out
, "[Skipping non-.class member %.*s]\n",
1433 filename_length
, filename
);
1438 if (flag_print_class_info
)
1439 fprintf (out
, "Reading class member: %.*s.\n",
1440 filename_length
, filename
);
1444 JCF_SKIP (jcf
, compressed_size
);
1448 unsigned char *save_end
;
1449 jcf
->filbuf
= jcf_unexpected_eof
;
1450 save_end
= jcf
->read_end
;
1451 jcf
->read_end
= jcf
->read_ptr
+ compressed_size
;
1452 process_class (jcf
);
1453 jcf
->filbuf
= save_filbuf
;
1454 jcf
->read_end
= save_end
;
1460 if (flag_print_class_info
)
1461 fprintf (out
, "Reading .class from %s.\n", class_filename
);
1462 process_class (jcf
);
1468 return SUCCESS_EXIT_CODE
;
1474 disassemble_method (JCF
* jcf
, const unsigned char *byte_ops
, int len
)
1480 if (flag_disassemble_methods
== 0)
1482 #define BCODE byte_ops
1483 for (PC
= 0; PC
< len
;)
1488 switch (byte_ops
[PC
++])
1491 /* This is the actual code emitted for each of opcodes in javaops.def.
1492 The actual opcode-specific stuff is handled by the OPKIND macro.
1493 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1494 Those macros are defined below. The OPKINDs that do not have any
1495 inline parameters (such as BINOP) and therefore do mot need anything
1496 else to me printed out just use an empty body. */
1498 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1500 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1501 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1502 fputc ('\n', out); \
1505 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1506 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1507 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1508 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1510 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1511 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1513 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1514 These all push a constant onto the opcode stack. */
1515 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1516 saw_index = 0, i = (OPERAND_VALUE); \
1517 if (oldpc+1 == PC) /* nothing */; \
1518 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1519 else fprintf (out, " %d", i);
1521 /* Print out operand (a local variable index) for LOAD opcodes.
1522 These all push local variable onto the opcode stack. */
1523 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1524 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1526 /* Handle STORE opcodes same as LOAD opcodes.
1527 These all store a value from the opcode stack in a local variable. */
1530 /* Handle more kind of opcodes. */
1531 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1532 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1533 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1534 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1535 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1536 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1537 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1539 /* Handle putfield and getfield opcodes, with static versions. */
1540 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1541 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1543 /* Print operand for invoke opcodes. */
1544 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1545 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1546 if (OPERAND_VALUE) /* for invokeinterface */ \
1547 { int nargs = IMMEDIATE_u1; PC++; \
1548 fprintf (out, " nargs:%d", nargs); }
1550 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1551 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1553 #define ARRAY(OPERAND_TYPE, SUBOP) \
1554 ARRAY_##SUBOP(OPERAND_TYPE)
1555 /* Handle sub-categories of ARRAY opcodes. */
1556 #define ARRAY_LOAD(TYPE) /* nothing */
1557 #define ARRAY_STORE(TYPE) /* nothing */
1558 #define ARRAY_LENGTH(TYPE) /* nothing */
1559 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1560 #define ARRAY_NEW_NUM \
1561 INT_temp = IMMEDIATE_u1; \
1562 { switch ((int) INT_temp) { \
1563 case 4: fputs (" boolean", out); break; \
1564 case 5: fputs (" char", out); break; \
1565 case 6: fputs (" float", out); break; \
1566 case 7: fputs (" double", out); break; \
1567 case 8: fputs (" byte", out); break; \
1568 case 9: fputs (" short", out); break; \
1569 case 10: fputs (" int", out); break; \
1570 case 11: fputs (" long", out); break; \
1571 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1574 #define ARRAY_NEW_PTR \
1575 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1577 #define ARRAY_NEW_MULTI \
1578 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1579 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1581 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1582 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1584 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1585 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1586 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1588 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1589 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1590 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1592 #undef RET /* Defined by config/i386/i386.h */
1593 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1594 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1596 fprintf (out, " %ld", (long) INT_temp);
1598 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1599 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1601 #define LOOKUP_SWITCH \
1602 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1603 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1604 while (--npairs >= 0) { \
1605 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1606 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1609 #define TABLE_SWITCH \
1610 { jint default_offset = IMMEDIATE_s4; \
1611 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1612 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1613 (long) low, (long) high, (long) default_offset+oldpc); \
1614 for (; low <= high; low++) { \
1615 jint offset = IMMEDIATE_s4; \
1616 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1619 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1620 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1622 #define SPECIAL_IINC(OPERAND_TYPE) \
1623 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1624 fprintf (out, " %d", i); \
1625 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1627 fprintf (out, " %d", i)
1629 #define SPECIAL_WIDE(OPERAND_TYPE) \
1632 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1633 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1634 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1635 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1637 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1638 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1640 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1641 TEST(OPERAND_TYPE, OPERAND_VALUE)
1643 #include "javaop.def"
1646 if (oldpc
+1 == PC
) /* nothing - local index implied by opcode */;
1650 fprintf (out
, " %ld", (long) INT_temp
);
1656 fprintf (out
, "%3d: unknown(%3d)\n", oldpc
, byte_ops
[PC
]);