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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [java/] [jcf-dump.c] - Blame information for rev 20

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

Line No. Rev Author Line
1 12 jlechner
/* 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 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 2, 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 COPYING.  If not, write to
21
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22
Boston, MA 02110-1301, USA.
23
 
24
Java and all Java-based marks are trademarks or registered trademarks
25
of Sun Microsystems, Inc. in the United States and other countries.
26
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
27
 
28
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
29
 
30
/*
31
  jcf-dump is a program to print out the contents of class files.
32
  Usage:  jcf-dump [FLAGS] CLASS
33
  Each CLASS is either:
34
  + the name of a class in the CLASSPATH (e.g "java.lang.String"), or
35
  + the name of a class *file* (e.g. "/home/me/work/package/Foo.class").
36
  + The name of a .zip or .jar file (which prints all the classes in the
37
  archive).
38
 
39
  OPTIONS:
40
  -c
41
        Dis-assemble each method.
42
  -classpath PATH
43
        Overrides $CLASSPATH.
44
  --print-main
45
        Print nothing if there is no valid "main" method;
46
        otherwise, print only the class name.
47
  --javap
48
        Print output in the style of Sun's javap program.  VERY UNFINISHED.
49
 */
50
 
51
 
52
#include "config.h"
53
#include "system.h"
54
#include "coretypes.h"
55
#include "tm.h"
56
#include "ggc.h"
57
#include "intl.h"
58
 
59
#include "jcf.h"
60
#include "tree.h"
61
#include "java-tree.h"
62
 
63
#include "version.h"
64
 
65
#include <getopt.h>
66
#include <math.h>
67
 
68
/* Output file. */
69
FILE *out;
70
/* Name of output file, if NULL if stdout. */
71
char *output_file = NULL;
72
 
73
int verbose = 0;
74
 
75
int flag_disassemble_methods = 0;
76
int flag_print_class_info = 1;
77
int flag_print_constant_pool = 0;
78
int flag_print_fields = 1;
79
int flag_print_methods = 1;
80
int flag_print_attributes = 1;
81
 
82
/* When nonzero, warn when source file is newer than matching class
83
   file.  */
84
int flag_newer = 1;
85
 
86
/* Print names of classes that have a "main" method. */
87
int flag_print_main = 0;
88
 
89
/* Index in constant pool of this class. */
90
int this_class_index = 0;
91
 
92
int class_access_flags = 0;
93
 
94
/* Print in format similar to javap.  VERY INCOMPLETE. */
95
int flag_javap_compatible = 0;
96
 
97
static void print_access_flags (FILE *, uint16, char);
98
static void print_constant_terse (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
 
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
             (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, " Signature: "); \
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, " Signature: "); \
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_LINENUMBERTABLE_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
  if (flag_disassemble_methods) \
303
    for (i = 0; i < n; i++) {\
304
      int start_pc = JCF_readu2 (jcf); \
305
      int line_number = JCF_readu2 (jcf); \
306
      fprintf (out, "  line: %d at pc: %d\n", line_number, start_pc); }\
307
  else \
308
    JCF_SKIP (jcf, 4 * n); }
309
 
310
#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT)                                \
311
{ int n = (COUNT);                                                          \
312
  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);           \
313
  while (n--)                                                               \
314
    {                                                                       \
315
      uint16 inner_class_info_index = JCF_readu2 (jcf);                     \
316
      uint16 outer_class_info_index = JCF_readu2 (jcf);                     \
317
      uint16 inner_name_index = JCF_readu2 (jcf);                           \
318
      uint16 inner_class_access_flags = JCF_readu2 (jcf);                   \
319
                                                                            \
320
      if (flag_print_class_info)                                            \
321
        {                                                                   \
322
          fprintf (out, "\n  inner: ");                                     \
323
          if (inner_class_info_index == 0)                                   \
324
            fprintf (out, " (no inner info index)");                        \
325
          else                                                              \
326
            print_constant_terse_with_index (out, jcf,                      \
327
                                             inner_class_info_index,        \
328
                                             CONSTANT_Class);               \
329
          if (inner_name_index == 0)                                         \
330
            fprintf (out, " (anonymous)");                                  \
331
          else if (verbose || flag_print_constant_pool)                     \
332
            {                                                               \
333
              fprintf (out, " (");                                          \
334
              print_constant_terse_with_index (out, jcf, inner_name_index,  \
335
                                               CONSTANT_Utf8);              \
336
              fputc (')', out);                                             \
337
            }                                                               \
338
          fprintf (out, ", access flags: 0x%x", inner_class_access_flags);  \
339
          print_access_flags (out, inner_class_access_flags, 'c');          \
340
          fprintf (out, ", outer class: ");                                 \
341
          if (outer_class_info_index == 0)                                   \
342
            fprintf (out, "(not a member)");                                \
343
          else                                                              \
344
            print_constant_terse_with_index (out, jcf,                      \
345
                                             outer_class_info_index,        \
346
                                             CONSTANT_Class);               \
347
        }                                                                   \
348
    }                                                                       \
