0N/A/*
2362N/A * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage ilib;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.File;
0N/Aimport java.io.FileOutputStream;
0N/Aimport java.io.DataOutputStream;
0N/Aimport java.io.PrintStream;
0N/Aimport java.io.PrintWriter;
0N/Aimport java.io.CharArrayWriter;
0N/Aimport java.util.List;
0N/Aimport java.util.Iterator;
0N/Aimport java.util.ArrayList;
0N/A
0N/Apublic class ClassDump implements RuntimeConstants {
0N/A
0N/A public static void dump(Options opt,
0N/A ClassLoader loader,
0N/A String className,
0N/A byte[] classfileBuffer) {
0N/A ClassReaderWriter c = new ClassReaderWriter(classfileBuffer);
0N/A (new ClassDump(className, c)).doit();
0N/A }
0N/A
0N/A static boolean verbose = true;
0N/A
0N/A final String className;
0N/A final ClassReaderWriter c;
0N/A private final PrintStream output;
0N/A
0N/A int constantPoolCount;
0N/A int methodsCount;
0N/A
0N/A ClassDump(String className, ClassReaderWriter c) {
0N/A this.className = className;
0N/A this.c = c;
0N/A this.output = System.err;
0N/A }
0N/A
0N/A void doit() {
0N/A int i;
0N/A c.copy(4 + 2 + 2); // magic min/maj version
0N/A constantPoolCount = c.copyU2();
0N/A // copy old constant pool
0N/A c.copyConstantPool(constantPoolCount);
0N/A
0N/A traceln("ConstantPool size: " + constantPoolCount);
0N/A
0N/A c.copy(2 + 2 + 2); // access, this, super
0N/A int interfaceCount = c.copyU2();
0N/A traceln("interfaceCount: " + interfaceCount);
0N/A c.copy(interfaceCount * 2);
0N/A copyFields(); // fields
0N/A copyMethods(); // methods
0N/A int attrCount = c.copyU2();
0N/A traceln("class attrCount: " + attrCount);
0N/A // copy the class attributes
0N/A copyAttrs(attrCount);
0N/A }
0N/A
0N/A
0N/A void copyFields() {
0N/A int count = c.copyU2();
0N/A if (verbose) {
0N/A System.out.println("fields count: " + count);
0N/A }
0N/A for (int i = 0; i < count; ++i) {
0N/A c.copy(6); // access, name, descriptor
0N/A int attrCount = c.copyU2();
0N/A if (verbose) {
0N/A System.out.println("field attr count: " + attrCount);
0N/A }
0N/A copyAttrs(attrCount);
0N/A }
0N/A }
0N/A
0N/A void copyMethods() {
0N/A methodsCount = c.copyU2();
0N/A if (verbose) {
0N/A System.out.println("methods count: " + methodsCount);
0N/A }
0N/A for (int i = 0; i < methodsCount; ++i) {
0N/A copyMethod();
0N/A }
0N/A }
0N/A
0N/A void copyMethod() {
0N/A int accessFlags = c.copyU2();// access flags
0N/A int nameIndex = c.copyU2(); // name
0N/A checkIndex(nameIndex, "Method name");
0N/A String methodName = c.constantPoolString(nameIndex);
0N/A traceln("method: " + methodName);
0N/A int descriptorIndex = c.copyU2(); // descriptor
0N/A checkIndex(descriptorIndex, "Method descriptor");
0N/A int attrCount = c.copyU2(); // attribute count
0N/A if (verbose) {
0N/A System.out.println("method attr count: " + attrCount);
0N/A }
0N/A for (int i = 0; i < attrCount; ++i) {
0N/A copyAttrForMethod(methodName, accessFlags);
0N/A }
0N/A }
0N/A
0N/A void copyAttrs(int attrCount) {
0N/A for (int i = 0; i < attrCount; ++i) {
0N/A copyAttr();
0N/A }
0N/A }
0N/A
0N/A void copyAttr() {
0N/A c.copy(2); // name
0N/A int len = c.copyU4(); // attr len
0N/A if (verbose) {
0N/A System.out.println("attr len: " + len);
0N/A }
0N/A c.copy(len); // attribute info
0N/A }
0N/A
0N/A void copyAttrForMethod(String methodName, int accessFlags) {
0N/A int nameIndex = c.copyU2(); // name
0N/A // check for Code attr
0N/A checkIndex(nameIndex, "Method attr name");
0N/A if (nameIndex == c.codeAttributeIndex) {
0N/A try {
0N/A copyCodeAttr(methodName);
0N/A } catch (IOException exc) {
0N/A System.err.println("Code Exception - " + exc);
0N/A System.exit(1);
0N/A }
0N/A } else {
0N/A int len = c.copyU4(); // attr len
0N/A traceln("method attr len: " + len);
0N/A c.copy(len); // attribute info
0N/A }
0N/A }
0N/A
0N/A void copyAttrForCode() throws IOException {
0N/A int nameIndex = c.copyU2(); // name
0N/A
0N/A checkIndex(nameIndex, "Code attr name");
0N/A int len = c.copyU4(); // attr len
0N/A traceln("code attr len: " + len);
0N/A c.copy(len); // attribute info
0N/A }
0N/A
0N/A void copyCodeAttr(String methodName) throws IOException {
0N/A traceln("Code attr found");
0N/A int attrLength = c.copyU4(); // attr len
0N/A checkLength(attrLength, "Code attr length");
0N/A int maxStack = c.readU2(); // max stack
0N/A c.copyU2(); // max locals
0N/A int codeLength = c.copyU4(); // code length
0N/A checkLength(codeLength, "Code length");
0N/A
0N/A copyExceptionTable();
0N/A
0N/A int attrCount = c.copyU2();
0N/A checkLength(attrCount, "Code attr count");
0N/A for (int i = 0; i < attrCount; ++i) {
0N/A copyAttrForCode();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Copy the exception table for this method code
0N/A */
0N/A void copyExceptionTable() throws IOException {
0N/A int tableLength = c.copyU2(); // exception table len
0N/A checkLength(tableLength, "Exception Table length");
0N/A if (tableLength > 0) {
0N/A traceln();
0N/A traceln("Exception table:");
0N/A traceln(" from:old/new to:old/new target:old/new type");
0N/A for (int tcnt = tableLength; tcnt > 0; --tcnt) {
0N/A int startPC = c.readU2();
0N/A int endPC = c.readU2();
0N/A int handlerPC = c.readU2();
0N/A int catchType = c.copyU2();
0N/A if (verbose) {
0N/A traceFixedWidthInt(startPC, 6);
0N/A traceFixedWidthInt(endPC, 6);
0N/A traceFixedWidthInt(handlerPC, 6);
0N/A trace(" ");
0N/A if (catchType == 0)
0N/A traceln("any");
0N/A else {
0N/A traceln("" + catchType);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void checkIndex(int index, String comment) {
0N/A if (index > constantPoolCount) {
0N/A output.println("ERROR BAD INDEX " + comment + " : " + index);
0N/A } else {
0N/A traceln(comment + " : " + index);
0N/A }
0N/A }
0N/A
0N/A private void checkLength(int length, String comment) {
0N/A if (length > c.inputBytes().length) {
0N/A output.println("ERROR BAD LENGTH " + comment + " : " + length);
0N/A } else {
0N/A traceln(comment + " : " + length);
0N/A }
0N/A }
0N/A
0N/A private void trace(String str) {
0N/A if (verbose) {
0N/A output.print(str);
0N/A }
0N/A }
0N/A
0N/A private void traceln(String str) {
0N/A if (verbose) {
0N/A output.println(str);
0N/A }
0N/A }
0N/A
0N/A private void traceln() {
0N/A if (verbose) {
0N/A output.println();
0N/A }
0N/A }
0N/A
0N/A private void trace(int i) {
0N/A if (verbose) {
0N/A output.print(i);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Print an integer so that it takes 'length' characters in
0N/A * the output. Temporary until formatting code is stable.
0N/A */
0N/A private void traceFixedWidthInt(int x, int length) {
0N/A if (verbose) {
0N/A CharArrayWriter baStream = new CharArrayWriter();
0N/A PrintWriter pStream = new PrintWriter(baStream);
0N/A pStream.print(x);
0N/A String str = baStream.toString();
0N/A for (int cnt = length - str.length(); cnt > 0; --cnt)
0N/A trace(" ");
0N/A trace(str);
0N/A }
0N/A }
0N/A
0N/A
0N/A}