Functionally similar to Sun's javap.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>.
Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "ggc.h"
#include "intl.h"
+#include "diagnostic.h"
#include "jcf.h"
#include "tree.h"
int flag_print_methods = 1;
int flag_print_attributes = 1;
-/* When nonzero, warn when source file is newer than matching class
- file. */
-int flag_newer = 1;
-
/* Print names of classes that have a "main" method. */
int flag_print_main = 0;
static void print_access_flags (FILE *, uint16, char);
static void print_constant_terse (FILE*, JCF*, int, int);
+static void print_constant_terse_with_index (FILE *, JCF *, int, int);
static void print_constant (FILE *, JCF *, int, int);
static void print_constant_ref (FILE *, JCF *, int);
static void disassemble_method (JCF*, const unsigned char *, int);
static void print_constant_pool (struct JCF *);
static void print_exception_table (struct JCF *, const unsigned char *entries,
int);
+static void indent (FILE *, int);
+static void print_element_value (FILE *, JCF *, int);
+static void print_annotation (FILE *, JCF *, int);
+static void print_annotations (FILE *, JCF *, int);
+static void print_parameter_annotations (FILE *, JCF *, int);
#define PRINT_SIGNATURE_RESULT_ONLY 1
#define PRINT_SIGNATURE_ARGS_ONLY 2
if (flag_print_class_info) \
fprintf (out, \
"Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
- (long) MAGIC, (long) MINOR, (long) MAJOR)
+ (unsigned long) MAGIC, (long) MINOR, (long) MAJOR)
#define HANDLE_START_CONSTANT_POOL(COUNT) \
if (flag_print_constant_pool) \
{ fprintf (out, "Field name:"); \
print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
print_access_flags (out, ACCESS_FLAGS, 'f'); \
- fprintf (out, " Signature: "); \
+ fprintf (out, " Descriptor: "); \
if (flag_print_constant_pool) \
fprintf (out, "%d=", SIGNATURE); \
print_signature (out, jcf, SIGNATURE, 0); \
fprintf (out, "\nMethod name:"); \
print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
print_access_flags (out, ACCESS_FLAGS, 'm'); \
- fprintf (out, " Signature: "); \
+ fprintf (out, " Descriptor: "); \
if (flag_print_constant_pool) \
fprintf (out, "%d=", SIGNATURE); \
print_signature (out, jcf, SIGNATURE, 0); \
print_signature (out, jcf, signature_index, 0); \
fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
+#define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT) \
+{ int n = (COUNT); int i; \
+ COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
+ fprintf (out, ", count: %d\n", n); \
+ for (i = 0; i < n; i++) { \
+ int start_pc = JCF_readu2 (jcf); \
+ int length = JCF_readu2 (jcf); \
+ int name_index = JCF_readu2 (jcf); \
+ int signature_index = JCF_readu2 (jcf); \
+ int slot = JCF_readu2 (jcf); \
+ fprintf (out, " slot#%d: name: ", slot); \
+ if (flag_print_constant_pool) \
+ fprintf (out, "%d=", name_index); \
+ print_name (out, jcf, name_index); \
+ fprintf (out, ", type: "); \
+ if (flag_print_constant_pool) \
+ fprintf (out, "%d=", signature_index); \
+ print_signature (out, jcf, signature_index, 0); \
+ fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
+
#define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
{ int n = (COUNT); int i; \
COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
if (c != '\r' && c != '\n') fputc('\n', out); }
+#define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE() \
+ { uint16 class_index, method_index; \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ class_index = JCF_readu2 (jcf); \
+ method_index = JCF_readu2 (jcf); \
+ fprintf (out, "\n Class: "); \
+ print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
+ fprintf (out, "\n Method: "); \
+ print_constant_terse_with_index (out, jcf, method_index, \
+ CONSTANT_NameAndType); \
+ fputc ('\n', out); \
+}
+
+#define HANDLE_SIGNATURE_ATTRIBUTE() \
+{ \
+ uint16 signature; \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ signature = JCF_readu2 (jcf); \
+ fprintf (out, "\n Value: "); \
+ print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8); \
+ fputc ('\n', out); \
+}
+
+#define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE() \
+{ \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ print_annotations (out, jcf, 1); \
+}
+
+#define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE() \
+{ \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ print_annotations (out, jcf, 1); \
+}
+
+#define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
+{ \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ print_parameter_annotations (out, jcf, 1); \
+}
+
+#define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE() \
+{ \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ print_parameter_annotations (out, jcf, 1); \
+}
+
+#define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE() \
+{ \
+ COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+ print_element_value (out, jcf, 1); \
+}
+
+
#define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
{ COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
#include "javaop.h"
+\f
+
+static void
+indent (FILE *stream, int level)
+{
+ int i;
+ for (i = 0; i < level; ++i)
+ fprintf (stream, " ");
+}
+
+static void
+print_element_value (FILE *stream, JCF *jcf, int level)
+{
+ uint8 tag = JCF_readu (jcf);
+ indent (stream, level);
+ switch (tag)
+ {
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ case 'I':
+ {
+ uint16 cindex = JCF_readu2 (jcf);
+ print_constant_terse_with_index (stream, jcf, cindex,
+ CONSTANT_Integer);
+ }
+ break;
+ case 'D':
+ {
+ uint16 cindex = JCF_readu2 (jcf);
+ print_constant_terse_with_index (stream, jcf, cindex,
+ CONSTANT_Double);
+ }
+ break;
+ case 'F':
+ {
+ uint16 cindex = JCF_readu2 (jcf);
+ print_constant_terse_with_index (stream, jcf, cindex,
+ CONSTANT_Float);
+ }
+ break;
+ case 'J':
+ {
+ uint16 cindex = JCF_readu2 (jcf);
+ print_constant_terse_with_index (stream, jcf, cindex,
+ CONSTANT_Long);
+ }
+ break;
+ case 's':
+ {
+ uint16 cindex = JCF_readu2 (jcf);
+ /* Despite what the JVM spec says, compilers generate a Utf8
+ constant here, not a String. */
+ print_constant_terse_with_index (stream, jcf, cindex,
+ CONSTANT_Utf8);
+ }
+ break;
+
+ case 'e':
+ {
+ uint16 type_name_index = JCF_readu2 (jcf);
+ uint16 const_name_index = JCF_readu2 (jcf);
+ fprintf (stream, "enum class: ");
+ print_constant_terse_with_index (stream, jcf, type_name_index,
+ CONSTANT_Utf8);
+ fprintf (stream, "\n");
+ indent (stream, level);
+ fprintf (stream, "Field: ");
+ print_constant_terse_with_index (stream, jcf, const_name_index,
+ CONSTANT_Utf8);
+ }
+ break;
+ case 'c':
+ {
+ uint16 class_info_index = JCF_readu2 (jcf);
+ print_constant_terse_with_index (stream, jcf, class_info_index,
+ CONSTANT_Utf8);
+ }
+ break;
+ case '@':
+ {
+ fprintf (stream, "Annotation:\n");
+ print_annotation (stream, jcf, level + 1);
+ }
+ break;
+ case '[':
+ {
+ uint16 n_array_elts = JCF_readu2 (jcf);
+ fprintf (stream, "array[%d]: [\n", (int) n_array_elts);
+ while (n_array_elts--)
+ print_element_value (stream, jcf, level + 1);
+ indent (stream, level);
+ fprintf (stream, "]");
+ }
+ break;
+ default:
+ fprintf (stream, "Unexpected tag value: %d", (int) tag);
+ break;
+ }
+ fputc ('\n', stream);
+}
+
+static void
+print_annotation (FILE *stream, JCF *jcf, int level)
+{
+ uint16 type_index = JCF_readu2 (jcf);
+ uint16 npairs = JCF_readu2 (jcf);
+ fprintf (stream, "\n");
+ indent (stream, level);
+ fprintf (stream, "Annotation name: ");
+ print_constant_terse_with_index (stream, jcf, type_index,
+ CONSTANT_Utf8);
+ if (npairs)
+ {
+ fprintf (stream, "\n");
+ while (npairs--)
+ {
+ uint16 name_index = JCF_readu2 (jcf);
+ indent (stream, level + 1);
+ fprintf (stream, "Name: ");
+ print_constant_terse_with_index (stream, jcf, name_index,
+ CONSTANT_Utf8);
+ fprintf (stream, "\n");
+ print_element_value (stream, jcf, level + 2);
+ }
+ }
+}
+
+static void
+print_annotations (FILE *stream, JCF *jcf, int level)
+{
+ uint16 num = JCF_readu2 (jcf);
+ while (num--)
+ print_annotation (stream, jcf, level);
+}
+
+static void
+print_parameter_annotations (FILE *stream, JCF *jcf, int level)
+{
+ uint8 nparams = JCF_readu (jcf);
+ uint8 i;
+ for (i = 0; i < nparams; ++i)
+ {
+ indent (stream, level);
+ fprintf (stream, "Parameter annotations (%d):\n", (int) i);
+ print_annotations (stream, jcf, level + 1);
+ }
+}
+
+\f
+
static void
print_constant_ref (FILE *stream, JCF *jcf, int index)
{
/* Normal; add the implicit bit. */
mantissa |= ((uint32)1 << 23);
- f = frexp (mantissa, &dummy);
+ f = frexp ((float) mantissa, &dummy);
f = ldexp (f, exponent + 1);
fprintf (out, "%.10g", f);
}
}
if (verbosity > 1)
- fprintf (out, ", bits = 0x%08lx", (long) JPOOL_UINT (jcf, index));
+ fprintf (out, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf, index));
break;
}
/* Normal; add the implicit bit. */
mantissa |= ((uint64)1 << 52);
- d = frexp (mantissa, &dummy);
+ d = frexp ((double) mantissa, &dummy);
d = ldexp (d, exponent + 1);
fprintf (out, "%.20g", d);
}
if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
fputs ("Inf", out);
else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
- fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
+ fprintf (out, "QNaN(%" HOST_LONG_LONG_FORMAT "u)",
+ (unsigned long long)mantissa);
else
- fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
+ fprintf (out, "SNaN(%" HOST_LONG_LONG_FORMAT "u)",
+ (unsigned long long)mantissa);
}
if (verbosity > 1)
{
int32 hi, lo;
hi = JPOOL_UINT (jcf, index);
lo = JPOOL_UINT (jcf, index + 1);
- fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
+ fprintf (out, ", bits = 0x%08lx%08lx", (unsigned long) hi,
+ (unsigned long) lo);
}
break;
}
static void
version (void)
{
- printf ("jcf-dump (GCC) %s\n\n", version_string);
- printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
+ printf ("jcf-dump %s%s\n\n", pkgversion_string, version_string);
+ printf ("Copyright %s 2011 Free Software Foundation, Inc.\n", _("(C)"));
printf (_("This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
exit (0);
{
JCF jcf[1];
int argi, opt;
+ const char *p;
+
+ p = argv[0] + strlen (argv[0]);
+ while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+ --p;
+ progname = p;
+
+ xmalloc_set_program_name (progname);
/* Unlock the stdio streams. */
unlock_std_streams ();
gcc_init_libintl ();
+ diagnostic_initialize (global_dc, 0);
+
if (argc <= 1)
{
fprintf (stderr, _("jcf-dump: no classes specified\n"));
for (argi = optind; argi < argc; argi++)
{
char *arg = argv[argi];
- const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
+ const char *class_filename = find_class (arg, strlen (arg), jcf);
if (class_filename == NULL)
class_filename = find_classfile (arg, jcf, NULL);
if (class_filename == NULL)
{
long compressed_size, member_size;
int compression_method, filename_length, extra_length;
- int general_purpose_bits;
const char *filename;
int total_length;
if (flag_print_class_info)
}
JCF_FILL (jcf, 26);
JCF_SKIP (jcf, 2);
- general_purpose_bits = JCF_readu2_le (jcf);
+ (void) /* general_purpose_bits = */ JCF_readu2_le (jcf);
compression_method = JCF_readu2_le (jcf);
JCF_SKIP (jcf, 8);
compressed_size = JCF_readu4_le (jcf);