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