aboutsummaryrefslogtreecommitdiff
path: root/gprofng/src/ClassFile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/ClassFile.cc')
-rw-r--r--gprofng/src/ClassFile.cc1639
1 files changed, 1639 insertions, 0 deletions
diff --git a/gprofng/src/ClassFile.cc b/gprofng/src/ClassFile.cc
new file mode 100644
index 0000000..7dd64a7
--- /dev/null
+++ b/gprofng/src/ClassFile.cc
@@ -0,0 +1,1639 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Oracle.
+
+ This file is part of GNU Binutils.
+
+ This program 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 3, 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 of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "DbeSession.h"
+#include "ClassFile.h"
+#include "Function.h"
+#include "StringBuilder.h"
+#include "DbeFile.h"
+
+class ByteCodeInfo
+{
+public:
+
+ ByteCodeInfo (JMethod *_func, int _bci, int _lno)
+ {
+ func = _func;
+ bci = _bci;
+ lno = _lno;
+ };
+
+ JMethod *func;
+ int bci;
+ int lno;
+};
+
+typedef unsigned char u1;
+typedef unsigned short u2;
+typedef unsigned int u4;
+
+// Class File Constants
+#define JAVA_MAGIC 0xcafebabe
+
+enum {
+ // First argument in access_flags_to_str()
+ ClassAccess = 1,
+ FieldAccess,
+ MethodAccess,
+ NestedClassAccess,
+
+ // jdk/src/share/classes/sun/tools/java/RuntimeConstants.java
+ // Type codes
+ T_CLASS = 0x00000002,
+ T_BOOLEAN = 0x00000004,
+ T_CHAR = 0x00000005,
+ T_FLOAT = 0x00000006,
+ T_DOUBLE = 0x00000007,
+ T_BYTE = 0x00000008,
+ T_SHORT = 0x00000009,
+ T_INT = 0x0000000a,
+ T_LONG = 0x0000000b,
+
+// Access and modifier flags
+ ACC_PUBLIC = 0x00000001,
+ ACC_PRIVATE = 0x00000002,
+ ACC_PROTECTED = 0x00000004,
+ ACC_STATIC = 0x00000008,
+ ACC_FINAL = 0x00000010,
+ ACC_SYNCHRONIZED = 0x00000020,
+ ACC_VOLATILE = 0x00000040,
+ ACC_TRANSIENT = 0x00000080,
+ ACC_NATIVE = 0x00000100,
+ ACC_INTERFACE = 0x00000200,
+ ACC_ABSTRACT = 0x00000400,
+ ACC_STRICT = 0x00000800,
+ ACC_SYNTHETIC = 0x00001000,
+ ACC_ANNOTATION = 0x00002000,
+ ACC_ENUM = 0x00004000,
+
+ ACC_SUPER = 0x00000020,
+ ACC_BRIDGE = 0x00000040,
+ ACC_VARARGS = 0x00000080,
+
+// Opcodes
+ opc_try = -3,
+ opc_dead = -2,
+ opc_label = -1,
+ opc_nop = 0,
+ opc_aconst_null = 1,
+ opc_iconst_m1 = 2,
+ opc_iconst_0 = 3,
+ opc_iconst_1 = 4,
+ opc_iconst_2 = 5,
+ opc_iconst_3 = 6,
+ opc_iconst_4 = 7,
+ opc_iconst_5 = 8,
+ opc_lconst_0 = 9,
+ opc_lconst_1 = 10,
+ opc_fconst_0 = 11,
+ opc_fconst_1 = 12,
+ opc_fconst_2 = 13,
+ opc_dconst_0 = 14,
+ opc_dconst_1 = 15,
+ opc_bipush = 16,
+ opc_sipush = 17,
+ opc_ldc = 18,
+ opc_ldc_w = 19,
+ opc_ldc2_w = 20,
+ opc_iload = 21,
+ opc_lload = 22,
+ opc_fload = 23,
+ opc_dload = 24,
+ opc_aload = 25,
+ opc_iload_0 = 26,
+ opc_iload_1 = 27,
+ opc_iload_2 = 28,
+ opc_iload_3 = 29,
+ opc_lload_0 = 30,
+ opc_lload_1 = 31,
+ opc_lload_2 = 32,
+ opc_lload_3 = 33,
+ opc_fload_0 = 34,
+ opc_fload_1 = 35,
+ opc_fload_2 = 36,
+ opc_fload_3 = 37,
+ opc_dload_0 = 38,
+ opc_dload_1 = 39,
+ opc_dload_2 = 40,
+ opc_dload_3 = 41,
+ opc_aload_0 = 42,
+ opc_aload_1 = 43,
+ opc_aload_2 = 44,
+ opc_aload_3 = 45,
+ opc_iaload = 46,
+ opc_laload = 47,
+ opc_faload = 48,
+ opc_daload = 49,
+ opc_aaload = 50,
+ opc_baload = 51,
+ opc_caload = 52,
+ opc_saload = 53,
+ opc_istore = 54,
+ opc_lstore = 55,
+ opc_fstore = 56,
+ opc_dstore = 57,
+ opc_astore = 58,
+ opc_istore_0 = 59,
+ opc_istore_1 = 60,
+ opc_istore_2 = 61,
+ opc_istore_3 = 62,
+ opc_lstore_0 = 63,
+ opc_lstore_1 = 64,
+ opc_lstore_2 = 65,
+ opc_lstore_3 = 66,
+ opc_fstore_0 = 67,
+ opc_fstore_1 = 68,
+ opc_fstore_2 = 69,
+ opc_fstore_3 = 70,
+ opc_dstore_0 = 71,
+ opc_dstore_1 = 72,
+ opc_dstore_2 = 73,
+ opc_dstore_3 = 74,
+ opc_astore_0 = 75,
+ opc_astore_1 = 76,
+ opc_astore_2 = 77,
+ opc_astore_3 = 78,
+ opc_iastore = 79,
+ opc_lastore = 80,
+ opc_fastore = 81,
+ opc_dastore = 82,
+ opc_aastore = 83,
+ opc_bastore = 84,
+ opc_castore = 85,
+ opc_sastore = 86,
+ opc_pop = 87,
+ opc_pop2 = 88,
+ opc_dup = 89,
+ opc_dup_x1 = 90,
+ opc_dup_x2 = 91,
+ opc_dup2 = 92,
+ opc_dup2_x1 = 93,
+ opc_dup2_x2 = 94,
+ opc_swap = 95,
+ opc_iadd = 96,
+ opc_ladd = 97,
+ opc_fadd = 98,
+ opc_dadd = 99,
+ opc_isub = 100,
+ opc_lsub = 101,
+ opc_fsub = 102,
+ opc_dsub = 103,
+ opc_imul = 104,
+ opc_lmul = 105,
+ opc_fmul = 106,
+ opc_dmul = 107,
+ opc_idiv = 108,
+ opc_ldiv = 109,
+ opc_fdiv = 110,
+ opc_ddiv = 111,
+ opc_irem = 112,
+ opc_lrem = 113,
+ opc_frem = 114,
+ opc_drem = 115,
+ opc_ineg = 116,
+ opc_lneg = 117,
+ opc_fneg = 118,
+ opc_dneg = 119,
+ opc_ishl = 120,
+ opc_lshl = 121,
+ opc_ishr = 122,
+ opc_lshr = 123,
+ opc_iushr = 124,
+ opc_lushr = 125,
+ opc_iand = 126,
+ opc_land = 127,
+ opc_ior = 128,
+ opc_lor = 129,
+ opc_ixor = 130,
+ opc_lxor = 131,
+ opc_iinc = 132,
+ opc_i2l = 133,
+ opc_i2f = 134,
+ opc_i2d = 135,
+ opc_l2i = 136,
+ opc_l2f = 137,
+ opc_l2d = 138,
+ opc_f2i = 139,
+ opc_f2l = 140,
+ opc_f2d = 141,
+ opc_d2i = 142,
+ opc_d2l = 143,
+ opc_d2f = 144,
+ opc_i2b = 145,
+ opc_i2c = 146,
+ opc_i2s = 147,
+ opc_lcmp = 148,
+ opc_fcmpl = 149,
+ opc_fcmpg = 150,
+ opc_dcmpl = 151,
+ opc_dcmpg = 152,
+ opc_ifeq = 153,
+ opc_ifne = 154,
+ opc_iflt = 155,
+ opc_ifge = 156,
+ opc_ifgt = 157,
+ opc_ifle = 158,
+ opc_if_icmpeq = 159,
+ opc_if_icmpne = 160,
+ opc_if_icmplt = 161,
+ opc_if_icmpge = 162,
+ opc_if_icmpgt = 163,
+ opc_if_icmple = 164,
+ opc_if_acmpeq = 165,
+ opc_if_acmpne = 166,
+ opc_goto = 167,
+ opc_jsr = 168,
+ opc_ret = 169,
+ opc_tableswitch = 170,
+ opc_lookupswitch = 171,
+ opc_ireturn = 172,
+ opc_lreturn = 173,
+ opc_freturn = 174,
+ opc_dreturn = 175,
+ opc_areturn = 176,
+ opc_return = 177,
+ opc_getstatic = 178,
+ opc_putstatic = 179,
+ opc_getfield = 180,
+ opc_putfield = 181,
+ opc_invokevirtual = 182,
+ opc_invokespecial = 183,
+ opc_invokestatic = 184,
+ opc_invokeinterface = 185,
+ opc_invokedynamic = 186,
+ opc_new = 187,
+ opc_newarray = 188,
+ opc_anewarray = 189,
+ opc_arraylength = 190,
+ opc_athrow = 191,
+ opc_checkcast = 192,
+ opc_instanceof = 193,
+ opc_monitorenter = 194,
+ opc_monitorexit = 195,
+ opc_wide = 196,
+ opc_multianewarray = 197,
+ opc_ifnull = 198,
+ opc_ifnonnull = 199,
+ opc_goto_w = 200,
+ opc_jsr_w = 201,
+ opc_breakpoint = 202,
+
+// Constant table
+ CONSTANT_UTF8 = 1,
+ CONSTANT_UNICODE = 2,
+ CONSTANT_INTEGER = 3,
+ CONSTANT_FLOAT = 4,
+ CONSTANT_LONG = 5,
+ CONSTANT_DOUBLE = 6,
+ CONSTANT_CLASS = 7,
+ CONSTANT_STRING = 8,
+ CONSTANT_FIELD = 9,
+ CONSTANT_METHOD = 10,
+ CONSTANT_INTERFACEMETHOD = 11,
+ CONSTANT_NAMEANDTYPE = 12,
+ CONSTANT_METHODHANDLE = 15,
+ CONSTANT_METHODTYPE = 16,
+ CONSTANT_INVOKEDYNAMIC = 18
+};
+
+static char *opcNames[] = {
+ NTXT ("nop"),
+ NTXT ("aconst_null"),
+ NTXT ("iconst_m1"),
+ NTXT ("iconst_0"),
+ NTXT ("iconst_1"),
+ NTXT ("iconst_2"),
+ NTXT ("iconst_3"),
+ NTXT ("iconst_4"),
+ NTXT ("iconst_5"),
+ NTXT ("lconst_0"),
+ NTXT ("lconst_1"),
+ NTXT ("fconst_0"),
+ NTXT ("fconst_1"),
+ NTXT ("fconst_2"),
+ NTXT ("dconst_0"),
+ NTXT ("dconst_1"),
+ NTXT ("bipush"),
+ NTXT ("sipush"),
+ NTXT ("ldc"),
+ NTXT ("ldc_w"),
+ NTXT ("ldc2_w"),
+ NTXT ("iload"),
+ NTXT ("lload"),
+ NTXT ("fload"),
+ NTXT ("dload"),
+ NTXT ("aload"),
+ NTXT ("iload_0"),
+ NTXT ("iload_1"),
+ NTXT ("iload_2"),
+ NTXT ("iload_3"),
+ NTXT ("lload_0"),
+ NTXT ("lload_1"),
+ NTXT ("lload_2"),
+ NTXT ("lload_3"),
+ NTXT ("fload_0"),
+ NTXT ("fload_1"),
+ NTXT ("fload_2"),
+ NTXT ("fload_3"),
+ NTXT ("dload_0"),
+ NTXT ("dload_1"),
+ NTXT ("dload_2"),
+ NTXT ("dload_3"),
+ NTXT ("aload_0"),
+ NTXT ("aload_1"),
+ NTXT ("aload_2"),
+ NTXT ("aload_3"),
+ NTXT ("iaload"),
+ NTXT ("laload"),
+ NTXT ("faload"),
+ NTXT ("daload"),
+ NTXT ("aaload"),
+ NTXT ("baload"),
+ NTXT ("caload"),
+ NTXT ("saload"),
+ NTXT ("istore"),
+ NTXT ("lstore"),
+ NTXT ("fstore"),
+ NTXT ("dstore"),
+ NTXT ("astore"),
+ NTXT ("istore_0"),
+ NTXT ("istore_1"),
+ NTXT ("istore_2"),
+ NTXT ("istore_3"),
+ NTXT ("lstore_0"),
+ NTXT ("lstore_1"),
+ NTXT ("lstore_2"),
+ NTXT ("lstore_3"),
+ NTXT ("fstore_0"),
+ NTXT ("fstore_1"),
+ NTXT ("fstore_2"),
+ NTXT ("fstore_3"),
+ NTXT ("dstore_0"),
+ NTXT ("dstore_1"),
+ NTXT ("dstore_2"),
+ NTXT ("dstore_3"),
+ NTXT ("astore_0"),
+ NTXT ("astore_1"),
+ NTXT ("astore_2"),
+ NTXT ("astore_3"),
+ NTXT ("iastore"),
+ NTXT ("lastore"),
+ NTXT ("fastore"),
+ NTXT ("dastore"),
+ NTXT ("aastore"),
+ NTXT ("bastore"),
+ NTXT ("castore"),
+ NTXT ("sastore"),
+ NTXT ("pop"),
+ NTXT ("pop2"),
+ NTXT ("dup"),
+ NTXT ("dup_x1"),
+ NTXT ("dup_x2"),
+ NTXT ("dup2"),
+ NTXT ("dup2_x1"),
+ NTXT ("dup2_x2"),
+ NTXT ("swap"),
+ NTXT ("iadd"),
+ NTXT ("ladd"),
+ NTXT ("fadd"),
+ NTXT ("dadd"),
+ NTXT ("isub"),
+ NTXT ("lsub"),
+ NTXT ("fsub"),
+ NTXT ("dsub"),
+ NTXT ("imul"),
+ NTXT ("lmul"),
+ NTXT ("fmul"),
+ NTXT ("dmul"),
+ NTXT ("idiv"),
+ NTXT ("ldiv"),
+ NTXT ("fdiv"),
+ NTXT ("ddiv"),
+ NTXT ("irem"),
+ NTXT ("lrem"),
+ NTXT ("frem"),
+ NTXT ("drem"),
+ NTXT ("ineg"),
+ NTXT ("lneg"),
+ NTXT ("fneg"),
+ NTXT ("dneg"),
+ NTXT ("ishl"),
+ NTXT ("lshl"),
+ NTXT ("ishr"),
+ NTXT ("lshr"),
+ NTXT ("iushr"),
+ NTXT ("lushr"),
+ NTXT ("iand"),
+ NTXT ("land"),
+ NTXT ("ior"),
+ NTXT ("lor"),
+ NTXT ("ixor"),
+ NTXT ("lxor"),
+ NTXT ("iinc"),
+ NTXT ("i2l"),
+ NTXT ("i2f"),
+ NTXT ("i2d"),
+ NTXT ("l2i"),
+ NTXT ("l2f"),
+ NTXT ("l2d"),
+ NTXT ("f2i"),
+ NTXT ("f2l"),
+ NTXT ("f2d"),
+ NTXT ("d2i"),
+ NTXT ("d2l"),
+ NTXT ("d2f"),
+ NTXT ("i2b"),
+ NTXT ("i2c"),
+ NTXT ("i2s"),
+ NTXT ("lcmp"),
+ NTXT ("fcmpl"),
+ NTXT ("fcmpg"),
+ NTXT ("dcmpl"),
+ NTXT ("dcmpg"),
+ NTXT ("ifeq"),
+ NTXT ("ifne"),
+ NTXT ("iflt"),
+ NTXT ("ifge"),
+ NTXT ("ifgt"),
+ NTXT ("ifle"),
+ NTXT ("if_icmpeq"),
+ NTXT ("if_icmpne"),
+ NTXT ("if_icmplt"),
+ NTXT ("if_icmpge"),
+ NTXT ("if_icmpgt"),
+ NTXT ("if_icmple"),
+ NTXT ("if_acmpeq"),
+ NTXT ("if_acmpne"),
+ NTXT ("goto"),
+ NTXT ("jsr"),
+ NTXT ("ret"),
+ NTXT ("tableswitch"),
+ NTXT ("lookupswitch"),
+ NTXT ("ireturn"),
+ NTXT ("lreturn"),
+ NTXT ("freturn"),
+ NTXT ("dreturn"),
+ NTXT ("areturn"),
+ NTXT ("return"),
+ NTXT ("getstatic"),
+ NTXT ("putstatic"),
+ NTXT ("getfield"),
+ NTXT ("putfield"),
+ NTXT ("invokevirtual"),
+ NTXT ("invokespecial"),
+ NTXT ("invokestatic"),
+ NTXT ("invokeinterface"),
+ NTXT ("invokedynamic"),
+ NTXT ("new"),
+ NTXT ("newarray"),
+ NTXT ("anewarray"),
+ NTXT ("arraylength"),
+ NTXT ("athrow"),
+ NTXT ("checkcast"),
+ NTXT ("instanceof"),
+ NTXT ("monitorenter"),
+ NTXT ("monitorexit"),
+ NTXT ("wide"),
+ NTXT ("multianewarray"),
+ NTXT ("ifnull"),
+ NTXT ("ifnonnull"),
+ NTXT ("goto_w"),
+ NTXT ("jsr_w"),
+ NTXT ("breakpoint")
+};
+
+
+#define APPEND_FLAG(len, buf, flag, x) \
+ if (((x) & (flag)) != 0) \
+ { \
+ flag &= ~(x); \
+ AppendString(len, buf, NTXT("%s%s"), delimiter, #x); \
+ delimiter = NTXT("|"); \
+ }
+
+static char *
+access_flags_to_str (int kind, int flag)
+{
+ static char buf[256];
+ size_t len = 0;
+ buf[0] = 0;
+ if (flag == 0)
+ {
+ AppendString (len, buf, NTXT ("0x%x"), (unsigned int) flag);
+ return buf;
+ }
+ const char *delimiter = "";
+ if (kind == ClassAccess)
+ {
+ APPEND_FLAG (len, buf, flag, ACC_FINAL);
+ APPEND_FLAG (len, buf, flag, ACC_SUPER);
+ APPEND_FLAG (len, buf, flag, ACC_INTERFACE);
+ APPEND_FLAG (len, buf, flag, ACC_ABSTRACT);
+ APPEND_FLAG (len, buf, flag, ACC_SYNTHETIC);
+ APPEND_FLAG (len, buf, flag, ACC_ANNOTATION);
+ APPEND_FLAG (len, buf, flag, ACC_ENUM);
+ if (flag)
+ AppendString (len, buf, "%s0x%x", delimiter, (unsigned int) (flag));
+ }
+ else if (kind == FieldAccess)
+ {
+ APPEND_FLAG (len, buf, flag, ACC_PUBLIC);
+ APPEND_FLAG (len, buf, flag, ACC_PRIVATE);
+ APPEND_FLAG (len, buf, flag, ACC_PROTECTED);
+ APPEND_FLAG (len, buf, flag, ACC_STATIC);
+ APPEND_FLAG (len, buf, flag, ACC_FINAL);
+ APPEND_FLAG (len, buf, flag, ACC_VOLATILE);
+ APPEND_FLAG (len, buf, flag, ACC_TRANSIENT);
+ APPEND_FLAG (len, buf, flag, ACC_SYNTHETIC);
+ APPEND_FLAG (len, buf, flag, ACC_ENUM);
+ if (flag)
+ AppendString (len, buf, "%s0x%x", delimiter, (unsigned int) (flag));
+ }
+ else if (kind == MethodAccess)
+ {
+ APPEND_FLAG (len, buf, flag, ACC_PUBLIC);
+ APPEND_FLAG (len, buf, flag, ACC_PRIVATE);
+ APPEND_FLAG (len, buf, flag, ACC_PROTECTED);
+ APPEND_FLAG (len, buf, flag, ACC_STATIC);
+ APPEND_FLAG (len, buf, flag, ACC_FINAL);
+ APPEND_FLAG (len, buf, flag, ACC_SYNCHRONIZED);
+ APPEND_FLAG (len, buf, flag, ACC_BRIDGE);
+ APPEND_FLAG (len, buf, flag, ACC_VARARGS);
+ APPEND_FLAG (len, buf, flag, ACC_NATIVE);
+ APPEND_FLAG (len, buf, flag, ACC_ABSTRACT);
+ APPEND_FLAG (len, buf, flag, ACC_STRICT);
+ APPEND_FLAG (len, buf, flag, ACC_SYNTHETIC);
+ if (flag)
+ AppendString (len, buf, "%s0x%x", delimiter, (unsigned int) (flag));
+ }
+ else if (kind == NestedClassAccess)
+ {
+ APPEND_FLAG (len, buf, flag, ACC_PUBLIC);
+ APPEND_FLAG (len, buf, flag, ACC_PRIVATE);
+ APPEND_FLAG (len, buf, flag, ACC_PROTECTED);
+ APPEND_FLAG (len, buf, flag, ACC_STATIC);
+ APPEND_FLAG (len, buf, flag, ACC_FINAL);
+ APPEND_FLAG (len, buf, flag, ACC_INTERFACE);
+ APPEND_FLAG (len, buf, flag, ACC_ABSTRACT);
+ APPEND_FLAG (len, buf, flag, ACC_SYNTHETIC);
+ APPEND_FLAG (len, buf, flag, ACC_ANNOTATION);
+ APPEND_FLAG (len, buf, flag, ACC_ENUM);
+ if (flag)
+ AppendString (len, buf, "%s0x%x", delimiter, (unsigned int) (flag));
+ }
+ return buf;
+}
+
+class DataReadException
+{
+public:
+
+ DataReadException (char *s)
+ {
+ str_err = s;
+ }
+
+ ~DataReadException ()
+ {
+ free (str_err);
+ }
+
+ char *
+ toString ()
+ {
+ return str_err;
+ }
+
+private:
+ char *str_err;
+};
+
+class DataInputStream
+{
+public:
+
+ DataInputStream (const unsigned char *bytes, int64_t sz)
+ {
+ bp = bp_orig = bytes;
+ bp_last = bp_orig + sz;
+ }
+
+ DataInputStream (DataInputStream *in)
+ {
+ bp = bp_orig = in->bp_orig;
+ bp_last = in->bp_last;
+ }
+
+ u1
+ readByte ()
+ {
+ check (1);
+ u1 val = *bp;
+ bp++;
+ return val;
+ }
+
+ u2
+ readUnsignedShort ()
+ {
+ check (2);
+ u2 val = (bp[0] << 8) | bp[1];
+ bp += 2;
+ return val;
+ }
+
+ u4
+ readUnsigned ()
+ {
+ check (4);
+ u4 val = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
+ bp += 4;
+ return val;
+ }
+
+ const u1 *
+ getptr ()
+ {
+ return bp;
+ }
+
+ const size_t
+ get_offset ()
+ {
+ return bp - bp_orig;
+ }
+
+ void
+ skip (int n)
+ {
+ check (n);
+ bp += n;
+ }
+
+ void
+ reset ()
+ {
+ bp = bp_orig;
+ }
+
+ void
+ copy_bytes (char *buf, int64_t len)
+ {
+ check (len);
+ memcpy (buf, bp, len);
+ buf[len] = '\0';
+ }
+
+private:
+
+ void
+ check (int64_t sz)
+ {
+ if (sz < 0 || bp + sz > bp_last)
+ {
+ DataReadException *e1 = new DataReadException (
+ dbe_sprintf (GTXT ("(Cannot read %lld byte(s) offset=0x%llx)\n"),
+ (long long) sz, (long long) get_offset ()));
+ throw (e1);
+ }
+ };
+
+ const unsigned char *bp_last;
+ const unsigned char *bp_orig;
+ const unsigned char *bp;
+};
+
+class BinaryConstantPool
+{
+public:
+ BinaryConstantPool (DataInputStream &in);
+ ~BinaryConstantPool ();
+
+ u1
+ getType (int n)
+ {
+ return (n < nconst && n > 0) ? types[n] : 0;
+ };
+ char *getString (int index);
+
+private:
+ static char *getTypeName (int ty);
+ static char *type_name_to_str (int ty);
+ static char *offset_to_str (long long offset);
+ int nconst;
+ u1 *types;
+ int64_t *offsets;
+ char **strings;
+ DataInputStream *input;
+};
+
+char *
+BinaryConstantPool::type_name_to_str (int ty)
+{
+ static char buf[128];
+ char *tyName = getTypeName (ty);
+ snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), tyName, ty);
+ return buf;
+}
+
+char *
+BinaryConstantPool::offset_to_str (long long offset)
+{
+ static char buf[128];
+ snprintf (buf, sizeof (buf), NTXT ("offset=0x%06llx (%llu)"), offset, offset);
+ return buf;
+}
+
+BinaryConstantPool::BinaryConstantPool (DataInputStream &in)
+{
+ nconst = 0;
+ types = NULL;
+ offsets = NULL;
+ strings = NULL;
+ input = new DataInputStream (in);
+ int cntConst = in.readUnsignedShort ();
+ if (cntConst > 0)
+ {
+ types = new u1[cntConst];
+ types[0] = 0;
+ offsets = new int64_t [cntConst];
+ strings = new char * [cntConst];
+ strings[0] = NULL;
+ }
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("# BinaryConstantPool: %d\n"), (int) nconst);
+ for (int i = 1; i < cntConst; i++)
+ {
+ nconst = i + 1;
+ strings[i] = NULL;
+ types[i] = in.readByte ();
+ offsets[i] = in.get_offset ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" %3d %-25s %-25s"), i, offset_to_str (offsets[i]), type_name_to_str (types[i]));
+ switch (types[i])
+ {
+ case CONSTANT_UTF8:
+ {
+ u2 length = in.readUnsignedShort ();
+ in.skip (length);
+ Dprintf (DUMP_JAVA_CLASS, " length=%u\n", (unsigned int) length);
+ break;
+ }
+ case CONSTANT_INTEGER:
+ {
+ u4 bytes = in.readUnsigned ();
+ Dprintf (DUMP_JAVA_CLASS, " bytes=0x%08x\n", (unsigned int) bytes);
+ break;
+ }
+ case CONSTANT_FLOAT:
+ {
+ u4 bytes = in.readUnsigned ();
+ Dprintf (DUMP_JAVA_CLASS, " bytes=0x%08x\n", (unsigned int) bytes);
+ break;
+ }
+ case CONSTANT_LONG:
+ case CONSTANT_DOUBLE:
+ {
+ // JVM 4.4.5: all 8-byte constants take up
+ // two entries in the constant_pool table.
+ i++;
+ nconst++;
+ offsets[i] = 0;
+ strings[i] = NULL;
+ u4 high_bytes = in.readUnsigned ();
+ u4 low_bytes = in.readUnsigned ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" high_bytes=0x%08x low_bytes=0x%08x\n"),
+ (unsigned int) high_bytes, (unsigned int) low_bytes);
+ break;
+ }
+ case CONSTANT_CLASS:
+ {
+ u2 name_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" name_index=%6u\n"), (unsigned int) name_index);
+ break;
+ }
+ case CONSTANT_STRING:
+ {
+ u2 string_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" string_index=%4u\n"), (unsigned int) string_index);
+ break;
+ }
+ case CONSTANT_FIELD:
+ case CONSTANT_METHOD:
+ case CONSTANT_INTERFACEMETHOD:
+ {
+ u2 class_index = in.readUnsignedShort ();
+ u2 name_and_type_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" class_index=%5u name_and_type_index=%u\n"),
+ (unsigned int) class_index, (unsigned int) name_and_type_index);
+ break;
+ }
+ case CONSTANT_NAMEANDTYPE:
+ {
+ u2 name_index = in.readUnsignedShort ();
+ u2 descriptor_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, " name_index=%6u descriptor_index=%u\n",
+ (unsigned int) name_index, (unsigned int) descriptor_index);
+ break;
+ }
+ case CONSTANT_METHODHANDLE:
+ {
+ u1 reference_kind = in.readByte ();
+ u2 reference_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, " reference_kind=%u reference_index=%u\n",
+ (unsigned int) reference_kind, (unsigned int) reference_index);
+ break;
+ }
+ case CONSTANT_METHODTYPE:
+ {
+ u2 descriptor_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" descriptor_index=%u\n"),
+ (unsigned int) descriptor_index);
+ break;
+ }
+ case CONSTANT_INVOKEDYNAMIC:
+ {
+ u2 bootstrap_method_attr_index = in.readUnsignedShort ();
+ u2 name_and_type_index = in.readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" bootstrap_method_attr_index=%5u name_and_type_index=%u\n"),
+ (unsigned int) bootstrap_method_attr_index,
+ (unsigned int) name_and_type_index);
+ break;
+ }
+ default:
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("\n"));
+ DataReadException *e1 = new DataReadException (
+ dbe_sprintf (GTXT ("BinaryConstantPool[%d]: bad tag %d %s\n"),
+ i, types[i], offset_to_str (offsets[i])));
+ throw (e1);
+ }
+ }
+}
+
+BinaryConstantPool::~BinaryConstantPool ()
+{
+ delete[] types;
+ delete[] offsets;
+ delete input;
+ if (strings)
+ {
+ for (int i = 0; i < nconst; i++)
+ free (strings[i]);
+ delete[] strings;
+ }
+}
+
+#define CASE_S(x) case x: return (char *) #x
+
+char *
+BinaryConstantPool::getTypeName (int ty)
+{
+ switch (ty)
+ {
+ CASE_S (CONSTANT_UTF8);
+ CASE_S (CONSTANT_INTEGER);
+ CASE_S (CONSTANT_FLOAT);
+ CASE_S (CONSTANT_LONG);
+ CASE_S (CONSTANT_DOUBLE);
+ CASE_S (CONSTANT_CLASS);
+ CASE_S (CONSTANT_STRING);
+ CASE_S (CONSTANT_FIELD);
+ CASE_S (CONSTANT_METHOD);
+ CASE_S (CONSTANT_INTERFACEMETHOD);
+ CASE_S (CONSTANT_NAMEANDTYPE);
+ CASE_S (CONSTANT_METHODHANDLE);
+ CASE_S (CONSTANT_METHODTYPE);
+ CASE_S (CONSTANT_INVOKEDYNAMIC);
+ default: return NTXT ("UNKNOWN_TYPE");
+ }
+}
+
+char *
+BinaryConstantPool::getString (int index)
+{
+ if (index >= nconst || index <= 0)
+ return NULL;
+ if (strings[index])
+ return strings[index];
+ input->reset ();
+ input->skip (offsets[index]);
+ switch (types[index])
+ {
+ case CONSTANT_CLASS:
+ case CONSTANT_STRING:
+ case CONSTANT_NAMEANDTYPE:
+ strings[index] = dbe_strdup (getString (input->readUnsignedShort ()));
+ return strings[index];
+ case CONSTANT_METHOD:
+ input->readUnsignedShort (); // cl_inx
+ strings[index] = dbe_strdup (getString (input->readUnsignedShort ()));
+ return strings[index];
+ case CONSTANT_UTF8:
+ break;
+ default:
+ return NULL;
+ }
+ u2 len = input->readUnsignedShort ();
+ strings[index] = (char *) malloc (len + 1);
+ input->copy_bytes (strings[index], len);
+ return strings[index];
+}
+
+ClassFile::ClassFile () : Module ()
+{
+ input = NULL;
+ bcpool = NULL;
+ cf_buf = NULL;
+ cur_jmthd = NULL;
+ blanksCnt = 0;
+ cf_bufsz = 0;
+ lang_code = Sp_lang_java;
+ class_name = NULL;
+ class_filename = NULL;
+ source_name = NULL;
+ byteCodeInfo = NULL;
+}
+
+char *
+ClassFile::get_opc_name (int op)
+{
+ if (op >= 0 && ((size_t) op) < sizeof (opcNames) / sizeof (char*))
+ return opcNames[op];
+ switch (op)
+ {
+ case opc_try:
+ return NTXT ("try");
+ case opc_dead:
+ return NTXT ("dead");
+ case opc_label:
+ return NTXT ("label");
+ default:
+ return NTXT ("Unknown op code");
+ }
+}
+
+void
+ClassFile::openFile (const char *fname)
+{
+ if (fname == NULL)
+ return;
+ int fd = open64 (fname, O_RDONLY);
+ if (fd == -1)
+ {
+ append_msg (CMSG_ERROR, GTXT ("Cannot open file %s"), fname);
+ return;
+ }
+ struct stat64 stat_buf;
+ if ((fstat64 (fd, &stat_buf) == -1) || (stat_buf.st_size == 0))
+ {
+ close (fd);
+ append_msg (CMSG_ERROR, GTXT ("Cannot read file %s"), fname);
+ return;
+ }
+ cf_bufsz = stat_buf.st_size;
+ cf_buf = (unsigned char *) malloc (cf_bufsz);
+ if (cf_bufsz != read_from_file (fd, cf_buf, cf_bufsz))
+ {
+ free (cf_buf);
+ cf_buf = NULL;
+ close (fd);
+ append_msg (CMSG_ERROR, GTXT ("Cannot read file %s"), fname);
+ return;
+ }
+ close (fd);
+
+ input = new DataInputStream (cf_buf, cf_bufsz);
+ u4 c_magic = input->readUnsigned ();
+ if (c_magic != JAVA_MAGIC)
+ {
+ append_msg (CMSG_ERROR, GTXT ("Not a class file: %s"), fname);
+ return;
+ }
+ /* u2 minor = */ input->readUnsignedShort ();
+ /* u2 major = */ input->readUnsignedShort ();
+ status = AE_OK;
+}
+
+ClassFile::~ClassFile ()
+{
+ free (cf_buf);
+ free (class_name);
+ free (class_filename);
+ free (source_name);
+ delete bcpool;
+ delete input;
+}
+
+static void
+convertName (char *s)
+{
+ while (*s)
+ {
+ if (*s == '/')
+ *s = '.';
+ s++;
+ }
+}
+
+void
+ClassFile::printConstant (StringBuilder *sb, int index)
+{
+ u1 type = bcpool->getType (index);
+ switch (type)
+ {
+ case CONSTANT_METHOD:
+ {
+ char *str = bcpool->getString (index);
+ if (str)
+ {
+ convertName (str);
+ sb->append (str);
+ sb->append (NTXT ("()"));
+ }
+ break;
+ }
+ case CONSTANT_CLASS:
+ {
+ char *str = bcpool->getString (index);
+ if (str)
+ {
+ convertName (str);
+ sb->append (str);
+ }
+ break;
+ }
+ case CONSTANT_UTF8:
+ {
+ char *str = bcpool->getString (index);
+ if (str)
+ sb->append (str);
+ break;
+ }
+ case CONSTANT_STRING:
+ {
+ char *str = bcpool->getString (index);
+ if (str)
+ {
+ sb->append ('"');
+ sb->append (str);
+ sb->append ('"');
+ }
+ break;
+ }
+ default:
+ sb->append ('#');
+ sb->append ((int) index);
+ break;
+ }
+}
+
+long long
+ClassFile::printCodeSequence (StringBuilder *sb, uint64_t addr, DataInputStream *in)
+{
+ int64_t offset = in->get_offset ();
+ sb->appendf (NTXT ("%08llx: "), (long long) addr);
+ int opcode = in->readByte ();
+ if (opcode == opc_wide)
+ {
+ opcode = in->readByte ();
+ sb->append (get_opc_name (opcode));
+ sb->append (NTXT ("_w "));
+ int arg = in->readUnsignedShort ();
+ 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:
+ sb->append (arg);
+ break;
+ case opc_iinc:
+ sb->append (arg);
+ sb->append (' ');
+ sb->append (in->readUnsignedShort ());
+ break;
+ default:
+ sb->append (GTXT ("Invalid opcode"));
+ break;
+ }
+ }
+ else
+ {
+ sb->append (get_opc_name (opcode));
+ sb->append (' ');
+ 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:
+ sb->append (in->readByte ());
+ break;
+ case opc_iinc:
+ sb->append (in->readByte ());
+ sb->append (' ');
+ sb->append (in->readByte ());
+ break;
+ case opc_tableswitch:
+ {
+ int align = (addr + 1) % 4; // 1 byte is a length of opc_lookupswitch
+ if (align != 0)
+ {
+ in->skip (4 - align); // four byte boundry
+ }
+ long default_skip = in->readUnsigned ();
+ long low = in->readUnsigned ();
+ long high = in->readUnsigned ();
+ sb->appendf (GTXT ("%ld to %ld: default=0x%llx"),
+ (long) low, (long) high, (long long) (addr + default_skip));
+ for (long i = low; i <= high; ++i)
+ /* u4 i1 = */ in->readUnsigned ();
+ break;
+ }
+ case opc_lookupswitch:
+ {
+ int align = (addr + 1) % 4; // 1 byte is a length of opc_lookupswitch
+ if (align != 0)
+ in->skip (4 - align); // four byte boundry
+ u4 default_skip = in->readUnsigned ();
+ u4 npairs = in->readUnsigned ();
+ sb->appendf (GTXT ("%d: default=0x%llx"), npairs,
+ (long long) (addr + default_skip));
+ for (int i = 0, nints = npairs * 2; i < nints; i += 2)
+ {
+ /* u4 i1 = */ in->readUnsigned ();
+ /* u4 i2 = */ in->readUnsigned ();
+ }
+ break;
+ }
+ case opc_newarray:
+ switch (in->readByte ())
+ {
+ case T_INT:
+ sb->append (GTXT ("int"));
+ break;
+ case T_LONG:
+ sb->append (GTXT ("long"));
+ break;
+ case T_FLOAT:
+ sb->append (GTXT ("float"));
+ break;
+ case T_DOUBLE:
+ sb->append (GTXT ("double"));
+ break;
+ case T_CHAR:
+ sb->append (GTXT ("char"));
+ break;
+ case T_SHORT:
+ sb->append (GTXT ("short"));
+ break;
+ case T_BYTE:
+ sb->append (GTXT ("byte"));
+ break;
+ case T_BOOLEAN:
+ sb->append (GTXT ("boolean"));
+ break;
+ default:
+ sb->append (GTXT ("BOGUS TYPE"));
+ break;
+ }
+ break;
+ case opc_anewarray:
+ sb->append (GTXT ("class "));
+ printConstant (sb, in->readUnsignedShort ());
+ break;
+ case opc_sipush:
+ sb->append (in->readUnsignedShort ());
+ break;
+ case opc_bipush:
+ sb->append (in->readByte ());
+ break;
+ case opc_ldc:
+ printConstant (sb, in->readByte ());
+ break;
+ 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:
+ printConstant (sb, in->readUnsignedShort ());
+ break;
+ case opc_invokeinterface:
+ {
+ u2 index = in->readUnsignedShort ();
+ u1 count = in->readByte ();
+ /* u1 zero = */ in->readByte ();
+ sb->appendf (" #%u, %u) ", (unsigned int) index, (unsigned int) count);
+ printConstant (sb, index);
+ break;
+ }
+ case opc_multianewarray:
+ {
+ u2 index = in->readUnsignedShort ();
+ printConstant (sb, index);
+ sb->appendf (GTXT (" dim #%d "), index);
+ break;
+ }
+ 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:
+ sb->appendf (NTXT ("0x%llx"), (long long) (addr + (short) in->readUnsignedShort ()));
+ break;
+ case opc_jsr_w:
+ case opc_goto_w:
+ sb->append (addr + (int) in->readUnsigned ());
+ break;
+ default:
+ break;
+ }
+ }
+ return in->get_offset () - offset;
+}
+
+void
+ClassFile::readAttributes (int count)
+{
+ blanksCnt += 4;
+ for (int ax = 0; ax < count; ax++)
+ {
+ u2 attribute_name_index = input->readUnsignedShort ();
+ u4 attribute_length = input->readUnsigned ();
+ char *attribute_name = bcpool->getString (attribute_name_index);
+ if (!attribute_name)
+ {
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("%*c %2d: attr_name=%3d %-15s len=%4d\n"),
+ (int) blanksCnt, ' ', (int) (ax + 1),
+ (int) attribute_name_index, STR (attribute_name), (int) attribute_length);
+ input->skip (attribute_length);
+ continue;
+ }
+
+ if (strcmp (attribute_name, NTXT ("SourceFile")) == 0)
+ {
+ u2 sourcefile_index = input->readUnsignedShort ();
+ source_name = dbe_strdup (bcpool->getString (sourcefile_index));
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("%*c %2d: attr_name=%3d %-15s len=%4d file_name=%d %s\n"),
+ (int) blanksCnt, ' ', (int) (ax + 1),
+ (int) attribute_name_index, STR (attribute_name), (int) attribute_length,
+ (int) sourcefile_index, STR (source_name));
+ }
+ else if (strcmp (attribute_name, NTXT ("InnerClasses")) == 0)
+ {
+ int niclasses = input->readUnsignedShort ();
+ for (int ix = 0; ix < niclasses; ix++)
+ {
+ u2 inner_class_info_index = input->readUnsignedShort ();
+ u2 outer_class_info_index = input->readUnsignedShort ();
+ u2 inner_name_index = input->readUnsignedShort ();
+ u2 inner_class_access_flags = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS,
+ NTXT ("%*c %2d: attr_name=%3d %-15s len=%4d name=%d '%s'\n"
+ "%*cinner_class_info_index=%d outer_class_info_index=%d flags=%s\n"),
+ (int) blanksCnt, ' ', (int) (ax + 1),
+ (int) attribute_name_index, STR (attribute_name), (int) attribute_length,
+ (int) inner_name_index, STR (bcpool->getString (inner_name_index)),
+ (int) (blanksCnt + 10), ' ',
+ (int) inner_class_info_index, (int) outer_class_info_index,
+ access_flags_to_str (NestedClassAccess, inner_class_access_flags));
+ }
+ }
+ else if (strcmp (attribute_name, NTXT ("Code")) == 0)
+ {
+ u2 max_stack = input->readUnsignedShort ();
+ u2 max_locals = input->readUnsignedShort ();
+ u4 code_length = input->readUnsigned ();
+ if (cur_jmthd)
+ {
+ cur_jmthd->size = code_length;
+ cur_jmthd->img_fname = dbeFile->get_location ();
+ cur_jmthd->img_offset = input->get_offset ();
+ }
+ input->skip (code_length);
+ u2 exception_table_length = input->readUnsignedShort ();
+ input->skip (exception_table_length * (2 + 2 + 2 + 2));
+ Dprintf (DUMP_JAVA_CLASS,
+ NTXT ("%*c %2d: attr_name=%3d %-15s len=%4d max_stack=%d max_locals=%d code_length=%d exception_table_length=%d\n"),
+ (int) blanksCnt, ' ', (int) (ax + 1),
+ (int) attribute_name_index, STR (attribute_name), (int) attribute_length,
+ (int) max_stack, (int) max_locals, (int) code_length, (int) exception_table_length);
+ readAttributes (input->readUnsignedShort ());
+ }
+ else if (strcmp (attribute_name, NTXT ("LineNumberTable")) == 0)
+ {
+ int nlines = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("%*c %2d: attr_name=%3d %-15s len=%4d nlines=%d\n"),
+ (int) blanksCnt, ' ', (int) (ax + 1),
+ (int) attribute_name_index, STR (attribute_name), (int) attribute_length,
+ (int) nlines);
+ for (int lx = 0; lx < nlines; lx++)
+ {
+ int bci = input->readUnsignedShort ();
+ int lno = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("%*c %3d: pc=%4d (0x%04x) line=%d\n"),
+ (int) (blanksCnt + 5), ' ', (int) (lx + 1), (int) bci, (int) bci, (int) lno);
+ if (cur_jmthd)
+ byteCodeInfo->append (new ByteCodeInfo (cur_jmthd, bci, lno));
+ }
+ }
+ else
+ {
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("%*c %2d: attr_name=%3d %-15s len=%4d\n"),
+ (int) blanksCnt, ' ', (int) (ax + 1),
+ (int) attribute_name_index, STR (attribute_name),
+ (int) attribute_length);
+ input->skip (attribute_length);
+ }
+ }
+ blanksCnt -= 4;
+}
+
+int
+ClassFile::readFile ()
+{
+ if (status != AE_NOTREAD)
+ return status;
+ status = AE_OTHER;
+
+ // The ClassFile Structure http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
+ try
+ {
+ blanksCnt = 4;
+ cur_jmthd = NULL;
+ char *fname = dbeFile->get_location ();
+ openFile (fname);
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("\nClassFile::readFile status=%d %s location=%s\n"),
+ (unsigned int) status, STR (get_name ()), STR (fname));
+ if (status != AE_OK)
+ return status;
+ byteCodeInfo = new Vector<ByteCodeInfo *>(512);
+ bcpool = new BinaryConstantPool (*input);
+ u2 access_flags = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("\naccess_flags=%s; %s\n"),
+ access_flags_to_str (ClassAccess, access_flags),
+ STR (dbeFile->get_name ()));
+ u2 classNameInd = input->readUnsignedShort ();
+ class_filename = dbe_strdup (bcpool->getString (classNameInd));
+ if (class_filename)
+ {
+ class_name = strdup (class_filename);
+ convertName (class_name);
+ }
+
+ // Get superclass name
+ u2 superClassInd = input->readUnsignedShort ();
+ //char *str = bcpool->getString(superClassInd);
+ //super_name = str ? convertName( str ) : NULL;
+
+ // Read interfaces
+ int interfaces_count = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS,
+ NTXT (" class_name=%3d %-20s superClass=%3d %s interfaces_count=%d\n"),
+ (int) classNameInd, STR (class_name),
+ (int) superClassInd, STR (bcpool->getString (superClassInd)),
+ (int) interfaces_count);
+ for (int i = 0; i < interfaces_count; i++)
+ {
+ u2 index = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" %6lld%s"), (long long) index,
+ (i % 8 == 7) || (i + 1 == interfaces_count) ? "\n" : "");
+ }
+
+ // Read fields
+ int fields_count = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" fields_count=%d\n"), fields_count);
+ for (int i = 0; i < fields_count; i++)
+ {
+ u2 fld_access_flags = input->readUnsignedShort ();
+ u2 name_index = input->readUnsignedShort ();
+ u2 descriptor_index = input->readUnsignedShort ();
+ u2 attributes_count = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS,
+ NTXT (" %2d: name=%3d %-20s flags=%s; desc_ind=%d attr_count=%d\n"),
+ i, (int) name_index, STR (bcpool->getString (name_index)),
+ access_flags_to_str (FieldAccess, fld_access_flags),
+ (int) descriptor_index, (int) attributes_count);
+ readAttributes (attributes_count);
+ }
+
+ // Read methods
+ int methods_count = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("\n methods_count=%d\n"), (int) methods_count);
+ int func_cnt = functions->size ();
+ for (int i = 0; i < methods_count; i++)
+ {
+ u2 mthd_access_flags = input->readUnsignedShort ();
+ u2 name_index = input->readUnsignedShort ();
+ u2 descriptor_index = input->readUnsignedShort ();
+ char *mname = bcpool->getString (name_index);
+ if (mname == NULL)
+ {
+ DataReadException *e1 = new DataReadException (dbe_sprintf (GTXT ("method name[%d] is NULL\n"), i));
+ throw (e1);
+ }
+ char *msign = bcpool->getString (descriptor_index);
+ if (msign == NULL)
+ {
+ DataReadException *e1 = new DataReadException (dbe_sprintf (GTXT ("method signature[%d] is NULL\n"), i));
+ throw (e1);
+ }
+ size_t len = strlen (class_name);
+ cur_jmthd = NULL;
+ for (int idx = 0; idx < func_cnt; idx++)
+ {
+ JMethod *jmthd = (JMethod*) functions->fetch (idx);
+ char *jmt_name = jmthd->get_name (Histable::SHORT);
+ if (strncmp (jmt_name, class_name, len) == 0)
+ {
+ if (strcmp (jmt_name + len + 1, mname) == 0 &&
+ strcmp (jmthd->get_signature (), msign) == 0)
+ {
+ cur_jmthd = jmthd;
+ break;
+ }
+ }
+ }
+ if (cur_jmthd == NULL)
+ {
+ cur_jmthd = dbeSession->createJMethod ();
+ cur_jmthd->module = this;
+ cur_jmthd->set_signature (dbe_strdup (msign));
+ char *nm = dbe_sprintf (NTXT ("%s.%s"), class_name, mname);
+ cur_jmthd->set_name (nm);
+ free (nm);
+ functions->append (cur_jmthd);
+ }
+ if ((mthd_access_flags & ACC_NATIVE) != 0)
+ {
+ cur_jmthd->flags |= FUNC_FLAG_NATIVE;
+ }
+ u2 attributes_count = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS,
+ NTXT (" %2d: name=%d %-20s flags=%s desc_ind=%d attr_count=%d\n"),
+ (int) (i + 1), (int) name_index, STR (bcpool->getString (name_index)),
+ access_flags_to_str (MethodAccess, mthd_access_flags),
+ (int) descriptor_index, (int) attributes_count);
+ readAttributes (attributes_count);
+ cur_jmthd->popSrcFile ();
+ }
+
+ // Read global attributes
+ u2 global_attributes_count = input->readUnsignedShort ();
+ Dprintf (DUMP_JAVA_CLASS, NTXT (" global_attributes_count=%d\n"), global_attributes_count);
+ readAttributes (global_attributes_count);
+ status = AE_OK;
+ }
+ catch (DataReadException *ex)
+ {
+ append_msg (CMSG_ERROR, GTXT ("Cannot read class file %s (%s)"), get_name (), ex->toString ());
+ delete ex;
+ status = AE_OTHER;
+ }
+
+ char *fnm = NULL;
+ if (class_filename)
+ {
+ if (strcmp (class_filename, get_name ()) != 0)
+ set_name (strdup (class_filename));
+ if (source_name)
+ {
+ char *bname = strrchr (class_filename, '/');
+ if (bname)
+ fnm = dbe_sprintf (NTXT ("%.*s/%s"), (int) (bname - class_filename),
+ class_filename, source_name);
+ else
+ fnm = strdup (source_name);
+ }
+ else
+ fnm = get_java_file_name (class_filename, false);
+ }
+ else if (source_name)
+ fnm = strdup (source_name);
+ if (fnm)
+ {
+ set_file_name (fnm);
+ main_source = findSource (file_name, true);
+ main_source->dbeFile->filetype |= DbeFile::F_JAVA_SOURCE;
+ }
+
+ for (long i = 0, sz = VecSize (functions); i < sz; i++)
+ functions->get (i)->def_source = main_source;
+ JMethod *func = NULL;
+ for (long i = 0, sz = VecSize (byteCodeInfo); i < sz; i++)
+ {
+ ByteCodeInfo *p = byteCodeInfo->get (i);
+ if (func != p->func)
+ {
+ if (func)
+ func->popSrcFile ();
+ func = p->func;
+ func->line_first = p->lno;
+ func->pushSrcFile (main_source, 0);
+ }
+ func->line_last = p->lno;
+ func->add_PC_info (p->bci, p->lno, main_source);
+ }
+ if (func)
+ func->popSrcFile ();
+ Destroy (byteCodeInfo);
+ Dprintf (DUMP_JAVA_CLASS, NTXT ("\n status=%d class_filename=%s class_name=%s source_name=%s file_name=%s %s\n"),
+ (unsigned int) status, STR (class_filename), STR (class_name),
+ STR (source_name), STR (file_name),
+ STR (get_name ()));
+ return status;
+}
+
+#define MAX_CLASS_SIZE 65536
+
+char *
+ClassFile::get_disasm (uint64_t inst_address, uint64_t end_address,
+ uint64_t start_address, uint64_t f_offset, int64_t &inst_size)
+{
+ int64_t offset = f_offset + (inst_address - start_address);
+ if ((cf_buf == NULL) || (inst_address >= end_address) || (offset >= cf_bufsz))
+ {
+ inst_size = 0;
+ return NULL;
+ }
+
+ // Check for an implausibly large size
+ if ((inst_address - start_address) > MAX_CLASS_SIZE)
+ {
+ append_msg (CMSG_ERROR, GTXT ("Cannot disassemble class file %s (%s), implausible size = %lld"),
+ get_name (), dbeFile->get_location (),
+ (end_address - start_address));
+ inst_size = 0;
+ return NULL;
+ }
+
+ StringBuilder sb;
+ DataInputStream *in = new DataInputStream (input);
+ try
+ {
+ in->skip (offset);
+ inst_size = printCodeSequence (&sb, inst_address - start_address, in);
+ }
+ catch (DataReadException *ex)
+ {
+ append_msg (CMSG_ERROR, GTXT ("Cannot disassemble class file %s (%s) %s"),
+ get_name (), dbeFile->get_location (), ex->toString ());
+ delete ex;
+ inst_size = 0;
+ }
+ delete in;
+ if (inst_size == 0)
+ return NULL;
+ return sb.toString ();
+}
+
+char *
+ClassFile::get_java_file_name (char *clname, bool classSuffix)
+{
+ size_t len = strlen (clname);
+ if (len > 6 && streq (clname + len - 6, NTXT (".class")))
+ len -= 6;
+ if (!classSuffix)
+ { // remove $SubClassName from "ClassName$SubClassName"
+ char *tmp = strchr (clname, '$');
+ if (tmp)
+ len = tmp - clname;
+ }
+ char *clpath = (char *) malloc (len + 10);
+ for (size_t i = 0; i < len; i++)
+ clpath[i] = (clname[i] == '.') ? '/' : clname[i];
+ snprintf (clpath + len, 10, classSuffix ? NTXT (".class") : NTXT (".java"));
+ return clpath;
+}