349
  if (flag_print_class_info)                                                \
350
    fputc ('\n', out);                                                      \
351
}
352
 
353
#define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
354
{ int i, n = (LENGTH), c = 0;                                      \
355
  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
356
  fputc ('\n', out); \
357
  for (i = 0;  i < n;  i++) { c = JCF_readu(jcf); fputc(c, out); } \
358
  if (c != '\r' && c != '\n') fputc('\n', out); }
359
 
360
#define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
361
{ COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
362
  fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
363
 
364
#define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
365
  if (flag_print_attributes > 0) \
366
    fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
367
 
368
#include "javaop.h"
369
 
370
static void
371
print_constant_ref (FILE *stream, JCF *jcf, int index)
372
{
373
  if (index <= 0 || index >= JPOOL_SIZE(jcf))
374
    fprintf (stream, "<out of range>");
375
  else
376
    {
377
      if (flag_print_constant_pool)
378
        fprintf (stream, "#%d=", index);
379
      fputc ('<', stream);
380
      print_constant (stream, jcf, index, 1);
381
      fputc ('>', stream);
382
    }
383
}
384
 
385
/* Print the access flags given by FLAGS.
386
   The CONTEXT is one of 'c' (class flags), 'f' (field flags),
387
   or 'm' (method flags). */
388
 
389
static void
390
print_access_flags (FILE *stream, uint16 flags, char context)
391
{
392
  if (flags & ACC_PUBLIC) fprintf (stream, " public");
393
  if (flags & ACC_PRIVATE) fprintf (stream, " private");
394
  if (flags & ACC_PROTECTED) fprintf (stream, " protected");
395
  if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
396
  if (flags & ACC_STATIC) fprintf (stream, " static");
397
  if (flags & ACC_FINAL) fprintf (stream, " final");
398
  if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
399
  if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
400
  if (flags & ACC_NATIVE) fprintf (stream, " native");
401
  if (flags & ACC_SYNCHRONIZED)
402
    {
403
      if (context == 'c')
404
        fprintf (stream, " super");
405
      else
406
        fprintf (stream, " synchronized");
407
    }
408
  if (flags & ACC_INTERFACE) fprintf (stream, " interface");
409
  if (flags & ACC_STRICT) fprintf (stream, " strictfp");
410
}
411
 
412
 
413
static void
414
print_name (FILE* stream, JCF* jcf, int name_index)
415
{
416
  if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
417
    fprintf (stream, "<not a UTF8 constant>");
418
  else
419
    jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
420
                    JPOOL_UTF_LENGTH (jcf, name_index));
421
}
422
 
423
/* If the type of the constant at INDEX matches EXPECTED,
424
   print it tersely, otherwise more verbosely. */
425
 
426
static void
427
print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
428
{
429
  if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
430
    fprintf (out, "<constant pool index %d not in range>", index);
431
  else if (JPOOL_TAG (jcf, index) != expected)
432
    {
433
      fprintf (out, "<Unexpected constant type ");
434
      print_constant (out, jcf, index, 1);
435
      fprintf (out, ">");
436
    }
437
  else
438
    print_constant (out, jcf, index, 0);
439
}
440
 
441
static void
442
print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
443
{
444
  if (flag_print_constant_pool)
445
    fprintf (out, "%d=", index);
446
  print_constant_terse (out, jcf, index, expected);
447
}
448
 
449
/* Print the constant at INDEX in JCF's constant pool.
450
   If verbosity==0, print very tersely (no extraneous text).
451
   If verbosity==1, prefix the type of the constant.
452
   If verbosity==2, add more descriptive text. */
453
 
