|
@@ -0,0 +1,910 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
|
+ *
|
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
|
+ *
|
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
|
+ * accompanied this code).
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
+ *
|
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
|
+ * questions.
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+package sun.tools.javap;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.io.*;
|
|
|
+
|
|
|
+import static sun.tools.javap.RuntimeConstants.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Program to print information about class files
|
|
|
+ *
|
|
|
+ * @author Sucheta Dambalkar
|
|
|
+ */
|
|
|
+public class JavapPrinter {
|
|
|
+ JavapEnvironment env;
|
|
|
+ ClassData cls;
|
|
|
+ byte[] code;
|
|
|
+ String lP= "";
|
|
|
+ PrintWriter out;
|
|
|
+
|
|
|
+ public JavapPrinter(InputStream cname, PrintWriter out, JavapEnvironment env){
|
|
|
+ this.out = out;
|
|
|
+ this.cls = new ClassData(cname);
|
|
|
+ this.env = env;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Entry point to print class file information.
|
|
|
+ */
|
|
|
+ public void print(){
|
|
|
+ printclassHeader();
|
|
|
+ printfields();
|
|
|
+ printMethods();
|
|
|
+ printend();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print a description of the class (not members).
|
|
|
+ */
|
|
|
+ public void printclassHeader(){
|
|
|
+ String srcName="";
|
|
|
+ if ((srcName = cls.getSourceName()) != "null") // requires debug info
|
|
|
+ out.println("Compiled from " + javaclassname(srcName));
|
|
|
+
|
|
|
+ if(cls.isInterface()) {
|
|
|
+ // The only useful access modifier of an interface is
|
|
|
+ // public; interfaces are always marked as abstract and
|
|
|
+ // cannot be final.
|
|
|
+ out.print((cls.isPublic()?"public ":"") +
|
|
|
+ "interface "+ javaclassname(cls.getClassName()));
|
|
|
+ }
|
|
|
+ else if(cls.isClass()) {
|
|
|
+ String []accflags = cls.getAccess();
|
|
|
+ printAccess(accflags);
|
|
|
+ out.print("class "+ javaclassname(cls.getClassName()));
|
|
|
+
|
|
|
+ if(cls.getSuperClassName() != null){
|
|
|
+ out.print(" extends " + javaclassname(cls.getSuperClassName()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String []interfacelist = cls.getSuperInterfaces();
|
|
|
+ if(interfacelist.length > 0){
|
|
|
+ if(cls.isClass()) {
|
|
|
+ out.print(" implements ");
|
|
|
+ }
|
|
|
+ else if(cls.isInterface()){
|
|
|
+ out.print(" extends ");
|
|
|
+ }
|
|
|
+
|
|
|
+ for(int j = 0; j < interfacelist.length; j++){
|
|
|
+ out.print(javaclassname(interfacelist[j]));
|
|
|
+
|
|
|
+ if((j+1) < interfacelist.length) {
|
|
|
+ out.print(",");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Print class attribute information.
|
|
|
+ if((env.showallAttr) || (env.showVerbose)){
|
|
|
+ printClassAttributes();
|
|
|
+ }
|
|
|
+ // Print verbose output.
|
|
|
+ if(env.showVerbose){
|
|
|
+ printverbosecls();
|
|
|
+ }
|
|
|
+ out.println("{");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print verbose output.
|
|
|
+ */
|
|
|
+ public void printverbosecls(){
|
|
|
+ out.println(" minor version: "+cls.getMinor_version());
|
|
|
+ out.println(" major version: "+cls.getMajor_version());
|
|
|
+ out.println(" Constant pool:");
|
|
|
+ printcp();
|
|
|
+ env.showallAttr = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print class attribute information.
|
|
|
+ */
|
|
|
+ public void printClassAttributes(){
|
|
|
+ out.println();
|
|
|
+ AttrData[] clsattrs = cls.getAttributes();
|
|
|
+ for(int i = 0; i < clsattrs.length; i++){
|
|
|
+ String clsattrname = clsattrs[i].getAttrName();
|
|
|
+ if(clsattrname.equals("SourceFile")){
|
|
|
+ out.println(" SourceFile: "+ cls.getSourceName());
|
|
|
+ }else if(clsattrname.equals("InnerClasses")){
|
|
|
+ printInnerClasses();
|
|
|
+ }else {
|
|
|
+ printAttrData(clsattrs[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print the fields
|
|
|
+ */
|
|
|
+ public void printfields(){
|
|
|
+ FieldData[] fields = cls.getFields();
|
|
|
+ for(int f = 0; f < fields.length; f++){
|
|
|
+ String[] accflags = fields[f].getAccess();
|
|
|
+ if(checkAccess(accflags)){
|
|
|
+ if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
|
|
|
+ || env.showInternalSigs || env.showallAttr)){
|
|
|
+ out.print(" ");
|
|
|
+ }
|
|
|
+ printAccess(accflags);
|
|
|
+ out.println(fields[f].getType()+" " +fields[f].getName()+";");
|
|
|
+ if (env.showInternalSigs) {
|
|
|
+ out.println(" Signature: " + (fields[f].getInternalSig()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // print field attribute information.
|
|
|
+ if (env.showallAttr){
|
|
|
+ printFieldAttributes(fields[f]);
|
|
|
+
|
|
|
+ }
|
|
|
+ if((env.showDisassembled) || (env.showLineAndLocal)){
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /* print field attribute information. */
|
|
|
+ public void printFieldAttributes(FieldData field){
|
|
|
+ Vector fieldattrs = field.getAttributes();
|
|
|
+ for(int j = 0; j < fieldattrs.size(); j++){
|
|
|
+ String fieldattrname = ((AttrData)fieldattrs.elementAt(j)).getAttrName();
|
|
|
+ if(fieldattrname.equals("ConstantValue")){
|
|
|
+ printConstantValue(field);
|
|
|
+ }else if (fieldattrname.equals("Deprecated")){
|
|
|
+ out.println("Deprecated: "+ field.isDeprecated());
|
|
|
+ }else if (fieldattrname.equals("Synthetic")){
|
|
|
+ out.println(" Synthetic: "+ field.isSynthetic());
|
|
|
+ }else {
|
|
|
+ printAttrData((AttrData)fieldattrs.elementAt(j));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print the methods
|
|
|
+ */
|
|
|
+ public void printMethods(){
|
|
|
+ MethodData[] methods = cls.getMethods();
|
|
|
+ for(int m = 0; m < methods.length; m++){
|
|
|
+ String[] accflags = methods[m].getAccess();
|
|
|
+ if(checkAccess(accflags)){
|
|
|
+ if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
|
|
|
+ || env.showInternalSigs || env.showallAttr)){
|
|
|
+ out.print(" ");
|
|
|
+ }
|
|
|
+ printMethodSignature(methods[m], accflags);
|
|
|
+ printExceptions(methods[m]);
|
|
|
+ out.println(";");
|
|
|
+
|
|
|
+ // Print internal signature of method.
|
|
|
+ if (env.showInternalSigs){
|
|
|
+ out.println(" Signature: " + (methods[m].getInternalSig()));
|
|
|
+ }
|
|
|
+
|
|
|
+ //Print disassembled code.
|
|
|
+ if(env.showDisassembled && ! env.showallAttr) {
|
|
|
+ printcodeSequence(methods[m]);
|
|
|
+ printExceptionTable(methods[m]);
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Print line and local variable attribute information.
|
|
|
+ if (env.showLineAndLocal) {
|
|
|
+ printLineNumTable(methods[m]);
|
|
|
+ printLocVarTable(methods[m]);
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Print method attribute information.
|
|
|
+ if (env.showallAttr){
|
|
|
+ printMethodAttributes(methods[m]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print method signature.
|
|
|
+ */
|
|
|
+ public void printMethodSignature(MethodData method, String[] accflags){
|
|
|
+ printAccess(accflags);
|
|
|
+
|
|
|
+ if((method.getName()).equals("<init>")){
|
|
|
+ out.print(javaclassname(cls.getClassName()));
|
|
|
+ out.print(method.getParameters());
|
|
|
+ }else if((method.getName()).equals("<clinit>")){
|
|
|
+ out.print("{}");
|
|
|
+ }else{
|
|
|
+ out.print(method.getReturnType()+" ");
|
|
|
+ out.print(method.getName());
|
|
|
+ out.print(method.getParameters());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * print method attribute information.
|
|
|
+ */
|
|
|
+ public void printMethodAttributes(MethodData method){
|
|
|
+ Vector methodattrs = method.getAttributes();
|
|
|
+ Vector codeattrs = method.getCodeAttributes();
|
|
|
+ for(int k = 0; k < methodattrs.size(); k++){
|
|
|
+ String methodattrname = ((AttrData)methodattrs.elementAt(k)).getAttrName();
|
|
|
+ if(methodattrname.equals("Code")){
|
|
|
+ printcodeSequence(method);
|
|
|
+ printExceptionTable(method);
|
|
|
+ for(int c = 0; c < codeattrs.size(); c++){
|
|
|
+ String codeattrname = ((AttrData)codeattrs.elementAt(c)).getAttrName();
|
|
|
+ if(codeattrname.equals("LineNumberTable")){
|
|
|
+ printLineNumTable(method);
|
|
|
+ }else if(codeattrname.equals("LocalVariableTable")){
|
|
|
+ printLocVarTable(method);
|
|
|
+ }else if(codeattrname.equals("StackMapTable")) {
|
|
|
+ // Java SE JSR 202 stack map tables
|
|
|
+ printStackMapTable(method);
|
|
|
+ }else if(codeattrname.equals("StackMap")) {
|
|
|
+ // Java ME CLDC stack maps
|
|
|
+ printStackMap(method);
|
|
|
+ } else {
|
|
|
+ printAttrData((AttrData)codeattrs.elementAt(c));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else if(methodattrname.equals("Exceptions")){
|
|
|
+ out.println(" Exceptions: ");
|
|
|
+ printExceptions(method);
|
|
|
+ }else if (methodattrname.equals("Deprecated")){
|
|
|
+ out.println(" Deprecated: "+ method.isDeprecated());
|
|
|
+ }else if (methodattrname.equals("Synthetic")){
|
|
|
+ out.println(" Synthetic: "+ method.isSynthetic());
|
|
|
+ }else {
|
|
|
+ printAttrData((AttrData)methodattrs.elementAt(k));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print exceptions.
|
|
|
+ */
|
|
|
+ public void printExceptions(MethodData method){
|
|
|
+ int []exc_index_table = method.get_exc_index_table();
|
|
|
+ if (exc_index_table != null) {
|
|
|
+ if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
|
|
|
+ || env.showInternalSigs || env.showallAttr)){
|
|
|
+ out.print(" ");
|
|
|
+ }
|
|
|
+ out.print(" throws ");
|
|
|
+ int k;
|
|
|
+ int l = exc_index_table.length;
|
|
|
+
|
|
|
+ for (k=0; k<l; k++) {
|
|
|
+ out.print(javaclassname(cls.getClassName(exc_index_table[k])));
|
|
|
+ if (k<l-1) out.print(", ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print code sequence.
|
|
|
+ */
|
|
|
+ public void printcodeSequence(MethodData method){
|
|
|
+ code = method.getCode();
|
|
|
+ if(code != null){
|
|
|
+ out.println(" Code:");
|
|
|
+ if(env.showVerbose){
|
|
|
+ printVerboseHeader(method);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int pc=0; pc < code.length; ) {
|
|
|
+ out.print(" "+pc+":\t");
|
|
|
+ pc=pc+printInstr(pc);
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print instructions.
|
|
|
+ */
|
|
|
+ public int printInstr(int pc){
|
|
|
+ int opcode = getUbyte(pc);
|
|
|
+ int opcode2;
|
|
|
+ String mnem;
|
|
|
+ switch (opcode) {
|
|
|
+ case opc_nonpriv:
|
|
|
+ case opc_priv:
|
|
|
+ opcode2 = getUbyte(pc+1);
|
|
|
+ mnem=Tables.opcName((opcode<<8)+opcode2);
|
|
|
+ if (mnem==null)
|
|
|
+ // assume all (even nonexistent) priv and nonpriv instructions
|
|
|
+ // are 2 bytes long
|
|
|
+ mnem=Tables.opcName(opcode)+" "+opcode2;
|
|
|
+ out.print(mnem);
|
|
|
+ return 2;
|
|
|
+ case opc_wide: {
|
|
|
+ opcode2 = getUbyte(pc+1);
|
|
|
+ mnem=Tables.opcName((opcode<<8)+opcode2);
|
|
|
+ if (mnem==null) {
|
|
|
+ // nonexistent opcode - but we have to print something
|
|
|
+ out.print("bytecode "+opcode);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ out.print(mnem+" "+getUShort(pc+2));
|
|
|
+ if (opcode2==opc_iinc) {
|
|
|
+ out.print(", "+getShort(pc+4));
|
|
|
+ return 6;
|
|
|
+ }
|
|
|
+ return 4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mnem=Tables.opcName(opcode);
|
|
|
+ if (mnem==null) {
|
|
|
+ // nonexistent opcode - but we have to print something
|
|
|
+ out.print("bytecode "+opcode);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ if (opcode>opc_jsr_w) {
|
|
|
+ // pseudo opcodes should be printed as bytecodes
|
|
|
+ out.print("bytecode "+opcode);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ out.print(Tables.opcName(opcode));
|
|
|
+ switch (opcode) {
|
|
|
+ case opc_aload: case opc_astore:
|
|
|
+ case opc_fload: case opc_fstore:
|
|
|
+ case opc_iload: case opc_istore:
|
|
|
+ case opc_lload: case opc_lstore:
|
|
|
+ case opc_dload: case opc_dstore:
|
|
|
+ case opc_ret:
|
|
|
+ out.print("\t"+getUbyte(pc+1));
|
|
|
+ return 2;
|
|
|
+ case opc_iinc:
|
|
|
+ out.print("\t"+getUbyte(pc+1)+", "+getbyte(pc+2));
|
|
|
+ return 3;
|
|
|
+ case opc_tableswitch:{
|
|
|
+ int tb=align(pc+1);
|
|
|
+ int default_skip = getInt(tb); /* default skip pamount */
|
|
|
+ int low = getInt(tb+4);
|
|
|
+ int high = getInt(tb+8);
|
|
|
+ int count = high - low;
|
|
|
+ out.print("{ //"+low+" to "+high);
|
|
|
+ for (int i = 0; i <= count; i++)
|
|
|
+ out.print( "\n\t\t" + (i+low) + ": "+lP+(pc+getInt(tb+12+4*i))+";");
|
|
|
+ out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
|
|
|
+ return tb-pc+16+count*4;
|
|
|
+ }
|
|
|
+
|
|
|
+ case opc_lookupswitch:{
|
|
|
+ int tb=align(pc+1);
|
|
|
+ int default_skip = getInt(tb);
|
|
|
+ int npairs = getInt(tb+4);
|
|
|
+ out.print("{ //"+npairs);
|
|
|
+ for (int i = 1; i <= npairs; i++)
|
|
|
+ out.print("\n\t\t"+getInt(tb+i*8)
|
|
|
+ +": "+lP+(pc+getInt(tb+4+i*8))+";"
|
|
|
+ );
|
|
|
+ out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
|
|
|
+ return tb-pc+(npairs+1)*8;
|
|
|
+ }
|
|
|
+ case opc_newarray:
|
|
|
+ int type=getUbyte(pc+1);
|
|
|
+ switch (type) {
|
|
|
+ case T_BOOLEAN:out.print(" boolean");break;
|
|
|
+ case T_BYTE: out.print(" byte"); break;
|
|
|
+ case T_CHAR: out.print(" char"); break;
|
|
|
+ case T_SHORT: out.print(" short"); break;
|
|
|
+ case T_INT: out.print(" int"); break;
|
|
|
+ case T_LONG: out.print(" long"); break;
|
|
|
+ case T_FLOAT: out.print(" float"); break;
|
|
|
+ case T_DOUBLE: out.print(" double"); break;
|
|
|
+ case T_CLASS: out.print(" class"); break;
|
|
|
+ default: out.print(" BOGUS TYPE:"+type);
|
|
|
+ }
|
|
|
+ return 2;
|
|
|
+
|
|
|
+ case opc_anewarray: {
|
|
|
+ int index = getUShort(pc+1);
|
|
|
+ out.print("\t#"+index+"; //");
|
|
|
+ PrintConstant(index);
|
|
|
+ return 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ case opc_sipush:
|
|
|
+ out.print("\t"+getShort(pc+1));
|
|
|
+ return 3;
|
|
|
+
|
|
|
+ case opc_bipush:
|
|
|
+ out.print("\t"+getbyte(pc+1));
|
|
|
+ return 2;
|
|
|
+
|
|
|
+ case opc_ldc: {
|
|
|
+ int index = getUbyte(pc+1);
|
|
|
+ out.print("\t#"+index+"; //");
|
|
|
+ PrintConstant(index);
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ case opc_ldc_w: case opc_ldc2_w:
|
|
|
+ case opc_instanceof: case opc_checkcast:
|
|
|
+ case opc_new:
|
|
|
+ case opc_putstatic: case opc_getstatic:
|
|
|
+ case opc_putfield: case opc_getfield:
|
|
|
+ case opc_invokevirtual:
|
|
|
+ case opc_invokespecial:
|
|
|
+ case opc_invokestatic: {
|
|
|
+ int index = getUShort(pc+1);
|
|
|
+ out.print("\t#"+index+"; //");
|
|
|
+ PrintConstant(index);
|
|
|
+ return 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ case opc_invokeinterface: {
|
|
|
+ int index = getUShort(pc+1), nargs=getUbyte(pc+3);
|
|
|
+ out.print("\t#"+index+", "+nargs+"; //");
|
|
|
+ PrintConstant(index);
|
|
|
+ return 5;
|
|
|
+ }
|
|
|
+
|
|
|
+ case opc_multianewarray: {
|
|
|
+ int index = getUShort(pc+1), dimensions=getUbyte(pc+3);
|
|
|
+ out.print("\t#"+index+", "+dimensions+"; //");
|
|
|
+ PrintConstant(index);
|
|
|
+ return 4;
|
|
|
+ }
|
|
|
+ case opc_jsr: case opc_goto:
|
|
|
+ case opc_ifeq: case opc_ifge: case opc_ifgt:
|
|
|
+ case opc_ifle: case opc_iflt: case opc_ifne:
|
|
|
+ case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
|
|
|
+ case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
|
|
|
+ case opc_if_acmpeq: case opc_if_acmpne:
|
|
|
+ case opc_ifnull: case opc_ifnonnull:
|
|
|
+ out.print("\t"+lP+(pc + getShort(pc+1)) );
|
|
|
+ return 3;
|
|
|
+
|
|
|
+ case opc_jsr_w:
|
|
|
+ case opc_goto_w:
|
|
|
+ out.print("\t"+lP+(pc + getInt(pc+1)));
|
|
|
+ return 5;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Print code attribute details.
|
|
|
+ */
|
|
|
+ public void printVerboseHeader(MethodData method) {
|
|
|
+ int argCount = method.getArgumentlength();
|
|
|
+ if (!method.isStatic())
|
|
|
+ ++argCount; // for 'this'
|
|
|
+
|
|
|
+ out.println(" Stack=" + method.getMaxStack()
|
|
|
+ + ", Locals=" + method.getMaxLocals()
|
|
|
+ + ", Args_size=" + argCount);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print the exception table for this method code
|
|
|
+ */
|
|
|
+ void printExceptionTable(MethodData method){//throws IOException
|
|
|
+ Vector exception_table = method.getexception_table();
|
|
|
+ if (exception_table.size() > 0) {
|
|
|
+ out.println(" Exception table:");
|
|
|
+ out.println(" from to target type");
|
|
|
+ for (int idx = 0; idx < exception_table.size(); ++idx) {
|
|
|
+ TrapData handler = (TrapData)exception_table.elementAt(idx);
|
|
|
+ printFixedWidthInt(handler.start_pc, 6);
|
|
|
+ printFixedWidthInt(handler.end_pc, 6);
|
|
|
+ printFixedWidthInt(handler.handler_pc, 6);
|
|
|
+ out.print(" ");
|
|
|
+ int catch_cpx = handler.catch_cpx;
|
|
|
+ if (catch_cpx == 0) {
|
|
|
+ out.println("any");
|
|
|
+ }else {
|
|
|
+ out.print("Class ");
|
|
|
+ out.println(cls.getClassName(catch_cpx));
|
|
|
+ out.println("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print LineNumberTable attribute information.
|
|
|
+ */
|
|
|
+ public void printLineNumTable(MethodData method) {
|
|
|
+ int numlines = method.getnumlines();
|
|
|
+ Vector lin_num_tb = method.getlin_num_tb();
|
|
|
+ if( lin_num_tb.size() > 0){
|
|
|
+ out.println(" LineNumberTable: ");
|
|
|
+ for (int i=0; i<numlines; i++) {
|
|
|
+ LineNumData linnumtb_entry=(LineNumData)lin_num_tb.elementAt(i);
|
|
|
+ out.println(" line " + linnumtb_entry.line_number + ": "
|
|
|
+ + linnumtb_entry.start_pc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print LocalVariableTable attribute information.
|
|
|
+ */
|
|
|
+ public void printLocVarTable(MethodData method){
|
|
|
+ int siz = method.getloc_var_tbsize();
|
|
|
+ if(siz > 0){
|
|
|
+ out.println(" LocalVariableTable: ");
|
|
|
+ out.print(" ");
|
|
|
+ out.println("Start Length Slot Name Signature");
|
|
|
+ }
|
|
|
+ Vector loc_var_tb = method.getloc_var_tb();
|
|
|
+
|
|
|
+ for (int i=0; i<siz; i++) {
|
|
|
+ LocVarData entry=(LocVarData)loc_var_tb.elementAt(i);
|
|
|
+
|
|
|
+ out.println(" "+entry.start_pc+" "+entry.length+" "+
|
|
|
+ entry.slot+" "+cls.StringValue(entry.name_cpx) +
|
|
|
+ " "+cls.StringValue(entry.sig_cpx));
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print StackMap attribute information.
|
|
|
+ */
|
|
|
+ public void printStackMap(MethodData method) {
|
|
|
+ StackMapData[] stack_map_tb = method.getStackMap();
|
|
|
+ int number_of_entries = stack_map_tb.length;
|
|
|
+ if (number_of_entries > 0) {
|
|
|
+ out.println(" StackMap: number_of_entries = " + number_of_entries);
|
|
|
+
|
|
|
+ for (StackMapData frame : stack_map_tb) {
|
|
|
+ frame.print(this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print StackMapTable attribute information.
|
|
|
+ */
|
|
|
+ public void printStackMapTable(MethodData method) {
|
|
|
+ StackMapTableData[] stack_map_tb = method.getStackMapTable();
|
|
|
+ int number_of_entries = stack_map_tb.length;
|
|
|
+ if (number_of_entries > 0) {
|
|
|
+ out.println(" StackMapTable: number_of_entries = " + number_of_entries);
|
|
|
+
|
|
|
+ for (StackMapTableData frame : stack_map_tb) {
|
|
|
+ frame.print(this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ void printMap(String name, int[] map) {
|
|
|
+ out.print(name);
|
|
|
+ for (int i=0; i<map.length; i++) {
|
|
|
+ int fulltype = map[i];
|
|
|
+ int type = fulltype & 0xFF;
|
|
|
+ int argument = fulltype >> 8;
|
|
|
+ switch (type) {
|
|
|
+ case ITEM_Object:
|
|
|
+ out.print(" ");
|
|
|
+ PrintConstant(argument);
|
|
|
+ break;
|
|
|
+ case ITEM_NewObject:
|
|
|
+ out.print(" " + Tables.mapTypeName(type));
|
|
|
+ out.print(" " + argument);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ out.print(" " + Tables.mapTypeName(type));
|
|
|
+ }
|
|
|
+ out.print( (i==(map.length-1)? ' ' : ','));
|
|
|
+ }
|
|
|
+ out.println("]");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print ConstantValue attribute information.
|
|
|
+ */
|
|
|
+ public void printConstantValue(FieldData field){
|
|
|
+ out.print(" Constant value: ");
|
|
|
+ int cpx = (field.getConstantValueIndex());
|
|
|
+ byte tag=0;
|
|
|
+ try {
|
|
|
+ tag=cls.getTag(cpx);
|
|
|
+
|
|
|
+ } catch (IndexOutOfBoundsException e) {
|
|
|
+ out.print("Error:");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (tag) {
|
|
|
+ case CONSTANT_METHOD:
|
|
|
+ case CONSTANT_INTERFACEMETHOD:
|
|
|
+ case CONSTANT_FIELD: {
|
|
|
+ CPX2 x = (CPX2)(cls.getCpoolEntry(cpx));
|
|
|
+ if (x.cpx1 == cls.getthis_cpx()) {
|
|
|
+ // don't print class part for local references
|
|
|
+ cpx=x.cpx2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print InnerClass attribute information.
|
|
|
+ */
|
|
|
+ public void printInnerClasses(){//throws ioexception
|
|
|
+
|
|
|
+ InnerClassData[] innerClasses = cls.getInnerClasses();
|
|
|
+ if(innerClasses != null){
|
|
|
+ if(innerClasses.length > 0){
|
|
|
+ out.print(" ");
|
|
|
+ out.println("InnerClass: ");
|
|
|
+ for(int i = 0 ; i < innerClasses.length; i++){
|
|
|
+ out.print(" ");
|
|
|
+ //access
|
|
|
+ String[] accflags = innerClasses[i].getAccess();
|
|
|
+ if(checkAccess(accflags)){
|
|
|
+ printAccess(accflags);
|
|
|
+ if (innerClasses[i].inner_name_index!=0) {
|
|
|
+ out.print("#"+innerClasses[i].inner_name_index+"= ");
|
|
|
+ }
|
|
|
+ out.print("#"+innerClasses[i].inner_class_info_index);
|
|
|
+ if (innerClasses[i].outer_class_info_index!=0) {
|
|
|
+ out.print(" of #"+innerClasses[i].outer_class_info_index);
|
|
|
+ }
|
|
|
+ out.print("; //");
|
|
|
+ if (innerClasses[i].inner_name_index!=0) {
|
|
|
+ out.print(cls.getName(innerClasses[i].inner_name_index)+"=");
|
|
|
+ }
|
|
|
+ PrintConstant(innerClasses[i].inner_class_info_index);
|
|
|
+ if (innerClasses[i].outer_class_info_index!=0) {
|
|
|
+ out.print(" of ");
|
|
|
+ PrintConstant(innerClasses[i].outer_class_info_index);
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print constant pool information.
|
|
|
+ */
|
|
|
+ public void printcp(){
|
|
|
+ int cpx = 1 ;
|
|
|
+
|
|
|
+ while (cpx < cls.getCpoolCount()) {
|
|
|
+ out.print("const #"+cpx+" = ");
|
|
|
+ cpx+=PrintlnConstantEntry(cpx);
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print constant pool entry information.
|
|
|
+ */
|
|
|
+ public int PrintlnConstantEntry(int cpx) {
|
|
|
+ int size=1;
|
|
|
+ byte tag=0;
|
|
|
+ try {
|
|
|
+ tag=cls.getTag(cpx);
|
|
|
+ } catch (IndexOutOfBoundsException e) {
|
|
|
+ out.println(" <Incorrect CP index>");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ out.print(cls.StringTag(cpx)+"\t");
|
|
|
+ Object x=cls.getCpoolEntryobj(cpx);
|
|
|
+ if (x==null) {
|
|
|
+ switch (tag) {
|
|
|
+ case CONSTANT_LONG:
|
|
|
+ case CONSTANT_DOUBLE:
|
|
|
+ size=2;
|
|
|
+ }
|
|
|
+ out.println("null;");
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+ String str=cls.StringValue(cpx);
|
|
|
+
|
|
|
+ switch (tag) {
|
|
|
+ case CONSTANT_CLASS:
|
|
|
+ case CONSTANT_STRING:
|
|
|
+ out.println("#"+(((CPX)x).cpx)+";\t// "+str);
|
|
|
+ break;
|
|
|
+ case CONSTANT_FIELD:
|
|
|
+ case CONSTANT_METHOD:
|
|
|
+ case CONSTANT_INTERFACEMETHOD:
|
|
|
+ out.println("#"+((CPX2)x).cpx1+".#"+((CPX2)x).cpx2+";\t// "+str);
|
|
|
+ break;
|
|
|
+ case CONSTANT_NAMEANDTYPE:
|
|
|
+ out.println("#"+((CPX2)x).cpx1+":#"+((CPX2)x).cpx2+";// "+str);
|
|
|
+ break;
|
|
|
+ case CONSTANT_LONG:
|
|
|
+ case CONSTANT_DOUBLE:
|
|
|
+ size=2;
|
|
|
+ default:
|
|
|
+ out.println(str+";");
|
|
|
+ }
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Checks access of class, field or method.
|
|
|
+ */
|
|
|
+ public boolean checkAccess(String accflags[]){
|
|
|
+
|
|
|
+ boolean ispublic = false;
|
|
|
+ boolean isprotected = false;
|
|
|
+ boolean isprivate = false;
|
|
|
+ boolean ispackage = false;
|
|
|
+
|
|
|
+ for(int i= 0; i < accflags.length; i++){
|
|
|
+ if(accflags[i].equals("public")) ispublic = true;
|
|
|
+ else if (accflags[i].equals("protected")) isprotected = true;
|
|
|
+ else if (accflags[i].equals("private")) isprivate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!(ispublic || isprotected || isprivate)) ispackage = true;
|
|
|
+
|
|
|
+ if((env.showAccess == env.PUBLIC) && (isprotected || isprivate || ispackage)) return false;
|
|
|
+ else if((env.showAccess == env.PROTECTED) && (isprivate || ispackage)) return false;
|
|
|
+ else if((env.showAccess == env.PACKAGE) && (isprivate)) return false;
|
|
|
+ else return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Prints access of class, field or method.
|
|
|
+ */
|
|
|
+ public void printAccess(String []accflags){
|
|
|
+ for(int j = 0; j < accflags.length; j++){
|
|
|
+ out.print(accflags[j]+" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print an integer so that it takes 'length' characters in
|
|
|
+ * the output. Temporary until formatting code is stable.
|
|
|
+ */
|
|
|
+ public void printFixedWidthInt(long x, int length) {
|
|
|
+ CharArrayWriter baStream = new CharArrayWriter();
|
|
|
+ PrintWriter pStream = new PrintWriter(baStream);
|
|
|
+ pStream.print(x);
|
|
|
+ String str = baStream.toString();
|
|
|
+ for (int cnt = length - str.length(); cnt > 0; --cnt)
|
|
|
+ out.print(' ');
|
|
|
+ out.print(str);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected int getbyte (int pc) {
|
|
|
+ return code[pc];
|
|
|
+ }
|
|
|
+
|
|
|
+ protected int getUbyte (int pc) {
|
|
|
+ return code[pc]&0xFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ int getShort (int pc) {
|
|
|
+ return (code[pc]<<8) | (code[pc+1]&0xFF);
|
|
|
+ }
|
|
|
+
|
|
|
+ int getUShort (int pc) {
|
|
|
+ return ((code[pc]<<8) | (code[pc+1]&0xFF))&0xFFFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected int getInt (int pc) {
|
|
|
+ return (getShort(pc)<<16) | (getShort(pc+2)&0xFFFF);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print constant value at that index.
|
|
|
+ */
|
|
|
+ void PrintConstant(int cpx) {
|
|
|
+ if (cpx==0) {
|
|
|
+ out.print("#0");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ byte tag=0;
|
|
|
+ try {
|
|
|
+ tag=cls.getTag(cpx);
|
|
|
+
|
|
|
+ } catch (IndexOutOfBoundsException e) {
|
|
|
+ out.print("#"+cpx);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (tag) {
|
|
|
+ case CONSTANT_METHOD:
|
|
|
+ case CONSTANT_INTERFACEMETHOD:
|
|
|
+ case CONSTANT_FIELD: {
|
|
|
+ // CPX2 x=(CPX2)(cpool[cpx]);
|
|
|
+ CPX2 x = (CPX2)(cls.getCpoolEntry(cpx));
|
|
|
+ if (x.cpx1 == cls.getthis_cpx()) {
|
|
|
+ // don't print class part for local references
|
|
|
+ cpx=x.cpx2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static int align (int n) {
|
|
|
+ return (n+3) & ~3 ;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void printend(){
|
|
|
+ out.println("}");
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String javaclassname(String name){
|
|
|
+ return name.replace('/','.');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Print attribute data in hex.
|
|
|
+ */
|
|
|
+ public void printAttrData(AttrData attr){
|
|
|
+ byte []data = attr.getData();
|
|
|
+ int i = 0;
|
|
|
+ int j = 0;
|
|
|
+ out.print(" "+attr.getAttrName()+": ");
|
|
|
+ out.println("length = " + cls.toHex(attr.datalen));
|
|
|
+
|
|
|
+ out.print(" ");
|
|
|
+
|
|
|
+
|
|
|
+ while (i < data.length){
|
|
|
+ String databytestring = cls.toHex(data[i]);
|
|
|
+ if(databytestring.equals("0x")) out.print("00");
|
|
|
+ else if(databytestring.substring(2).length() == 1){
|
|
|
+ out.print("0"+databytestring.substring(2));
|
|
|
+ } else{
|
|
|
+ out.print(databytestring.substring(2));
|
|
|
+ }
|
|
|
+
|
|
|
+ j++;
|
|
|
+ if(j == 16) {
|
|
|
+ out.println();
|
|
|
+ out.print(" ");
|
|
|
+ j = 0;
|
|
|
+ }
|
|
|
+ else out.print(" ");
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ out.println();
|
|
|
+ }
|
|
|
+}
|