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