454
static void
455
print_constant (FILE *out, JCF *jcf, int index, int verbosity)
456
{
457
  int j, n;
458
  jlong num;
459
  const char *str;
460
  int kind = JPOOL_TAG (jcf, index);
461
  switch (kind)
462
    {
463
    case CONSTANT_Class:
464
      n = JPOOL_USHORT1 (jcf, index);
465
      if (verbosity > 0)
466
        {
467
          if (verbosity > 1)
468
            fprintf (out, "Class name: %d=", n);
469
          else
470
            fprintf (out, "Class ");
471
        }
472
      if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
473
        fprintf (out, "<out of range>");
474
      else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
475
        {
476
          int len = JPOOL_UTF_LENGTH (jcf, n);
477
          jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
478
        }
479
      else
480
        print_constant_terse (out, jcf, n, CONSTANT_Utf8);
481
      break;
482
    case CONSTANT_Fieldref:
483
      str = "Field"; goto field_or_method;
484
    case CONSTANT_Methodref:
485
      str = "Method"; goto field_or_method;
486
    case CONSTANT_InterfaceMethodref:
487
      str = "InterfaceMethod"; goto field_or_method;
488
    field_or_method:
489
      {
490
        uint16 tclass = JPOOL_USHORT1 (jcf, index);
491
        uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
492
        if (verbosity == 2)
493
          fprintf (out, "%sref class: %d=", str, tclass);
494
        else if (verbosity > 0)
495
            fprintf (out, "%s ", str);
496
        print_constant_terse (out, jcf, tclass, CONSTANT_Class);
497
        if (verbosity < 2)
498
          fprintf (out, ".");
499
        else
500
          fprintf (out, " name_and_type: %d=<", name_and_type);
501
        print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
502
        if (verbosity == 2)
503
          fputc ('>', out);
504
      }
505
      break;
506
    case CONSTANT_String:
507
      j = JPOOL_USHORT1 (jcf, index);
508
      if (verbosity > 0)
509
        {
510
          if (verbosity > 1)
511
            fprintf (out, "String %d=", j);
512
          else
513
            fprintf (out, "String ");
514
        }
515
      print_constant_terse (out, jcf, j, CONSTANT_Utf8);
516
      break;
517
    case CONSTANT_Integer:
518
      if (verbosity > 0)
519
        fprintf (out, "Integer ");
520
      num = JPOOL_INT (jcf, index);
521
      goto integer;
522
    case CONSTANT_Long:
523
      if (verbosity > 0)
524
        fprintf (out, "Long ");
525
      num = JPOOL_LONG (jcf, index);
526
      goto integer;
527
    integer:
528
      {
529
        char buffer[25];
530
        format_int (buffer, num, 10);
531
        fprintf (out, "%s", buffer);
532
        if (verbosity > 1)
533
          {
534
            format_uint (buffer, (uint64)num, 16);
535
            fprintf (out, "=0x%s", buffer);
536
          }
537
      }
538
      break;
539
    case CONSTANT_Float:
540
      {
541
        jfloat fnum = JPOOL_FLOAT (jcf, index);
542
 
543
        if (verbosity > 0)
544
          fputs ("Float ", out);
545
 
546
        if (fnum.negative)
547
          putc ('-', out);
548
 
549
        if (JFLOAT_FINITE (fnum))
550
          {
551
            int dummy;
552
            int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
553
            double f;
554
            uint32 mantissa = fnum.mantissa;
555
            if (fnum.exponent == 0)
556
              /* Denormal.  */
557
              exponent++;
558
            else
559
              /* Normal; add the implicit bit.  */
560
              mantissa |= ((uint32)1 << 23);
561
 
562
            f = frexp (mantissa, &dummy);
563
            f = ldexp (f, exponent + 1);
564
            fprintf (out, "%.10g", f);
565
          }
566
        else
567
          {
568
            if (fnum.mantissa == 0)
569
              fputs ("Inf", out);
570
            else if (fnum.mantissa & JFLOAT_QNAN_MASK)
571
              fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
572
            else
573
              fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
574
          }
575
 
576
        if (verbosity > 1)
577
          fprintf (out, ", bits = 0x%08lx", JPOOL_UINT (jcf, index));
578
 
579
        break;
580
      }
581
    case CONSTANT_Double:
582
      {
583
        jdouble dnum = JPOOL_DOUBLE (jcf, index);
584
 
585
        if (verbosity > 0)
586
          fputs ("Double ", out);
587
 
588
        if (dnum.negative)
589
          putc ('-', out);
590
 
591
        if (JDOUBLE_FINITE (dnum))
592
          {
593
            int dummy;
594
            int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
595
            double d;
596
            uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
597
                               + dnum.mantissa1);
598
            if (dnum.exponent == 0)
599
              /* Denormal.  */
600
              exponent++;
601
            else
602
              /* Normal; add the implicit bit.  */
603
              mantissa |= ((uint64)1 << 52);
604
 
605
            d = frexp (mantissa, &dummy);
606
            d = ldexp (d, exponent + 1);
607
            fprintf (out, "%.20g", d);
608
          }
609
        else
610
          {
611
            uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
612
            mantissa = (mantissa << 32) + dnum.mantissa1;
613
 
614
            if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
615
              fputs ("Inf", out);
616
            else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
617
              fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
618
            else
619
              fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
620
          }
621
        if (verbosity > 1)
622
          {
623
            int32 hi, lo;
624
            hi = JPOOL_UINT (jcf, index);
625
            lo = JPOOL_UINT (jcf, index + 1);
626
            fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
627
          }
628
        break;
629
      }
630
    case CONSTANT_NameAndType:
631
      {
632
        uint16 name = JPOOL_USHORT1 (jcf, index);
633
        uint16 sig = JPOOL_USHORT2 (jcf, index);
634
        if (verbosity > 0)
635
          {
636
            if (verbosity > 1)
637
              fprintf (out, "NameAndType name: %d=", name);
638
            else
639
              fprintf (out, "NameAndType ");
640
          }
641
        print_name (out, jcf, name);
642
        if (verbosity <= 1)
643
          fputc (' ', out);
644
        else
645
          fprintf (out, ", signature: %d=", sig);
646
        print_signature (out, jcf, sig, 0);
647
      }
648
      break;
649
    case CONSTANT_Utf8:
650
      {
651
        const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
652
        int length = JPOOL_UTF_LENGTH (jcf, index);
653
        if (verbosity > 0)
654
          { /* Print as 8-bit bytes. */
655
            fputs ("Utf8: \"", out);
656
            while (--length >= 0)
657
              jcf_print_char (out, *str++);
658
          }
659
        else
660
          { /* Print as Unicode. */
661
            fputc ('\"', out);
662
            jcf_print_utf8 (out, str, length);
663
          }
664
        fputc ('\"', out);
665
      }
666
      break;
667
    default:
668
      fprintf (out, "(Unknown constant type %d)", kind);
669
    }
