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 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); \
434 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
435 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
436 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
438 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
439 if (flag_print_attributes > 0) \
440 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
447 indent (FILE *stream
, int level
)
450 for (i
= 0; i
< level
; ++i
)
451 fprintf (stream
, " ");
455 print_element_value (FILE *stream
, JCF
*jcf
, int level
)
457 uint8 tag
= JCF_readu (jcf
);
458 indent (stream
, level
);
467 uint16 cindex
= JCF_readu2 (jcf
);
468 print_constant_terse_with_index (stream
, jcf
, cindex
,
474 uint16 cindex
= JCF_readu2 (jcf
);
475 print_constant_terse_with_index (stream
, jcf
, cindex
,
481 uint16 cindex
= JCF_readu2 (jcf
);
482 print_constant_terse_with_index (stream
, jcf
, cindex
,
488 uint16 cindex
= JCF_readu2 (jcf
);
489 print_constant_terse_with_index (stream
, jcf
, cindex
,
495 uint16 cindex
= JCF_readu2 (jcf
);
496 /* Despite what the JVM spec says, compilers generate a Utf8
497 constant here, not a String. */
498 print_constant_terse_with_index (stream
, jcf
, cindex
,
505 uint16 type_name_index
= JCF_readu2 (jcf
);
506 uint16 const_name_index
= JCF_readu2 (jcf
);
507 fprintf (stream
, "enum class: ");
508 print_constant_terse_with_index (stream
, jcf
, type_name_index
,
510 fprintf (stream
, "\n");
511 indent (stream
, level
);
512 fprintf (stream
, "Field: ");
513 print_constant_terse_with_index (stream
, jcf
, const_name_index
,
519 uint16 class_info_index
= JCF_readu2 (jcf
);
520 print_constant_terse_with_index (stream
, jcf
, class_info_index
,
526 fprintf (stream
, "Annotation:\n");
527 print_annotation (stream
, jcf
, level
+ 1);
532 uint16 n_array_elts
= JCF_readu2 (jcf
);
533 fprintf (stream
, "array[%d]: [\n", (int) n_array_elts
);
534 while (n_array_elts
--)
535 print_element_value (stream
, jcf
, level
+ 1);
536 indent (stream
, level
);
537 fprintf (stream
, "]");
541 fprintf (stream
, "Unexpected tag value: %d", (int) tag
);
544 fputc ('\n', stream
);
548 print_annotation (FILE *stream
, JCF
*jcf
, int level
)
550 uint16 type_index
= JCF_readu2 (jcf
);
551 uint16 npairs
= JCF_readu2 (jcf
);
552 fprintf (stream
, "\n");
553 indent (stream
, level
);
554 fprintf (stream
, "Annotation name: ");
555 print_constant_terse_with_index (stream
, jcf
, type_index
,
559 fprintf (stream
, "\n");
562 uint16 name_index
= JCF_readu2 (jcf
);
563 indent (stream
, level
+ 1);
564 fprintf (stream
, "Name: ");
565 print_constant_terse_with_index (stream
, jcf
, name_index
,
567 fprintf (stream
, "\n");
568 print_element_value (stream
, jcf
, level
+ 2);
574 print_annotations (FILE *stream
, JCF
*jcf
, int level
)
576 uint16 num
= JCF_readu2 (jcf
);
578 print_annotation (stream
, jcf
, level
);
582 print_parameter_annotations (FILE *stream
, JCF
*jcf
, int level
)
584 uint8 nparams
= JCF_readu (jcf
);
586 for (i
= 0; i
< nparams
; ++i
)
588 indent (stream
, level
);
589 fprintf (stream
, "Parameter annotations (%d):\n", (int) i
);
590 print_annotations (stream
, jcf
, level
+ 1);
597 print_constant_ref (FILE *stream
, JCF
*jcf
, int index
)
599 if (index
<= 0 || index
>= JPOOL_SIZE(jcf
))
600 fprintf (stream
, "<out of range>");
603 if (flag_print_constant_pool
)
604 fprintf (stream
, "#%d=", index
);
606 print_constant (stream
, jcf
, index
, 1);
611 /* Print the access flags given by FLAGS.
612 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
613 or 'm' (method flags). */
616 print_access_flags (FILE *stream
, uint16 flags
, char context
)
618 if (flags
& ACC_PUBLIC
) fprintf (stream
, " public");
619 if (flags
& ACC_PRIVATE
) fprintf (stream
, " private");
620 if (flags
& ACC_PROTECTED
) fprintf (stream
, " protected");
621 if (flags
& ACC_ABSTRACT
) fprintf (stream
, " abstract");
622 if (flags
& ACC_STATIC
) fprintf (stream
, " static");
623 if (flags
& ACC_FINAL
) fprintf (stream
, " final");
624 if (flags
& ACC_TRANSIENT
)
625 fprintf (stream
, context
== 'm' ? " varargs" : " transient");
626 if (flags
& ACC_VOLATILE
)
627 fprintf (stream
, context
== 'm' ? " bridge" : " volatile");
628 if (flags
& ACC_NATIVE
) fprintf (stream
, " native");
629 if (flags
& ACC_SYNCHRONIZED
)
632 fprintf (stream
, " super");
634 fprintf (stream
, " synchronized");
636 if (flags
& ACC_INTERFACE
)
637 fprintf (stream
, (flags
& ACC_ANNOTATION
) ? " @interface" : " interface");
638 if (flags
& ACC_ENUM
) fprintf (stream
, " enum");
639 if (flags
& ACC_STRICT
) fprintf (stream
, " strictfp");
640 if (flags
& ACC_SYNTHETIC
) fprintf (stream
, " synthetic");
645 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
647 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
648 fprintf (stream
, "<not a UTF8 constant>");
650 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
,name_index
),
651 JPOOL_UTF_LENGTH (jcf
, name_index
));
654 /* If the type of the constant at INDEX matches EXPECTED,
655 print it tersely, otherwise more verbosely. */
658 print_constant_terse (FILE *out
, JCF
*jcf
, int index
, int expected
)
660 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, index
))
661 fprintf (out
, "<constant pool index %d not in range>", index
);
662 else if (JPOOL_TAG (jcf
, index
) != expected
)
664 fprintf (out
, "<Unexpected constant type ");
665 print_constant (out
, jcf
, index
, 1);
669 print_constant (out
, jcf
, index
, 0);
673 print_constant_terse_with_index (FILE *out
, JCF
*jcf
, int index
, int expected
)
675 if (flag_print_constant_pool
)
676 fprintf (out
, "%d=", index
);
677 print_constant_terse (out
, jcf
, index
, expected
);
680 /* Print the constant at INDEX in JCF's constant pool.
681 If verbosity==0, print very tersely (no extraneous text).
682 If verbosity==1, prefix the type of the constant.
683 If verbosity==2, add more descriptive text. */
686 print_constant (FILE *out
, JCF
*jcf
, int index
, int verbosity
)
691 int kind
= JPOOL_TAG (jcf
, index
);
695 n
= JPOOL_USHORT1 (jcf
, index
);
699 fprintf (out
, "Class name: %d=", n
);
701 fprintf (out
, "Class ");
703 if (! CPOOL_INDEX_IN_RANGE (&jcf
->cpool
, n
))
704 fprintf (out
, "<out of range>");
705 else if (verbosity
< 2 && JPOOL_TAG (jcf
, n
) == CONSTANT_Utf8
)
707 int len
= JPOOL_UTF_LENGTH (jcf
, n
);
708 jcf_print_utf8_replace (out
, JPOOL_UTF_DATA(jcf
,n
), len
, '/', '.');
711 print_constant_terse (out
, jcf
, n
, CONSTANT_Utf8
);
713 case CONSTANT_Fieldref
:
714 str
= "Field"; goto field_or_method
;
715 case CONSTANT_Methodref
:
716 str
= "Method"; goto field_or_method
;
717 case CONSTANT_InterfaceMethodref
:
718 str
= "InterfaceMethod"; goto field_or_method
;
721 uint16 tclass
= JPOOL_USHORT1 (jcf
, index
);
722 uint16 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
724 fprintf (out
, "%sref class: %d=", str
, tclass
);
725 else if (verbosity
> 0)
726 fprintf (out
, "%s ", str
);
727 print_constant_terse (out
, jcf
, tclass
, CONSTANT_Class
);
731 fprintf (out
, " name_and_type: %d=<", name_and_type
);
732 print_constant_terse (out
, jcf
, name_and_type
, CONSTANT_NameAndType
);
737 case CONSTANT_String
:
738 j
= JPOOL_USHORT1 (jcf
, index
);
742 fprintf (out
, "String %d=", j
);
744 fprintf (out
, "String ");
746 print_constant_terse (out
, jcf
, j
, CONSTANT_Utf8
);
748 case CONSTANT_Integer
:
750 fprintf (out
, "Integer ");
751 num
= JPOOL_INT (jcf
, index
);
755 fprintf (out
, "Long ");
756 num
= JPOOL_LONG (jcf
, index
);
761 format_int (buffer
, num
, 10);
762 fprintf (out
, "%s", buffer
);
765 format_uint (buffer
, (uint64
)num
, 16);
766 fprintf (out
, "=0x%s", buffer
);
772 jfloat fnum
= JPOOL_FLOAT (jcf
, index
);
775 fputs ("Float ", out
);
780 if (JFLOAT_FINITE (fnum
))
783 int exponent
= fnum
.exponent
- JFLOAT_EXP_BIAS
;
785 uint32 mantissa
= fnum
.mantissa
;
786 if (fnum
.exponent
== 0)
790 /* Normal; add the implicit bit. */
791 mantissa
|= ((uint32
)1 << 23);
793 f
= frexp ((float) mantissa
, &dummy
);
794 f
= ldexp (f
, exponent
+ 1);
795 fprintf (out
, "%.10g", f
);
799 if (fnum
.mantissa
== 0)
801 else if (fnum
.mantissa
& JFLOAT_QNAN_MASK
)
802 fprintf (out
, "QNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
804 fprintf (out
, "SNaN(%u)", (fnum
.mantissa
& ~JFLOAT_QNAN_MASK
));
808 fprintf (out
, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf
, index
));
812 case CONSTANT_Double
:
814 jdouble dnum
= JPOOL_DOUBLE (jcf
, index
);
817 fputs ("Double ", out
);
822 if (JDOUBLE_FINITE (dnum
))
825 int exponent
= dnum
.exponent
- JDOUBLE_EXP_BIAS
;
827 uint64 mantissa
= ((((uint64
) dnum
.mantissa0
) << 32)
829 if (dnum
.exponent
== 0)
833 /* Normal; add the implicit bit. */
834 mantissa
|= ((uint64
)1 << 52);
836 d
= frexp ((double) mantissa
, &dummy
);
837 d
= ldexp (d
, exponent
+ 1);
838 fprintf (out
, "%.20g", d
);
842 uint64 mantissa
= dnum
.mantissa0
& ~JDOUBLE_QNAN_MASK
;
843 mantissa
= (mantissa
<< 32) + dnum
.mantissa1
;
845 if (dnum
.mantissa0
== 0 && dnum
.mantissa1
== 0)
847 else if (dnum
.mantissa0
& JDOUBLE_QNAN_MASK
)
848 fprintf (out
, "QNaN(%" HOST_LONG_LONG_FORMAT
"u)",
849 (unsigned long long)mantissa
);
851 fprintf (out
, "SNaN(%" HOST_LONG_LONG_FORMAT
"u)",
852 (unsigned long long)mantissa
);
857 hi
= JPOOL_UINT (jcf
, index
);
858 lo
= JPOOL_UINT (jcf
, index
+ 1);
859 fprintf (out
, ", bits = 0x%08lx%08lx", (unsigned long) hi
,
864 case CONSTANT_NameAndType
:
866 uint16 name
= JPOOL_USHORT1 (jcf
, index
);
867 uint16 sig
= JPOOL_USHORT2 (jcf
, index
);
871 fprintf (out
, "NameAndType name: %d=", name
);
873 fprintf (out
, "NameAndType ");
875 print_name (out
, jcf
, name
);
879 fprintf (out
, ", signature: %d=", sig
);
880 print_signature (out
, jcf
, sig
, 0);
885 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, index
);
886 int length
= JPOOL_UTF_LENGTH (jcf
, index
);
888 { /* Print as 8-bit bytes. */
889 fputs ("Utf8: \"", out
);
890 while (--length
>= 0)
891 jcf_print_char (out
, *str
++);
894 { /* Print as Unicode. */
896 jcf_print_utf8 (out
, str
, length
);
902 fprintf (out
, "(Unknown constant type %d)", kind
);
907 print_constant_pool (JCF
*jcf
)
910 for (i
= 1; i
< JPOOL_SIZE(jcf
); i
++)
912 int kind
= JPOOL_TAG (jcf
, i
);
913 fprintf (out
, "#%d: ", i
);
914 print_constant (out
, jcf
, i
, 2);
916 if (kind
== CONSTANT_Double
|| kind
== CONSTANT_Long
)
917 i
++; /* These take up two slots in the constant table */
922 print_signature_type (FILE* stream
, const unsigned char **ptr
,
923 const unsigned char *limit
)
932 for ((*ptr
)++; (*ptr
) < limit
&& ISDIGIT (**ptr
); (*ptr
)++)
934 array_size
= (array_size
< 0 ? 0 : 10 * array_size
) + *(*ptr
) - '0';
936 print_signature_type (stream
, ptr
, limit
);
937 if (array_size
== -1)
938 fprintf (stream
, "[]");
940 fprintf (stream
, "[%d]", array_size
);
945 fputc (*(*ptr
)++, stream
);
946 for (; **ptr
!= ')' && *ptr
< limit
; nargs
++)
950 print_signature_type (stream
, ptr
, limit
);
954 fputc (*(*ptr
)++, stream
);
955 print_signature_type (stream
, ptr
, limit
);
958 fprintf (stream
, "???");
962 case 'B': fprintf (stream
, "byte"); (*ptr
)++; break;
963 case 'C': fprintf (stream
, "char"); (*ptr
)++; break;
964 case 'D': fprintf (stream
, "double"); (*ptr
)++; break;
965 case 'F': fprintf (stream
, "float"); (*ptr
)++; break;
966 case 'S': fprintf (stream
, "short"); (*ptr
)++; break;
967 case 'I': fprintf (stream
, "int"); (*ptr
)++; break;
968 case 'J': fprintf (stream
, "long"); (*ptr
)++; break;
969 case 'Z': fprintf (stream
, "boolean"); (*ptr
)++; break;
970 case 'V': fprintf (stream
, "void"); (*ptr
)++; break;
973 for ((*ptr
)++; (*ptr
)<limit
&& *(*ptr
) != ';'; (*ptr
)++)
974 jcf_print_char (stream
, *(*ptr
) == '/' ? '.' : *(*ptr
));
979 jcf_print_char (stream
, *(*ptr
)++);
984 print_signature (FILE* stream
, JCF
*jcf
, int signature_index
, int options
)
986 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
987 print_constant_terse (out
, jcf
, signature_index
, CONSTANT_Utf8
);
990 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, signature_index
);
991 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
992 const unsigned char *limit
;
993 limit
= str
+ length
;
995 fprintf (stream
, "<empty signature string>");
998 if (options
& PRINT_SIGNATURE_RESULT_ONLY
)
1000 while (str
< limit
&& *str
++ != ')') ;
1002 if (options
& PRINT_SIGNATURE_ARGS_ONLY
)
1005 fputc ('(', stream
);
1006 while (str
< limit
&& *str
!= ')')
1008 print_signature_type (stream
, &str
, limit
);
1010 fputs (", ", stream
);
1012 fputc (')', stream
);
1016 print_signature_type (stream
, &str
, limit
);
1019 fprintf (stream
, "<junk:");
1020 jcf_print_utf8 (stream
, str
, limit
- str
);
1021 fputc ('>', stream
);
1030 print_exception_table (JCF
*jcf
, const unsigned char *entries
, int count
)
1032 /* Print exception table. */
1036 const unsigned char *ptr
= entries
;
1037 fprintf (out
, "Exceptions (count: %d):\n", i
);
1038 for (; --i
>= 0; ptr
+= 8)
1040 int start_pc
= GET_u2 (ptr
);
1041 int end_pc
= GET_u2 (ptr
+2);
1042 int handler_pc
= GET_u2 (ptr
+4);
1043 int catch_type
= GET_u2 (ptr
+6);
1044 fprintf (out
, " start: %d, end: %d, handler: %d, type: ",
1045 start_pc
, end_pc
, handler_pc
);
1046 if (catch_type
== 0)
1047 fputs ("0 /* finally */", out
);
1049 print_constant_terse_with_index (out
, jcf
,
1050 catch_type
, CONSTANT_Class
);
1056 #include "jcf-reader.c"
1059 process_class (JCF
*jcf
)
1062 if (jcf_parse_preamble (jcf
) != 0)
1063 fprintf (stderr
, _("Not a valid Java .class file.\n"));
1065 /* Parse and possibly print constant pool */
1066 code
= jcf_parse_constant_pool (jcf
);
1069 fprintf (stderr
, _("error while parsing constant pool\n"));
1070 exit (FATAL_EXIT_CODE
);
1072 code
= verify_constant_pool (jcf
);
1075 fprintf (stderr
, _("error in constant pool entry #%d\n"), code
);
1076 exit (FATAL_EXIT_CODE
);
1078 if (flag_print_constant_pool
)
1079 print_constant_pool (jcf
);
1081 jcf_parse_class (jcf
);
1082 code
= jcf_parse_fields (jcf
);
1085 fprintf (stderr
, _("error while parsing fields\n"));
1086 exit (FATAL_EXIT_CODE
);
1088 code
= jcf_parse_methods (jcf
);
1091 fprintf (stderr
, _("error while parsing methods\n"));
1092 exit (FATAL_EXIT_CODE
);
1094 code
= jcf_parse_final_attributes (jcf
);
1097 fprintf (stderr
, _("error while parsing final attributes\n"));
1098 exit (FATAL_EXIT_CODE
);
1100 jcf
->filename
= NULL
;
1105 /* This is used to mark options with no short value. */
1106 #define LONG_OPT(Num) ((Num) + 128)
1108 #define OPT_classpath LONG_OPT (0)
1109 #define OPT_CLASSPATH OPT_classpath
1110 #define OPT_bootclasspath LONG_OPT (1)
1111 #define OPT_extdirs LONG_OPT (2)
1112 #define OPT_HELP LONG_OPT (3)
1113 #define OPT_VERSION LONG_OPT (4)
1114 #define OPT_JAVAP LONG_OPT (5)
1116 static const struct option options
[] =
1118 { "classpath", required_argument
, NULL
, OPT_classpath
},
1119 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
1120 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
1121 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
1122 { "help", no_argument
, NULL
, OPT_HELP
},
1123 { "verbose", no_argument
, NULL
, 'v' },
1124 { "version", no_argument
, NULL
, OPT_VERSION
},
1125 { "javap", no_argument
, NULL
, OPT_JAVAP
},
1126 { "print-main", no_argument
, &flag_print_main
, 1 },
1127 { "print-constants", no_argument
, &flag_print_constant_pool
, 1 },
1128 { NULL
, no_argument
, NULL
, 0 }
1134 fprintf (stderr
, _("Try 'jcf-dump --help' for more information.\n"));
1141 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
1142 printf (_("Display contents of a class file in readable form.\n\n"));
1143 printf (_(" -c Disassemble method bodies\n"));
1144 printf (_(" --javap Generate output in 'javap' format\n"));
1146 printf (_(" --classpath PATH Set path to find .class files\n"));
1147 printf (_(" -IDIR Append directory to class path\n"));
1148 printf (_(" --bootclasspath PATH Override built-in class path\n"));
1149 printf (_(" --extdirs PATH Set extensions directory path\n"));
1150 printf (_(" -o FILE Set output file name\n"));
1152 printf (_(" --help Print this help, then exit\n"));
1153 printf (_(" --version Print version number, then exit\n"));
1154 printf (_(" -v, --verbose Print extra information while running\n"));
1156 printf (_("For bug reporting instructions, please see:\n"
1157 "%s.\n"), bug_report_url
);
1164 printf ("jcf-dump %s%s\n\n", pkgversion_string
, version_string
);
1165 printf ("Copyright %s 2011 Free Software Foundation, Inc.\n", _("(C)"));
1166 printf (_("This is free software; see the source for copying conditions. There is NO\n"
1167 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
1172 main (int argc
, char** argv
)
1178 p
= argv
[0] + strlen (argv
[0]);
1179 while (p
!= argv
[0] && !IS_DIR_SEPARATOR (p
[-1]))
1183 xmalloc_set_program_name (progname
);
1185 /* Unlock the stdio streams. */
1186 unlock_std_streams ();
1188 gcc_init_libintl ();
1190 diagnostic_initialize (global_dc
, 0);
1194 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1200 /* We use getopt_long_only to allow single `-' long options. For
1201 some of our options this is more natural. */
1202 while ((opt
= getopt_long_only (argc
, argv
, "o:I:vc", options
, NULL
)) != -1)
1207 /* Already handled. */
1211 output_file
= optarg
;
1215 jcf_path_include_arg (optarg
);
1223 flag_disassemble_methods
= 1;
1227 jcf_path_classpath_arg (optarg
);
1230 case OPT_bootclasspath
:
1231 jcf_path_bootclasspath_arg (optarg
);
1235 jcf_path_extdirs_arg (optarg
);
1247 flag_javap_compatible
++;
1248 flag_print_constant_pool
= 0;
1249 flag_print_attributes
= 0;
1257 if (verbose
&& ! flag_javap_compatible
)
1258 flag_print_constant_pool
= 1;
1262 fprintf (stderr
, _("jcf-dump: no classes specified\n"));
1266 jcf_path_seal (verbose
);
1268 if (flag_print_main
)
1270 flag_print_fields
= 0;
1271 flag_print_methods
= 0;
1272 flag_print_constant_pool
= 0;
1273 flag_print_attributes
= 0;
1274 flag_print_class_info
= 0;
1279 out
= fopen (output_file
, "w");
1282 fprintf (stderr
, _("Cannot open '%s' for output.\n"), output_file
);
1283 return FATAL_EXIT_CODE
;
1291 fprintf (out
, "Reading .class from <standard input>.\n");
1292 open_class ("<stdio>", jcf
, 0, NULL
);
1293 process_class (jcf
);
1297 for (argi
= optind
; argi
< argc
; argi
++)
1299 char *arg
= argv
[argi
];
1300 const char *class_filename
= find_class (arg
, strlen (arg
), jcf
);
1301 if (class_filename
== NULL
)
1302 class_filename
= find_classfile (arg
, jcf
, NULL
);
1303 if (class_filename
== NULL
)
1305 perror ("Could not find class");
1306 return FATAL_EXIT_CODE
;
1309 if (GET_u4 (jcf
->read_ptr
) == ZIPMAGIC
)
1311 long compressed_size
, member_size
;
1312 int compression_method
, filename_length
, extra_length
;
1313 const char *filename
;
1315 if (flag_print_class_info
)
1316 fprintf (out
, "Reading classes from archive %s.\n",
1321 jcf_filbuf_t save_filbuf
= jcf
->filbuf
;
1322 long magic
= JCF_readu4_le (jcf
);
1323 if (magic
== 0x02014b50 || magic
== 0x06054b50)
1324 break; /* got to central directory */
1325 if (magic
!= 0x04034b50) /* ZIPMAGIC (little-endian) */
1327 fprintf (stderr
, _("bad format of .zip/.jar archive\n"));
1328 return FATAL_EXIT_CODE
;
1332 (void) /* general_purpose_bits = */ JCF_readu2_le (jcf
);
1333 compression_method
= JCF_readu2_le (jcf
);
1335 compressed_size
= JCF_readu4_le (jcf
);
1336 member_size
= JCF_readu4_le (jcf
);
1337 filename_length
= JCF_readu2_le (jcf
);
1338 extra_length
= JCF_readu2_le (jcf
);
1339 total_length
= filename_length
+ extra_length
1341 if (jcf
->read_end
- jcf
->read_ptr
< total_length
)
1342 jcf_trim_old_input (jcf
);
1343 JCF_FILL (jcf
, total_length
);
1344 filename
= (const char *) jcf
->read_ptr
;
1345 JCF_SKIP (jcf
, filename_length
);
1346 JCF_SKIP (jcf
, extra_length
);
1347 if (filename_length
> 0
1348 && filename
[filename_length
-1] == '/')
1350 if (flag_print_class_info
)
1351 fprintf (out
, "[Skipping directory %.*s]\n",
1352 filename_length
, filename
);
1355 else if (compression_method
!= 0)
1357 if (flag_print_class_info
)
1358 fprintf (out
, "[Skipping compressed file %.*s]\n",
1359 filename_length
, filename
);
1362 else if (member_size
< 4
1363 || GET_u4 (jcf
->read_ptr
) != 0xcafebabe)
1365 if (flag_print_class_info
)
1366 fprintf (out
, "[Skipping non-.class member %.*s]\n",
1367 filename_length
, filename
);
1372 if (flag_print_class_info
)
1373 fprintf (out
, "Reading class member: %.*s.\n",
1374 filename_length
, filename
);
1378 JCF_SKIP (jcf
, compressed_size
);
1382 unsigned char *save_end
;
1383 jcf
->filbuf
= jcf_unexpected_eof
;
1384 save_end
= jcf
->read_end
;
1385 jcf
->read_end
= jcf
->read_ptr
+ compressed_size
;
1386 process_class (jcf
);
1387 jcf
->filbuf
= save_filbuf
;
1388 jcf
->read_end
= save_end
;
1394 if (flag_print_class_info
)
1395 fprintf (out
, "Reading .class from %s.\n", class_filename
);
1396 process_class (jcf
);
1402 return SUCCESS_EXIT_CODE
;
1408 disassemble_method (JCF
* jcf
, const unsigned char *byte_ops
, int len
)
1414 if (flag_disassemble_methods
== 0)
1416 #define BCODE byte_ops
1417 for (PC
= 0; PC
< len
;)
1422 switch (byte_ops
[PC
++])
1425 /* This is the actual code emitted for each of opcodes in javaops.def.
1426 The actual opcode-specific stuff is handled by the OPKIND macro.
1427 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1428 Those macros are defined below. The OPKINDs that do not have any
1429 inline parameters (such as BINOP) and therefore do mot need anything
1430 else to me printed out just use an empty body. */
1432 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1434 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1435 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1436 fputc ('\n', out); \
1439 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1440 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1441 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1442 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1444 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1445 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1447 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1448 These all push a constant onto the opcode stack. */
1449 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1450 saw_index = 0, i = (OPERAND_VALUE); \
1451 if (oldpc+1 == PC) /* nothing */; \
1452 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1453 else fprintf (out, " %d", i);
1455 /* Print out operand (a local variable index) for LOAD opcodes.
1456 These all push local variable onto the opcode stack. */
1457 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1458 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1460 /* Handle STORE opcodes same as LOAD opcodes.
1461 These all store a value from the opcode stack in a local variable. */
1464 /* Handle more kind of opcodes. */
1465 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1466 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1467 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1468 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1469 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1470 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1471 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1473 /* Handle putfield and getfield opcodes, with static versions. */
1474 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1475 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1477 /* Print operand for invoke opcodes. */
1478 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1479 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1480 if (OPERAND_VALUE) /* for invokeinterface */ \
1481 { int nargs = IMMEDIATE_u1; PC++; \
1482 fprintf (out, " nargs:%d", nargs); }
1484 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1485 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1487 #define ARRAY(OPERAND_TYPE, SUBOP) \
1488 ARRAY_##SUBOP(OPERAND_TYPE)
1489 /* Handle sub-categories of ARRAY opcodes. */
1490 #define ARRAY_LOAD(TYPE) /* nothing */
1491 #define ARRAY_STORE(TYPE) /* nothing */
1492 #define ARRAY_LENGTH(TYPE) /* nothing */
1493 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1494 #define ARRAY_NEW_NUM \
1495 INT_temp = IMMEDIATE_u1; \
1496 { switch ((int) INT_temp) { \
1497 case 4: fputs (" boolean", out); break; \
1498 case 5: fputs (" char", out); break; \
1499 case 6: fputs (" float", out); break; \
1500 case 7: fputs (" double", out); break; \
1501 case 8: fputs (" byte", out); break; \
1502 case 9: fputs (" short", out); break; \
1503 case 10: fputs (" int", out); break; \
1504 case 11: fputs (" long", out); break; \
1505 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1508 #define ARRAY_NEW_PTR \
1509 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1511 #define ARRAY_NEW_MULTI \
1512 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1513 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1515 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1516 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1518 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1519 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1520 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1522 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1523 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1524 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1526 #undef RET /* Defined by config/i386/i386.h */
1527 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1528 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1530 fprintf (out, " %ld", (long) INT_temp);
1532 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1533 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1535 #define LOOKUP_SWITCH \
1536 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1537 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1538 while (--npairs >= 0) { \
1539 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1540 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1543 #define TABLE_SWITCH \
1544 { jint default_offset = IMMEDIATE_s4; \
1545 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1546 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1547 (long) low, (long) high, (long) default_offset+oldpc); \
1548 for (; low <= high; low++) { \
1549 jint offset = IMMEDIATE_s4; \
1550 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1553 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1554 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1556 #define SPECIAL_IINC(OPERAND_TYPE) \
1557 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1558 fprintf (out, " %d", i); \
1559 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1561 fprintf (out, " %d", i)
1563 #define SPECIAL_WIDE(OPERAND_TYPE) \
1566 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1567 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1568 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1569 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1571 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1572 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1574 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1575 TEST(OPERAND_TYPE, OPERAND_VALUE)
1577 #include "javaop.def"
1580 if (oldpc
+1 == PC
) /* nothing - local index implied by opcode */;
1584 fprintf (out
, " %ld", (long) INT_temp
);
1590 fprintf (out
, "%3d: unknown(%3d)\n", oldpc
, byte_ops
[PC
]);