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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [java/] [jcf-dump.c] - Blame information for rev 861

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

Line No. Rev Author Line
1 287 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 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
 
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
 
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
 
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 2010 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
              const char *filename;
1309
              int total_length;
1310
              if (flag_print_class_info)
1311
                fprintf (out, "Reading classes from archive %s.\n",
1312
                         class_filename);
1313
              for (;;)
1314
                {
1315
                  int skip = 0;
1316
                  jcf_filbuf_t save_filbuf = jcf->filbuf;
1317
                  long magic = JCF_readu4_le (jcf);
1318
                  if (magic == 0x02014b50 || magic == 0x06054b50)
1319
                    break;  /* got to central directory */
1320
                  if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1321
                    {
1322
                      fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1323
                      return FATAL_EXIT_CODE;
1324
                    }
1325
                  JCF_FILL (jcf, 26);
1326
                  JCF_SKIP (jcf, 2);
1327
                  (void) /* general_purpose_bits = */ JCF_readu2_le (jcf);
1328
                  compression_method = JCF_readu2_le (jcf);
1329
                  JCF_SKIP (jcf, 8);
1330
                  compressed_size = JCF_readu4_le (jcf);
1331
                  member_size = JCF_readu4_le (jcf);
1332
                  filename_length = JCF_readu2_le (jcf);
1333
                  extra_length = JCF_readu2_le (jcf);
1334
                  total_length = filename_length + extra_length
1335
                    + compressed_size;
1336
                  if (jcf->read_end - jcf->read_ptr < total_length)
1337
                    jcf_trim_old_input (jcf);
1338
                  JCF_FILL (jcf, total_length);
1339
                  filename = (const char *) jcf->read_ptr;
1340
                  JCF_SKIP (jcf, filename_length);
1341
                  JCF_SKIP (jcf, extra_length);
1342
                  if (filename_length > 0
1343
                      && filename[filename_length-1] == '/')
1344
                    {
1345
                      if (flag_print_class_info)
1346
                        fprintf (out, "[Skipping directory %.*s]\n",
1347
                                 filename_length, filename);
1348
                      skip = 1;
1349
                    }
1350
                  else if (compression_method != 0)
1351
                    {
1352
                      if (flag_print_class_info)
1353
                        fprintf (out, "[Skipping compressed file %.*s]\n",
1354
                                 filename_length, filename);
1355
                      skip = 1;
1356
                    }
1357
                  else if (member_size < 4
1358
                           || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1359
                    {
1360
                      if (flag_print_class_info)
1361
                        fprintf (out, "[Skipping non-.class member %.*s]\n",
1362
                                 filename_length, filename);
1363
                      skip = 1;
1364
                    }
1365
                  else
1366
                    {
1367
                      if (flag_print_class_info)
1368
                        fprintf (out, "Reading class member: %.*s.\n",
1369
                                 filename_length, filename);
1370
                    }
1371
                  if (skip)
1372
                    {
1373
                      JCF_SKIP (jcf, compressed_size);
1374
                    }
1375
                  else
1376
                    {
1377
                      unsigned char *save_end;
1378
                      jcf->filbuf = jcf_unexpected_eof;
1379
                      save_end = jcf->read_end;
1380
                      jcf->read_end = jcf->read_ptr + compressed_size;
1381
                      process_class (jcf);
1382
                      jcf->filbuf = save_filbuf;
1383
                      jcf->read_end = save_end;
1384
                    }
1385
                }
1386
            }
1387
          else
1388
            {
1389
              if (flag_print_class_info)
1390
                fprintf (out, "Reading .class from %s.\n", class_filename);
1391
              process_class (jcf);
1392
            }
1393
          JCF_FINISH(jcf);
1394
        }
1395
    }
1396
 
1397
  return SUCCESS_EXIT_CODE;
1398
}
1399
 
1400
 
1401
 