670
}
671
 
672
static void
673
print_constant_pool (JCF *jcf)
674
{
675
  int i;
676
  for (i = 1; i < JPOOL_SIZE(jcf); i++)
677
    {
678
      int kind = JPOOL_TAG (jcf, i);
679
      fprintf (out, "#%d: ", i);
680
      print_constant (out, jcf, i, 2);
681
      fprintf (out, "\n");
682
      if (kind == CONSTANT_Double || kind == CONSTANT_Long)
683
        i++; /* These take up two slots in the constant table */
684
    }
685
}
686
 
687
static void
688
print_signature_type (FILE* stream, const unsigned char **ptr,
689
                      const unsigned char *limit)
690
{
691
  int array_size;
692
  if ((*ptr) >= limit)
693
    return;
694
  switch (*(*ptr))
695
    {
696
    case '[':
697
      array_size = -1;
698
      for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
699
        {
700
          array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
701
        }
702
      print_signature_type (stream, ptr, limit);
703
      if (array_size == -1)
704
        fprintf (stream, "[]");
705
      else
706
        fprintf (stream, "[%d]", array_size);
707
      break;
708
    case '(':
709
      {
710
        int nargs = 0;
711
        fputc (*(*ptr)++, stream);
712
        for (; **ptr != ')' && *ptr < limit; nargs++)
713
          {
714
            if (nargs > 0)
715
              fputc (',', stream);
716
            print_signature_type (stream, ptr, limit);
717
          }
718
        if (*ptr < limit)
719
          {
720
            fputc (*(*ptr)++, stream);
721
            print_signature_type (stream, ptr, limit);
722
          }
723
        else
724
          fprintf (stream, "???");
725
      }
726
    break;
727
 
728
    case 'B':  fprintf (stream, "byte");  (*ptr)++;  break;
729
    case 'C':  fprintf (stream, "char");  (*ptr)++;  break;
730
    case 'D':  fprintf (stream, "double");  (*ptr)++;  break;
731
    case 'F':  fprintf (stream, "float");  (*ptr)++;  break;
732
    case 'S':  fprintf (stream, "short");  (*ptr)++;  break;
733
    case 'I':  fprintf (stream, "int");  (*ptr)++;  break;
734
    case 'J':  fprintf (stream, "long");  (*ptr)++;  break;
735
    case 'Z':  fprintf (stream, "boolean");  (*ptr)++;  break;
736
    case 'V':  fprintf (stream, "void");  (*ptr)++;  break;
737
 
738
    case 'L':
739
      for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
740
        jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
741
      if (*(*ptr) == ';')
742
        (*ptr)++;
743
      break;
744
    default:
745
      jcf_print_char (stream, *(*ptr)++);
746
    }
747
}
748
 
749
static void
750
print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
751
{
752
  if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
753
    print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
754
  else
755
    {
756
      const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
757
      int length = JPOOL_UTF_LENGTH (jcf, signature_index);
758
      const unsigned char *limit;
759
      limit = str + length;
760
      if (str >= limit)
761
        fprintf (stream, "<empty signature string>");
762
      else
763
        {
764
          if (options & PRINT_SIGNATURE_RESULT_ONLY)
765
            {
766
              while (str < limit && *str++ != ')') ;
767
            }
768
          if (options & PRINT_SIGNATURE_ARGS_ONLY)
769
            {
770
              str++;
771
              fputc ('(', stream);
772
              while (str < limit && *str != ')')
773
                {
774
                  print_signature_type (stream, &str, limit);
775
                  if (*str != ')')
776
                    fputs (", ", stream);
777
                }
778
              fputc (')', stream);
779
            }
780
          else
781
            {
782
              print_signature_type (stream, &str, limit);
783
              if (str < limit)
784
                {
785
                  fprintf (stream, "<junk:");
786
                  jcf_print_utf8 (stream, str, limit - str);
787
                  fputc ('>', stream);
788
                }
789
            }
790
        }
791
    }
792
}
793
 
