OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [java/] [jcf-dump.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.