1402
static void
1403
disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1404
{
1405
#undef PTR
1406
  int PC;
1407
  int i;
1408
  int saw_wide = 0;
1409
  if (flag_disassemble_methods == 0)
1410
    return;
1411
#define BCODE byte_ops
1412
  for (PC = 0; PC < len;)
1413
    {
1414
      int oldpc = PC;
1415
      int saw_index;
1416
      jint INT_temp;
1417
      switch (byte_ops[PC++])
1418
        {
1419
 
1420
/* This is the actual code emitted for each of opcodes in javaops.def.
1421
   The actual opcode-specific stuff is handled by the OPKIND macro.
1422
   I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1423
   Those macros are defined below.  The OPKINDs that do not have any
1424
   inline parameters (such as BINOP) and therefore do mot need anything
1425
   else to me printed out just use an empty body. */
1426
 
1427
#define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1428
        case OPCODE: \
1429
          fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1430
          OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1431
          fputc ('\n', out); \
1432
          break;
1433
 
1434
#define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1435
#define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1436
#define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1437
#define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1438
 
1439
#define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1440
  (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1441
 
1442
/* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1443
   These all push a constant onto the opcode stack. */
1444
#define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1445
  saw_index = 0, i = (OPERAND_VALUE); \
1446
  if (oldpc+1 == PC) /* nothing */; \
1447
  else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1448
  else fprintf (out, " %d", i);
1449
 
1450
/* Print out operand (a local variable index) for LOAD opcodes.
1451
   These all push local variable onto the opcode stack. */
1452
#define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1453
  INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1454
 
1455
/* Handle STORE opcodes same as LOAD opcodes.
1456
   These all store a value from the opcode stack in a local variable. */
1457
#define STORE LOAD
1458
 
1459
/* Handle more kind of opcodes. */
1460
#define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1461
#define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1462
#define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1463
#define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1464
#define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1465
#define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1466
#define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1467
 
1468
/* Handle putfield and getfield opcodes, with static versions. */
1469
#define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1470
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1471
 
1472
/* Print operand for invoke opcodes. */
1473
#define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1474
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1475
  if (OPERAND_VALUE) /* for invokeinterface */ \
1476
  { int nargs = IMMEDIATE_u1;  PC++; \
1477
    fprintf (out, " nargs:%d", nargs); }
1478
 
1479
#define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1480
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1481
 
1482
#define ARRAY(OPERAND_TYPE, SUBOP) \
1483
  ARRAY_##SUBOP(OPERAND_TYPE)
1484
/* Handle sub-categories of ARRAY opcodes. */
1485
#define ARRAY_LOAD(TYPE) /* nothing */
1486
#define ARRAY_STORE(TYPE) /* nothing */
1487
#define ARRAY_LENGTH(TYPE) /* nothing */
1488
#define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1489
#define ARRAY_NEW_NUM \
1490
 INT_temp = IMMEDIATE_u1; \
1491
 { switch ((int) INT_temp) {  \
1492
    case  4: fputs (" boolean", out); break; \
1493
    case  5: fputs (" char", out); break; \
1494
    case  6: fputs (" float", out); break; \
1495
    case  7: fputs (" double", out); break; \
1496
    case  8: fputs (" byte", out); break; \
1497
    case  9: fputs (" short", out); break; \
1498
    case 10: fputs (" int", out); break; \
1499
    case 11: fputs (" long", out); break; \
1500
    default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1501
  } }
1502
 
1503
#define ARRAY_NEW_PTR  \
1504
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1505
 
1506
#define ARRAY_NEW_MULTI \
1507
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1508
  fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1509
 
1510
#define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1511
  fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1512
 
1513
#define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1514
  saw_index = 0, INT_temp = (OPERAND_VALUE); \
1515
  fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1516
 
1517
#define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1518
  saw_index = 0, INT_temp = (OPERAND_VALUE); \
1519
  fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1520
 
1521
#undef RET /* Defined by config/i386/i386.h */
1522
#define RET(OPERAND_TYPE, OPERAND_VALUE) \
1523
  INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1524
  saw_wide = 0; \
1525
  fprintf (out, " %ld", (long) INT_temp);
1526
 
1527
#define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1528
  PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1529
 
1530
#define LOOKUP_SWITCH \
1531
  { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1532
    fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1533
    while (--npairs >= 0) { \
1534
     jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1535
     fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1536
  }
1537
 
1538
#define TABLE_SWITCH \
1539
  { jint default_offset = IMMEDIATE_s4; \
1540
    jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1541
    fprintf (out, " low=%ld, high=%ld, default=%ld", \
1542
      (long) low, (long) high, (long) default_offset+oldpc); \
1543
    for (; low <= high; low++) { \
1544
     jint offset = IMMEDIATE_s4; \
1545
     fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1546
  }
1547
 
1548
#define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1549
  SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1550
 
1551
#define SPECIAL_IINC(OPERAND_TYPE) \
1552
  i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1553
  fprintf (out, " %d", i); \
1554
  i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1555
  saw_wide = 0; \
1556
  fprintf (out, " %d", i)
1557
 
1558
#define SPECIAL_WIDE(OPERAND_TYPE) \
1559
  saw_wide = 1;
1560
 
1561
#define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1562
#define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1563
#define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1564
#define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1565
 
1566
#define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1567
  fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1568
 
1569
#define COND(OPERAND_TYPE, OPERAND_VALUE) \
1570
   TEST(OPERAND_TYPE, OPERAND_VALUE)
1571
 
1572
#include "javaop.def"
1573
 
1574
        load_store:
1575
          if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1576
          else
1577
            {
1578
              saw_wide = 0;
1579
              fprintf (out, " %ld", (long) INT_temp);
1580
            }
1581
          fputc ('\n', out);
1582
          break;
1583
 
1584
        default:
1585
          fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1586
        }
1587
    }
1588
}

powered by: WebSVN 2.1.0

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