794
 
795
static void
796
print_exception_table (JCF *jcf, const unsigned char *entries, int count)
797
{
798
  /* Print exception table. */
799
  int i = count;
800
  if (i > 0)
801
    {
802
      const unsigned char *ptr = entries;
803
      fprintf (out, "Exceptions (count: %d):\n", i);
804
      for (; --i >= 0;  ptr+= 8)
805
        {
806
          int start_pc = GET_u2 (ptr);
807
          int end_pc = GET_u2 (ptr+2);
808
          int handler_pc = GET_u2 (ptr+4);
809
          int catch_type = GET_u2 (ptr+6);
810
          fprintf (out, "  start: %d, end: %d, handler: %d, type: ",
811
                   start_pc, end_pc, handler_pc);
812
          if (catch_type == 0)
813
            fputs ("0 /* finally */", out);
814
          else
815
            print_constant_terse_with_index (out, jcf,
816
                                             catch_type, CONSTANT_Class);
817
          fputc ('\n', out);
818
        }
819
    }
820
}
821
 
822
#include "jcf-reader.c"
823
 
824
static void
825
process_class (JCF *jcf)
826
{
827
  int code;
828
  if (jcf_parse_preamble (jcf) != 0)
829
    fprintf (stderr, _("Not a valid Java .class file.\n"));
830
 
831
  /* Parse and possibly print constant pool */
832
  code = jcf_parse_constant_pool (jcf);
833
  if (code != 0)
834
    {
835
      fprintf (stderr, _("error while parsing constant pool\n"));
836
      exit (FATAL_EXIT_CODE);
837
    }
838
  code = verify_constant_pool (jcf);
839
  if (code > 0)
840
    {
841
      fprintf (stderr, _("error in constant pool entry #%d\n"), code);
842
      exit (FATAL_EXIT_CODE);
843
    }
844
  if (flag_print_constant_pool)
845
    print_constant_pool (jcf);
846
 
847
  jcf_parse_class (jcf);
848
  code = jcf_parse_fields (jcf);
849
  if (code != 0)
850
    {
851
      fprintf (stderr, _("error while parsing fields\n"));
852
      exit (FATAL_EXIT_CODE);
853
    }
854
  code = jcf_parse_methods (jcf);
855
  if (code != 0)
856
    {
857
      fprintf (stderr, _("error while parsing methods\n"));
858
      exit (FATAL_EXIT_CODE);
859
    }
860
  code = jcf_parse_final_attributes (jcf);
861
  if (code != 0)
862
    {
863
      fprintf (stderr, _("error while parsing final attributes\n"));
864
      exit (FATAL_EXIT_CODE);
865
    }
866
  jcf->filename = NULL;
867
}
868
 
869
 
870
 
871
/* This is used to mark options with no short value.  */
872
#define LONG_OPT(Num)  ((Num) + 128)
873
 
874
#define OPT_classpath     LONG_OPT (0)
875
#define OPT_CLASSPATH     OPT_classpath
876
#define OPT_bootclasspath LONG_OPT (1)
877
#define OPT_extdirs       LONG_OPT (2)
878
#define OPT_HELP          LONG_OPT (3)
879
#define OPT_VERSION       LONG_OPT (4)
880
#define OPT_JAVAP         LONG_OPT (5)
881
 
