📄 jcf-dump.c
字号:
/* Program to dump out a Java(TM) .class file. Functionally similar to Sun's javap. Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. Java and all Java-based marks are trademarks or registered trademarksof Sun Microsystems, Inc. in the United States and other countries.The Free Software Foundation is independent of Sun Microsystems, Inc. *//* Written by Per Bothner <bothner@cygnus.com>, February 1996. *//* jcf-dump is a program to print out the contents of class files. Usage: jcf-dump [FLAGS] CLASS Each CLASS is either: + the name of a class in the CLASSPATH (e.g "java.lang.String"), or + the name of a class *file* (e.g. "/home/me/work/package/Foo.class"). + The name of a .zip or .jar file (which prints all the classes in the archive). OPTIONS: -c Dis-assemble each method. -classpath PATH Overrides $CLASSPATH. --print-main Print nothing if there is no valid "main" method; otherwise, print only the class name. --javap Print output in the style of Sun's javap program. VERY UNFINISHED. */ #include "config.h"#include "system.h"#include "jcf.h"#include "tree.h"#include "java-tree.h"/* Outout file. */FILE *out;/* Name of output file, if NULL if stdout. */char *output_file = NULL;int verbose = 0;int flag_disassemble_methods = 0;int flag_print_class_info = 1;int flag_print_constant_pool = 1;int flag_print_fields = 1;int flag_print_methods = 1;int flag_print_attributes = 1;/* Print names of classes that have a "main" method. */int flag_print_main = 0;/* Index in constant pool of this class. */int this_class_index = 0;int class_access_flags = 0;/* Print in format similar to javap. VERY IMCOMPLETE. */int flag_javap_compatible = 0;static int print_access_flags PROTO ((FILE *, uint16, char));static void print_constant_terse PROTO ((FILE*, JCF*, int, int));static void print_constant PROTO ((FILE *, JCF *, int, int));static void print_constant_ref PROTO ((FILE *, JCF *, int));static void disassemble_method PROTO ((JCF*, unsigned char *, int));static void print_name PROTO ((FILE*, JCF*, int));static void print_signature PROTO ((FILE*, JCF*, int, int));static int utf8_equal_string PROTO ((struct JCF*, int, const char *));static int usage PROTO ((void));static void process_class PROTO ((struct JCF *));#define PRINT_SIGNATURE_RESULT_ONLY 1#define PRINT_SIGNATURE_ARGS_ONLY 2static intDEFUN(utf8_equal_string, (jcf, index, value), JCF *jcf AND int index AND const char * value){ if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index) && JPOOL_TAG (jcf, index) == CONSTANT_Utf8) { int len = strlen (value); if (JPOOL_UTF_LENGTH (jcf, index) == len && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0) return 1; } return 0;}#define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \ this_class_index = 0; \ if (flag_print_class_info) \ fprintf (out, \ "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\ (long) MAGIC, (long) MINOR, (long) MAJOR)#define HANDLE_START_CONSTANT_POOL(COUNT) \ if (flag_print_constant_pool) \ fprintf (out, "\nConstant pool (count: %d):\n", COUNT)#define HANDLE_SOURCEFILE(INDEX) \{ fprintf (out, "Attribute "); \ print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \ fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \ print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }#define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \ this_class_index = THIS; \ class_access_flags = ACCESS_FLAGS; \ if (flag_print_class_info) \ { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \ print_access_flags (out, ACCESS_FLAGS, 'c'); \ fputc ('\n', out); \ fprintf (out, "This class: "); \ if (flag_print_constant_pool) \ fprintf (out, "%d=", THIS); \ print_constant_terse (out, jcf, THIS, CONSTANT_Class); \ if (flag_print_constant_pool || SUPER != 0) \ fprintf (out, ", super: "); \ if (flag_print_constant_pool) \ { \ fprintf (out, "%d", SUPER); \ if (SUPER != 0) \ fputc ('=', out); \ } \ if (SUPER != 0) \ print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \ fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \ }#define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \ (flag_print_attributes <= 0)#define HANDLE_CLASS_INTERFACE(INDEX) \ if (flag_print_class_info) \ { fprintf (out, "- Implements: %d=", INDEX); \ print_constant_terse (out, jcf, INDEX, CONSTANT_Class); \ fputc ('\n', out); }#define HANDLE_START_FIELDS(FIELDS_COUNT) \ if (flag_print_fields) \ fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)#define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \ if (flag_print_fields) \ { fprintf (out, "Field name:"); \ print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \ print_access_flags (out, ACCESS_FLAGS, 'f'); \ fprintf (out, " Signature: "); \ if (flag_print_constant_pool) \ fprintf (out, "%d=", SIGNATURE); \ print_signature (out, jcf, SIGNATURE, 0); \ fputc ('\n', out); } \ else \ flag_print_attributes--;#define HANDLE_END_FIELD() \ if (! flag_print_fields) \ flag_print_attributes++;#define HANDLE_START_METHODS(METHODS_COUNT) \ if (flag_print_methods) \ fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \ else \ flag_print_attributes--;#define HANDLE_END_METHODS() \ if (! flag_print_methods) \ flag_print_attributes++;#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \{ \ if (flag_print_methods) \ { \ if (flag_javap_compatible) \ { \ fprintf (out, " "); \ print_access_flags (out, ACCESS_FLAGS, 'm'); \ fputc (' ', out); \ print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \ fputc (' ', out); \ print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \ print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \ fputc ('\n', out); \ } \ else \ { \ fprintf (out, "\nMethod name:"); \ print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \ print_access_flags (out, ACCESS_FLAGS, 'm'); \ fprintf (out, " Signature: "); \ if (flag_print_constant_pool) \ fprintf (out, "%d=", SIGNATURE); \ print_signature (out, jcf, SIGNATURE, 0); \ fputc ('\n', out); \ } \ } \ if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \ && utf8_equal_string (jcf, NAME, "main") \ && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \ && this_class_index > 0 \ && (class_access_flags & ACC_PUBLIC)) \ { \ print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \ fputc ('\n', out); \ } \}#define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \( fprintf (out, "Attribute "), \ print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \ fprintf (out, ", length:%ld", (long) LENGTH) )#define HANDLE_CONSTANTVALUE(VALUE_INDEX) \( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \ fprintf (out, ", value: "), \ print_constant_ref (out, jcf, VALUE_INDEX), \ fprintf (out, "\n") )#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \{ COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \ fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \ (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \ disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }#define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \ print_exception_table (jcf, ENTRIES, COUNT)#define HANDLE_EXCEPTIONS_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 ex_index = JCF_readu2 (jcf); \ fprintf (out, "%3d: ", i); \ print_constant_ref (out, jcf, ex_index); \ fputc ('\n', out); } }#define HANDLE_LOCALVARIABLETABLE_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: %d=", slot, name_index); \ print_name (out, jcf, name_index); \ fprintf (out, ", type: %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); \ fprintf (out, ", count: %d\n", n); \ if (flag_disassemble_methods) \ for (i = 0; i < n; i++) {\ int start_pc = JCF_readu2 (jcf); \ int line_number = JCF_readu2 (jcf); \ fprintf (out, " line: %d at pc: %d\n", line_number, start_pc); }\ else \ JCF_SKIP (jcf, 4 * n); }#define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \{ COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \ fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }#define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \ if (flag_print_attributes > 0) \ fprintf (out, "\nAttributes (count: %d):\n", attributes_count);#include "javaop.h"static voidDEFUN(print_constant_ref, (stream, jcf, index), FILE *stream AND JCF *jcf AND int index){ fprintf (stream, "#%d=<", index); if (index <= 0 || index >= JPOOL_SIZE(jcf)) fprintf (stream, "out of range"); else print_constant (stream, jcf, index, 1); fprintf (stream, ">");}/* Print the access flags given by FLAGS. The CONTEXT is one of 'c' (class flags), 'f' (field flags), or 'm' (method flags). */static intDEFUN (print_access_flags, (stream, flags, context), FILE *stream AND uint16 flags AND char context){ if (flags & ACC_PUBLIC) fprintf (stream, " public"); if (flags & ACC_PRIVATE) fprintf (stream, " private"); if (flags & ACC_PROTECTED) fprintf (stream, " protected"); if (flags & ACC_STATIC) fprintf (stream, " static"); if (flags & ACC_FINAL) fprintf (stream, " final"); if (flags & ACC_SYNCHRONIZED) { if (context == 'c') fprintf (stream, " super"); else fprintf (stream, " synchronized"); } if (flags & ACC_VOLATILE) fprintf (stream, " volatile"); if (flags & ACC_TRANSIENT) fprintf (stream, " transient"); if (flags & ACC_NATIVE) fprintf (stream, " native"); if (flags & ACC_INTERFACE) fprintf (stream, " interface"); if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");}static voidDEFUN(print_name, (stream, jcf, name_index), FILE* stream AND JCF* jcf AND int name_index){ if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8) fprintf (stream, "<not a UTF8 constant>"); else jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index), JPOOL_UTF_LENGTH (jcf, name_index));}/* If the type of the constant at INDEX matches EXPECTED, print it tersely, otherwise more verbosely. */static voidDEFUN(print_constant_terse, (out, jcf, index, expected), FILE *out AND JCF *jcf AND int index AND int expected){ if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index)) fprintf (out, "<constant pool index %d not in range>", index); else if (JPOOL_TAG (jcf, index) != expected) { fprintf (out, "<Unexpected constant type "); print_constant (out, jcf, index, 1); fprintf (out, ">"); } else print_constant (out, jcf, index, 0);}/* Print the constant at INDEX in JCF's constant pool.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -