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