882
static const struct option options[] =
883
{
884
  { "classpath",     required_argument, NULL, OPT_classpath },
885
  { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
886
  { "extdirs",       required_argument, NULL, OPT_extdirs },
887
  { "CLASSPATH",     required_argument, NULL, OPT_CLASSPATH },
888
  { "help",          no_argument,       NULL, OPT_HELP },
889
  { "verbose",       no_argument,       NULL, 'v' },
890
  { "version",       no_argument,       NULL, OPT_VERSION },
891
  { "javap",         no_argument,       NULL, OPT_JAVAP },
892
  { "print-main",    no_argument,       &flag_print_main, 1 },
893
  { "print-constants", no_argument,     &flag_print_constant_pool, 1 },
894
  { NULL,            no_argument,       NULL, 0 }
895
};
896
 
897
static void
898
usage (void)
899
{
900
  fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
901
  exit (1);
902
}
903
 
904
static void
905
help (void)
906
{
907
  printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
908
  printf (_("Display contents of a class file in readable form.\n\n"));
909
  printf (_("  -c                      Disassemble method bodies\n"));
910
  printf (_("  --javap                 Generate output in 'javap' format\n"));
911
  printf ("\n");
912
  printf (_("  --classpath PATH        Set path to find .class files\n"));
913
  printf (_("  -IDIR                   Append directory to class path\n"));
914
  printf (_("  --bootclasspath PATH    Override built-in class path\n"));
915
  printf (_("  --extdirs PATH          Set extensions directory path\n"));
916
  printf (_("  -o FILE                 Set output file name\n"));
917
  printf ("\n");
918
  printf (_("  --help                  Print this help, then exit\n"));
919
  printf (_("  --version               Print version number, then exit\n"));
920
  printf (_("  -v, --verbose           Print extra information while running\n"));
921
  printf ("\n");
922
  printf (_("For bug reporting instructions, please see:\n"
923
            "%s.\n"), bug_report_url);
924
  exit (0);
925
}
926
 
927
static void
928
version (void)
929
{
930
  printf ("jcf-dump (GCC) %s\n\n", version_string);
931
  printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
932
  printf (_("This is free software; see the source for copying conditions.  There is NO\n"
933
            "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
934
  exit (0);
935
}
936
 
937
int
938
main (int argc, char** argv)
939
{
940
  JCF jcf[1];
941
  int argi, opt;
942
 
943
  /* Unlock the stdio streams.  */
944
  unlock_std_streams ();
945
 
946
  gcc_init_libintl ();
947
 
948
  if (argc <= 1)
949
    {
950
      fprintf (stderr, _("jcf-dump: no classes specified\n"));
951
      usage ();
952
    }
953
 
954
  jcf_path_init ();
955
 
956
  /* We use getopt_long_only to allow single `-' long options.  For
957
     some of our options this is more natural.  */
958
  while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
959
    {
960
      switch (opt)
961
        {
962
        case 0:
963
          /* Already handled.  */
964
          break;
965
 
966
        case 'o':
967
          output_file = optarg;
968
          break;
969
 
970
        case 'I':
971
          jcf_path_include_arg (optarg);
972
          break;
973
 
974
        case 'v':
975
          verbose++;
976
          break;
977
 
978
        case 'c':
979
          flag_disassemble_methods = 1;
980
          break;
981
 
982
        case OPT_classpath:
983
          jcf_path_classpath_arg (optarg);
984
          break;
985
 
986
        case OPT_bootclasspath:
987
          jcf_path_bootclasspath_arg (optarg);
988
          break;
989
 
990
        case OPT_extdirs:
991
          jcf_path_extdirs_arg (optarg);
992
          break;
993
 
994
        case OPT_HELP:
995
          help ();
996
          break;
997
 
998
        case OPT_VERSION:
999
          version ();
1000
          break;
1001
 
1002
        case OPT_JAVAP:
1003
          flag_javap_compatible++;
1004
          flag_print_constant_pool = 0;
1005
          flag_print_attributes = 0;
1006
          break;
1007
 
1008
        default:
1009
          usage ();
1010
        }
1011
    }
1012
 
1013
  if (verbose && ! flag_javap_compatible)
1014
    flag_print_constant_pool = 1;
1015
 
1016
  if (optind == argc)
1017
    {
1018
      fprintf (stderr, _("jcf-dump: no classes specified\n"));
1019
      usage ();
1020
    }
1021
 
1022
  jcf_path_seal (verbose);
1023
 
1024
  if (flag_print_main)
1025
    {
1026
      flag_print_fields = 0;
1027
      flag_print_methods = 0;
1028
      flag_print_constant_pool = 0;
1029
      flag_print_attributes = 0;
1030
      flag_print_class_info = 0;
1031
    }
1032
 
1033
  if (output_file)
1034
    {
1035
      out = fopen (output_file, "w");
1036
      if (! out)
1037
        {
1038
          fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1039
          return FATAL_EXIT_CODE;
1040
        }
1041
    }
1042
  else
1043
    out = stdout;
1044
 
1045
  if (optind >= argc)
1046
    {
1047
      fprintf (out, "Reading .class from <standard input>.\n");
1048
      open_class ("<stdio>", jcf, 0, NULL);
1049
      process_class (jcf);
1050
    }
1051
  else
1052
    {
1053
      for (argi = optind; argi < argc; argi++)
1054
        {
1055
          char *arg = argv[argi];
1056
          const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1057
          if (class_filename == NULL)
1058
            class_filename = find_classfile (arg, jcf, NULL);
1059
          if (class_filename == NULL)
1060
            {
1061
              perror ("Could not find class");
1062
              return FATAL_EXIT_CODE;
1063
            }
1064
          JCF_FILL (jcf, 4);
1065
          if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1066
            {
1067
              long compressed_size, member_size;
1068
              int compression_method, filename_length, extra_length;
1069
              int general_purpose_bits;
1070
              const char *filename;
1071
              int total_length;
1072
              if (flag_print_class_info)
1073
                fprintf (out, "Reading classes from archive %s.\n",
1074
                         class_filename);
1075
              for (;;)
1076
                {
1077
                  int skip = 0;
1078
                  jcf_filbuf_t save_filbuf = jcf->filbuf;
1079
                  long magic = JCF_readu4_le (jcf);
1080
                  if (magic == 0x02014b50 || magic == 0x06054b50)
1081
                    break;  /* got to central directory */
1082
                  if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1083
                    {
1084
                      fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1085
                      return FATAL_EXIT_CODE;
1086
                    }
1087
                  JCF_FILL (jcf, 26);
1088
                  JCF_SKIP (jcf, 2);
1089
                  general_purpose_bits = JCF_readu2_le (jcf);
1090
                  compression_method = JCF_readu2_le (jcf);
1091
                  JCF_SKIP (jcf, 8);
1092
                  compressed_size = JCF_readu4_le (jcf);
1093
                  member_size = JCF_readu4_le (jcf);
1094
                  filename_length = JCF_readu2_le (jcf);
1095
                  extra_length = JCF_readu2_le (jcf);
1096
                  total_length = filename_length + extra_length
1097
                    + compressed_size;
1098
                  if (jcf->read_end - jcf->read_ptr < total_length)
1099
                    jcf_trim_old_input (jcf);
1100
                  JCF_FILL (jcf, total_length);
1101
                  filename = (const char *) jcf->read_ptr;
1102
                  JCF_SKIP (jcf, filename_length);
1103
                  JCF_SKIP (jcf, extra_length);
1104
                  if (filename_length > 0
1105
                      && filename[filename_length-1] == '/')
1106
                    {
1107
                      if (flag_print_class_info)
1108
                        fprintf (out, "[Skipping directory %.*s]\n",
1109
                                 filename_length, filename);
1110
                      skip = 1;
1111
                    }
1112
                  else if (compression_method != 0)
1113
                    {
1114
                      if (flag_print_class_info)
1115
                        fprintf (out, "[Skipping compressed file %.*s]\n",
1116
                                 filename_length, filename);
1117
                      skip = 1;
1118
                    }
1119
                  else if (member_size < 4
1120
                           || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1121
                    {
1122
                      if (flag_print_class_info)
1123
                        fprintf (out, "[Skipping non-.class member %.*s]\n",
1124
                                 filename_length, filename);
1125
                      skip = 1;
1126
                    }
1127
                  else
1128
                    {
1129
                      if (flag_print_class_info)
1130
                        fprintf (out, "Reading class member: %.*s.\n",
1131
                                 filename_length, filename);
1132
                    }
1133
                  if (skip)
1134
                    {
1135
                      JCF_SKIP (jcf, compressed_size);
1136
                    }
1137
                  else
1138
                    {
1139
                      unsigned char *save_end;
1140
                      jcf->filbuf = jcf_unexpected_eof;
1141
                      save_end = jcf->read_end;
1142
                      jcf->read_end = jcf->read_ptr + compressed_size;
1143
                      process_class (jcf);
1144
                      jcf->filbuf = save_filbuf;
1145
                      jcf->read_end = save_end;
1146
                    }
1147
                }
1148
            }
1149
          else
1150
            {
1151
              if (flag_print_class_info)
1152
                fprintf (out, "Reading .class from %s.\n", class_filename);
1153
              process_class (jcf);
1154
            }
1155
          JCF_FINISH(jcf);
1156
        }
1157
    }
1158
 
1159
  return SUCCESS_EXIT_CODE;
1160
}
1161
 
1162
 
1163
 
1164
static void
1165
disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1166
{
1167
#undef PTR
1168
  int PC;
1169
  int i;
1170
  int saw_wide = 0;
1171
  if (flag_disassemble_methods == 0)
1172
    return;
1173
#define BCODE byte_ops
1174
  for (PC = 0; PC < len;)
1175
    {
1176
      int oldpc = PC;
1177
      int saw_index;
1178
      jint INT_temp;
1179
      switch (byte_ops[PC++])
1180
        {
1181
 
1182
/* This is the actual code emitted for each of opcodes in javaops.def.
1183
   The actual opcode-specific stuff is handled by the OPKIND macro.
1184
   I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1185
   Those macros are defined below.  The OPKINDs that do not have any
1186
   inline parameters (such as BINOP) and therefore do mot need anything
1187
   else to me printed out just use an empty body. */
1188
 
1189
#define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1190
        case OPCODE: \
1191
          fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1192
          OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1193
          fputc ('\n', out); \
1194
          break;
1195
 
1196
#define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1197
#define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1198
#define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1199
#define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1200
 
1201
#define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1202
  (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1203
 
1204
/* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1205
   These all push a constant onto the opcode stack. */
1206
#define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1207
  saw_index = 0, i = (OPERAND_VALUE); \
1208
  if (oldpc+1 == PC) /* nothing */; \
1209
  else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1210
  else fprintf (out, " %d", i);
1211
 
1212
/* Print out operand (a local variable index) for LOAD opcodes.
1213
   These all push local variable onto the opcode stack. */
1214
#define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1215
  INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1216
 
1217
/* Handle STORE opcodes same as LOAD opcodes.
1218
   These all store a value from the opcode stack in a local variable. */
1219
#define STORE LOAD
1220
 
1221
/* Handle more kind of opcodes. */
1222
#define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1223
#define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1224
#define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1225
#define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1226
#define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1227
#define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1228
#define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1229
 
1230
/* Handle putfield and getfield opcodes, with static versions. */
1231
#define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1232
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1233
 
1234
/* Print operand for invoke opcodes. */
1235
#define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1236
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1237
  if (OPERAND_VALUE) /* for invokeinterface */ \
1238
  { int nargs = IMMEDIATE_u1;  PC++; \
1239
    fprintf (out, " nargs:%d", nargs); }
1240
 
1241
#define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1242
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1243
 
1244
#define ARRAY(OPERAND_TYPE, SUBOP) \
1245
  ARRAY_##SUBOP(OPERAND_TYPE)
1246
/* Handle sub-categories of ARRAY opcodes. */
1247
#define ARRAY_LOAD(TYPE) /* nothing */
1248
#define ARRAY_STORE(TYPE) /* nothing */
1249
#define ARRAY_LENGTH(TYPE) /* nothing */
1250
#define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1251
#define ARRAY_NEW_NUM \
1252
 INT_temp = IMMEDIATE_u1; \
1253
 { switch ((int) INT_temp) {  \
1254
    case  4: fputs (" boolean", out); break; \
1255
    case  5: fputs (" char", out); break; \
1256
    case  6: fputs (" float", out); break; \
1257
    case  7: fputs (" double", out); break; \
1258
    case  8: fputs (" byte", out); break; \
1259
    case  9: fputs (" short", out); break; \
1260
    case 10: fputs (" int", out); break; \
1261
    case 11: fputs (" long", out); break; \
1262
    default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1263
  } }
1264
 
1265
#define ARRAY_NEW_PTR  \
1266
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1267
 
1268
#define ARRAY_NEW_MULTI \
1269
  fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1270
  fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1271
 
1272
#define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1273
  fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1274
 
1275
#define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1276
  saw_index = 0, INT_temp = (OPERAND_VALUE); \
1277
  fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1278
 
1279
#define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1280
  saw_index = 0, INT_temp = (OPERAND_VALUE); \
1281
  fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1282
 
1283
#undef RET /* Defined by config/i386/i386.h */
1284
#define RET(OPERAND_TYPE, OPERAND_VALUE) \
1285
  INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1286
  saw_wide = 0; \
1287
  fprintf (out, " %ld", (long) INT_temp);
1288
 
1289
#define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1290
  PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1291
 
1292
#define LOOKUP_SWITCH \
1293
  { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1294
    fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1295
    while (--npairs >= 0) { \
1296
     jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1297
     fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1298
  }
1299
 
1300
#define TABLE_SWITCH \
1301
  { jint default_offset = IMMEDIATE_s4; \
1302
    jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1303
    fprintf (out, " low=%ld, high=%ld, default=%ld", \
1304
      (long) low, (long) high, (long) default_offset+oldpc); \
1305
    for (; low <= high; low++) { \
1306
     jint offset = IMMEDIATE_s4; \
1307
     fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1308
  }
1309
 
1310
#define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1311
  SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1312
 
1313
#define SPECIAL_IINC(OPERAND_TYPE) \
1314
  i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1315
  fprintf (out, " %d", i); \
1316
  i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1317
  saw_wide = 0; \
1318
  fprintf (out, " %d", i)
1319
 
1320
#define SPECIAL_WIDE(OPERAND_TYPE) \
1321
  saw_wide = 1;
1322
 
1323
#define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1324
#define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1325
#define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1326
#define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1327
 
1328
#define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1329
  fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1330
 
1331
#define COND(OPERAND_TYPE, OPERAND_VALUE) \
1332
   TEST(OPERAND_TYPE, OPERAND_VALUE)
1333
 
1334
#include "javaop.def"
1335
 
1336
        load_store:
1337
          if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1338
          else
1339
            {
1340
              saw_wide = 0;
1341
              fprintf (out, " %ld", (long) INT_temp);
1342
            }
1343
          fputc ('\n', out);
1344
          break;
1345
 
1346
        default:
1347
          fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1348
        }
1349
    }
1350
}

powered by: WebSVN 2.1.0

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