rizin/librz/asm/arch/java/jvm.c
2022-02-06 15:50:50 +01:00

1557 lines
45 KiB
C

// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include "jvm.h"
#include "const.h"
#include <rz_analysis.h>
#define fail_if_no_enough_buffer_or_set(bytecode, jvm, n) \
if ((jvm->size - jvm->current) < n) { \
RZ_LOG_DEBUG("java: buffer is not big enough (available: %u, needed: %u)\n", jvm->size - jvm->current, n); \
return false; \
} \
bytecode->size = n
#define load_ut8(bytecode, jvm, t, c) \
fail_if_no_enough_buffer_or_set(bytecode, jvm, 2); \
bytecode->args[0] = (c)jvm->buffer[jvm->current + 1]; \
bytecode->type[0] = (t)
#define load_ut8x2(bytecode, jvm, t0, t1, c0, c1) \
fail_if_no_enough_buffer_or_set(bytecode, jvm, 3); \
bytecode->args[0] = (c0)jvm->buffer[jvm->current + 1]; \
bytecode->type[0] = (t0); \
bytecode->args[1] = (c1)jvm->buffer[jvm->current + 2]; \
bytecode->type[1] = (t1)
#define load_ut16(bytecode, jvm, t, c) \
fail_if_no_enough_buffer_or_set(bytecode, jvm, 3); \
bytecode->args[0] = (c)rz_read_at_be16(jvm->buffer, jvm->current + 1); \
bytecode->type[0] = (t)
#define load_ut32(bytecode, jvm, t, c) \
fail_if_no_enough_buffer_or_set(bytecode, jvm, 5); \
bytecode->args[0] = (c)rz_read_at_be32(jvm->buffer, jvm->current + 1); \
bytecode->type[0] = (t)
#define load_ut16_ut8(bytecode, jvm, t0, t1, c0, c1) \
fail_if_no_enough_buffer_or_set(bytecode, jvm, 4); \
bytecode->args[0] = (c0)rz_read_at_be16(jvm->buffer, jvm->current + 1); \
bytecode->type[0] = (t0); \
bytecode->args[1] = (c1)rz_read_at_be8(jvm->buffer, jvm->current + 3); \
bytecode->type[1] = (t1)
#define load_ut16x2(bytecode, jvm, t0, t1, c0, c1) \
fail_if_no_enough_buffer_or_set(bytecode, jvm, 5); \
bytecode->args[0] = (c0)rz_read_at_be16(jvm->buffer, jvm->current + 1); \
bytecode->type[0] = (t0); \
bytecode->args[1] = (c1)rz_read_at_be16(jvm->buffer, jvm->current + 3); \
bytecode->type[1] = (t1)
static inline ut32 align_upper(JavaVM *jvm) {
ut64 base = jvm->pc - jvm->section + jvm->current + 1;
ut64 mod = base % 4;
if (mod != 0) {
return 4 - mod;
}
return 0;
}
static bool decode_lookupswitch(JavaVM *jvm, Bytecode *bytecode) {
ut32 offset = jvm->current + align_upper(jvm);
if ((jvm->size - offset) < 8) {
return false;
}
ut32 pc_default = rz_read_at_be32(jvm->buffer, offset);
offset += sizeof(ut32);
ut32 npairs = rz_read_at_be32(jvm->buffer, offset);
offset += sizeof(ut32);
LookupSwitch *ls = RZ_NEW(LookupSwitch);
if (!ls) {
rz_warn_if_reached();
return false;
}
ls->pc_default = pc_default;
ls->npairs = npairs;
bytecode->args[0] = pc_default;
bytecode->type[0] = BYTECODE_TYPE_ADDRESS;
bytecode->extra = ls;
bytecode->size = offset - jvm->current;
return true;
}
static bool decode_tableswitch(JavaVM *jvm, Bytecode *bytecode) {
ut32 offset = jvm->current + align_upper(jvm) + 1;
if ((jvm->size - offset) < 12) {
rz_warn_if_reached();
return false;
}
ut32 pc_default = rz_read_at_be32(jvm->buffer, offset);
offset += sizeof(ut32);
ut32 low = rz_read_at_be32(jvm->buffer, offset);
offset += sizeof(ut32);
ut32 high = rz_read_at_be32(jvm->buffer, offset);
offset += sizeof(ut32);
ut32 length = high - low;
TableSwitch *ts = RZ_NEW(TableSwitch);
if (!ts) {
rz_warn_if_reached();
return false;
}
ts->pc_default = pc_default;
ts->low = low;
ts->high = high;
ts->length = length;
bytecode->args[0] = pc_default;
bytecode->type[0] = BYTECODE_TYPE_ADDRESS;
bytecode->extra = ts;
bytecode->size = offset - jvm->current;
return true;
}
static bool decode_instruction(JavaVM *jvm, Bytecode *bytecode) {
rz_return_val_if_fail((jvm->size - jvm->current) >= 1, false);
memset(bytecode, 0, sizeof(Bytecode));
const ut8 *buffer = jvm->buffer;
ut8 byte = buffer[jvm->current];
switch (byte) {
case BYTECODE_00_NOP:
strcpy(bytecode->name, "nop");
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_NOP;
break;
case BYTECODE_01_ACONST_NULL:
strcpy(bytecode->name, "aconst_null");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_02_ICONST_M1:
strcpy(bytecode->name, "iconst_m1");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_03_ICONST_0:
strcpy(bytecode->name, "iconst_0");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_04_ICONST_1:
strcpy(bytecode->name, "iconst_1");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_05_ICONST_2:
strcpy(bytecode->name, "iconst_2");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_06_ICONST_3:
strcpy(bytecode->name, "iconst_3");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_07_ICONST_4:
strcpy(bytecode->name, "iconst_4");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_08_ICONST_5:
strcpy(bytecode->name, "iconst_5");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_09_LCONST_0:
strcpy(bytecode->name, "lconst_0");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_0A_LCONST_1:
strcpy(bytecode->name, "lconst_1");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_0B_FCONST_0:
strcpy(bytecode->name, "fconst_0");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_0C_FCONST_1:
strcpy(bytecode->name, "fconst_1");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_0D_FCONST_2:
strcpy(bytecode->name, "fconst_2");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_0E_DCONST_0:
strcpy(bytecode->name, "dconst_0");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_0F_DCONST_1:
strcpy(bytecode->name, "dconst_1");
bytecode->size = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_10_BIPUSH:
strcpy(bytecode->name, "bipush");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, st32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_11_SIPUSH:
strcpy(bytecode->name, "sipush");
load_ut16(bytecode, jvm, BYTECODE_TYPE_NUMBER, st32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_12_LDC:
strcpy(bytecode->name, "ldc");
load_ut8(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_13_LDC_W:
strcpy(bytecode->name, "ldc_w");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_14_LDC2_W:
strcpy(bytecode->name, "ldc2_w");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_15_ILOAD:
strcpy(bytecode->name, "iload");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_16_LLOAD:
strcpy(bytecode->name, "lload");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_17_FLOAD:
strcpy(bytecode->name, "fload");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_18_DLOAD:
strcpy(bytecode->name, "dload");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_19_ALOAD:
strcpy(bytecode->name, "aload");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_1A_ILOAD_0:
strcpy(bytecode->name, "iload_0");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_1B_ILOAD_1:
strcpy(bytecode->name, "iload_1");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_1C_ILOAD_2:
strcpy(bytecode->name, "iload_2");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_1D_ILOAD_3:
strcpy(bytecode->name, "iload_3");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_1E_LLOAD_0:
strcpy(bytecode->name, "lload_0");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_1F_LLOAD_1:
strcpy(bytecode->name, "lload_1");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_20_LLOAD_2:
strcpy(bytecode->name, "lload_2");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_21_LLOAD_3:
strcpy(bytecode->name, "lload_3");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_22_FLOAD_0:
strcpy(bytecode->name, "fload_0");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_23_FLOAD_1:
strcpy(bytecode->name, "fload_1");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_24_FLOAD_2:
strcpy(bytecode->name, "fload_2");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_25_FLOAD_3:
strcpy(bytecode->name, "fload_3");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_26_DLOAD_0:
strcpy(bytecode->name, "dload_0");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_27_DLOAD_1:
strcpy(bytecode->name, "dload_1");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_28_DLOAD_2:
strcpy(bytecode->name, "dload_2");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_29_DLOAD_3:
strcpy(bytecode->name, "dload_3");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_2A_ALOAD_0:
strcpy(bytecode->name, "aload_0");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_2B_ALOAD_1:
strcpy(bytecode->name, "aload_1");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_2C_ALOAD_2:
strcpy(bytecode->name, "aload_2");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_2D_ALOAD_3:
strcpy(bytecode->name, "aload_3");
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_2E_IALOAD:
strcpy(bytecode->name, "iaload");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_2F_LALOAD:
strcpy(bytecode->name, "laload");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_30_FALOAD:
strcpy(bytecode->name, "faload");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_31_DALOAD:
strcpy(bytecode->name, "daload");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_32_AALOAD:
strcpy(bytecode->name, "aaload");
bytecode->size = 1;
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_33_BALOAD:
strcpy(bytecode->name, "baload");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_34_CALOAD:
strcpy(bytecode->name, "caload");
bytecode->size = 1;
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_35_SALOAD:
strcpy(bytecode->name, "saload");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case BYTECODE_36_ISTORE:
strcpy(bytecode->name, "istore");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_37_LSTORE:
strcpy(bytecode->name, "lstore");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_38_FSTORE:
strcpy(bytecode->name, "fstore");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_39_DSTORE:
strcpy(bytecode->name, "dstore");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_3A_ASTORE:
strcpy(bytecode->name, "astore");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_3B_ISTORE_0:
strcpy(bytecode->name, "istore_0");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_3C_ISTORE_1:
strcpy(bytecode->name, "istore_1");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_3D_ISTORE_2:
strcpy(bytecode->name, "istore_2");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_3E_ISTORE_3:
strcpy(bytecode->name, "istore_3");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_3F_LSTORE_0:
strcpy(bytecode->name, "lstore_0");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_40_LSTORE_1:
strcpy(bytecode->name, "lstore_1");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_41_LSTORE_2:
strcpy(bytecode->name, "lstore_2");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_42_LSTORE_3:
strcpy(bytecode->name, "lstore_3");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_43_FSTORE_0:
strcpy(bytecode->name, "fstore_0");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_44_FSTORE_1:
strcpy(bytecode->name, "fstore_1");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_45_FSTORE_2:
strcpy(bytecode->name, "fstore_2");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_46_FSTORE_3:
strcpy(bytecode->name, "fstore_3");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_47_DSTORE_0:
strcpy(bytecode->name, "dstore_0");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_48_DSTORE_1:
strcpy(bytecode->name, "dstore_1");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_49_DSTORE_2:
strcpy(bytecode->name, "dstore_2");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_4A_DSTORE_3:
strcpy(bytecode->name, "dstore_3");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_4B_ASTORE_0:
strcpy(bytecode->name, "astore_0");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_4C_ASTORE_1:
strcpy(bytecode->name, "astore_1");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_4D_ASTORE_2:
strcpy(bytecode->name, "astore_2");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_4E_ASTORE_3:
strcpy(bytecode->name, "astore_3");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_4F_IASTORE:
strcpy(bytecode->name, "iastore");
bytecode->stack_input = 3;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_50_LASTORE:
strcpy(bytecode->name, "lastore");
bytecode->stack_input = 3;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_51_FASTORE:
strcpy(bytecode->name, "fastore");
bytecode->stack_input = 3;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_52_DASTORE:
strcpy(bytecode->name, "dastore");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_53_AASTORE:
strcpy(bytecode->name, "aastore");
bytecode->size = 1;
bytecode->stack_input = 3;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_54_BASTORE:
strcpy(bytecode->name, "bastore");
bytecode->stack_input = 3;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_55_CASTORE:
strcpy(bytecode->name, "castore");
bytecode->size = 1;
bytecode->stack_input = 3;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_56_SASTORE:
strcpy(bytecode->name, "sastore");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_STORE;
break;
case BYTECODE_57_POP:
strcpy(bytecode->name, "pop");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_POP;
break;
case BYTECODE_58_POP2:
strcpy(bytecode->name, "pop2");
bytecode->stack_input = 2;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_POP;
break;
case BYTECODE_59_DUP:
strcpy(bytecode->name, "dup");
bytecode->stack_input = 1;
bytecode->stack_output = 2;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_5A_DUP_X1:
strcpy(bytecode->name, "dup_x1");
bytecode->stack_input = 2;
bytecode->stack_output = 3;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_5B_DUP_X2:
strcpy(bytecode->name, "dup_x2");
bytecode->stack_input = 3;
bytecode->stack_output = 4;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_5C_DUP2:
strcpy(bytecode->name, "dup2");
bytecode->stack_input = 2;
bytecode->stack_output = 4;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_5D_DUP2_X1:
strcpy(bytecode->name, "dup2_x1");
bytecode->stack_input = 3;
bytecode->stack_output = 5;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_5E_DUP2_X2:
strcpy(bytecode->name, "dup2_x2");
bytecode->stack_input = 4;
bytecode->stack_output = 6;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_5F_SWAP:
strcpy(bytecode->name, "swap");
bytecode->size = 1;
bytecode->stack_input = 2;
bytecode->stack_output = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MOV;
break;
case BYTECODE_60_IADD:
strcpy(bytecode->name, "iadd");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case BYTECODE_61_LADD:
strcpy(bytecode->name, "ladd");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case BYTECODE_62_FADD:
strcpy(bytecode->name, "fadd");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case BYTECODE_63_DADD:
strcpy(bytecode->name, "dadd");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case BYTECODE_64_ISUB:
strcpy(bytecode->name, "isub");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_65_LSUB:
strcpy(bytecode->name, "lsub");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_66_FSUB:
strcpy(bytecode->name, "fsub");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_67_DSUB:
strcpy(bytecode->name, "dsub");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_68_IMUL:
strcpy(bytecode->name, "imul");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MUL;
break;
case BYTECODE_69_LMUL:
strcpy(bytecode->name, "lmul");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MUL;
break;
case BYTECODE_6A_FMUL:
strcpy(bytecode->name, "fmul");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MUL;
break;
case BYTECODE_6B_DMUL:
strcpy(bytecode->name, "dmul");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MUL;
break;
case BYTECODE_6C_IDIV:
strcpy(bytecode->name, "idiv");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_DIV;
break;
case BYTECODE_6D_LDIV:
strcpy(bytecode->name, "ldiv");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_DIV;
break;
case BYTECODE_6E_FDIV:
strcpy(bytecode->name, "fdiv");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_DIV;
break;
case BYTECODE_6F_DDIV:
strcpy(bytecode->name, "ddiv");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_DIV;
break;
case BYTECODE_70_IREM:
strcpy(bytecode->name, "irem");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MOD;
break;
case BYTECODE_71_LREM:
strcpy(bytecode->name, "lrem");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MOD;
break;
case BYTECODE_72_FREM:
strcpy(bytecode->name, "frem");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MOD;
break;
case BYTECODE_73_DREM:
strcpy(bytecode->name, "drem");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_MOD;
break;
case BYTECODE_74_INEG:
strcpy(bytecode->name, "ineg");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_75_LNEG:
strcpy(bytecode->name, "lneg");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_76_FNEG:
strcpy(bytecode->name, "fneg");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_77_DNEG:
strcpy(bytecode->name, "dneg");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case BYTECODE_78_ISHL:
strcpy(bytecode->name, "ishl");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SHL;
break;
case BYTECODE_79_LSHL:
strcpy(bytecode->name, "lshl");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SHL;
break;
case BYTECODE_7A_ISHR:
strcpy(bytecode->name, "ishr");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SHR;
break;
case BYTECODE_7B_LSHR:
strcpy(bytecode->name, "lshr");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SHR;
break;
case BYTECODE_7C_IUSHR:
strcpy(bytecode->name, "iushr");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SHR;
break;
case BYTECODE_7D_LUSHR:
strcpy(bytecode->name, "lushr");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SHR;
break;
case BYTECODE_7E_IAND:
strcpy(bytecode->name, "iand");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_AND;
break;
case BYTECODE_7F_LAND:
strcpy(bytecode->name, "land");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_AND;
break;
case BYTECODE_80_IOR:
strcpy(bytecode->name, "ior");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_OR;
break;
case BYTECODE_81_LOR:
strcpy(bytecode->name, "lor");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_OR;
break;
case BYTECODE_82_IXOR:
strcpy(bytecode->name, "ixor");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_XOR;
break;
case BYTECODE_83_LXOR:
strcpy(bytecode->name, "lxor");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_XOR;
break;
case BYTECODE_84_IINC:
strcpy(bytecode->name, "iinc");
load_ut8x2(bytecode, jvm, BYTECODE_TYPE_NUMBER, BYTECODE_TYPE_NUMBER, ut32, ut32);
bytecode->atype = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case BYTECODE_85_I2L:
strcpy(bytecode->name, "i2l");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_86_I2F:
strcpy(bytecode->name, "i2f");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_87_I2D:
strcpy(bytecode->name, "i2d");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_88_L2I:
strcpy(bytecode->name, "l2i");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_89_L2F:
strcpy(bytecode->name, "l2f");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_8A_L2D:
strcpy(bytecode->name, "l2d");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_8B_F2I:
strcpy(bytecode->name, "f2i");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_8C_F2L:
strcpy(bytecode->name, "f2l");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_8D_F2D:
strcpy(bytecode->name, "f2d");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_8E_D2I:
strcpy(bytecode->name, "d2i");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_8F_D2L:
strcpy(bytecode->name, "d2l");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_90_D2F:
strcpy(bytecode->name, "d2f");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_91_I2B:
strcpy(bytecode->name, "i2b");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_92_I2C:
strcpy(bytecode->name, "i2c");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_93_I2S:
strcpy(bytecode->name, "i2s");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case BYTECODE_94_LCMP:
strcpy(bytecode->name, "lcmp");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case BYTECODE_95_FCMPL:
strcpy(bytecode->name, "fcmpl");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case BYTECODE_96_FCMPG:
strcpy(bytecode->name, "fcmpg");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case BYTECODE_97_DCMPL:
strcpy(bytecode->name, "dcmpl");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case BYTECODE_98_DCMPG:
strcpy(bytecode->name, "dcmpg");
bytecode->stack_input = 2;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case BYTECODE_99_IFEQ:
strcpy(bytecode->name, "ifeq");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_9A_IFNE:
strcpy(bytecode->name, "ifne");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_9B_IFLT:
strcpy(bytecode->name, "iflt");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_9C_IFGE:
strcpy(bytecode->name, "ifge");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_9D_IFGT:
strcpy(bytecode->name, "ifgt");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_9E_IFLE:
strcpy(bytecode->name, "ifle");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_9F_IF_ICMPEQ:
strcpy(bytecode->name, "if_icmpeq");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A0_IF_ICMPNE:
strcpy(bytecode->name, "if_icmpne");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A1_IF_ICMPLT:
strcpy(bytecode->name, "if_icmplt");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A2_IF_ICMPGE:
strcpy(bytecode->name, "if_icmpge");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A3_IF_ICMPGT:
strcpy(bytecode->name, "if_icmpgt");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A4_IF_ICMPLE:
strcpy(bytecode->name, "if_icmple");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A5_IF_ACMPEQ:
strcpy(bytecode->name, "if_acmpeq");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A6_IF_ACMPNE:
strcpy(bytecode->name, "if_acmpne");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case BYTECODE_A7_GOTO:
strcpy(bytecode->name, "goto");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->atype = RZ_ANALYSIS_OP_TYPE_JMP;
break;
case BYTECODE_A8_JSR:
strcpy(bytecode->name, "jsr");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->stack_output = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CALL;
break;
case BYTECODE_A9_RET:
strcpy(bytecode->name, "ret");
load_ut8(bytecode, jvm, BYTECODE_TYPE_NUMBER, ut32);
bytecode->size = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_AA_TABLESWITCH:
strcpy(bytecode->name, "tableswitch");
if (!decode_tableswitch(jvm, bytecode)) {
rz_warn_if_reached();
return false;
}
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
bytecode->stack_input = 1;
break;
case BYTECODE_AB_LOOKUPSWITCH:
strcpy(bytecode->name, "lookupswitch");
if (!decode_lookupswitch(jvm, bytecode)) {
rz_warn_if_reached();
return false;
}
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
bytecode->stack_input = 1;
break;
case BYTECODE_AC_IRETURN:
strcpy(bytecode->name, "ireturn");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_AD_LRETURN:
strcpy(bytecode->name, "lreturn");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_AE_FRETURN:
strcpy(bytecode->name, "freturn");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_AF_DRETURN:
strcpy(bytecode->name, "dreturn");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_B0_ARETURN:
strcpy(bytecode->name, "areturn");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_B1_RETURN:
strcpy(bytecode->name, "return");
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_RET;
break;
case BYTECODE_B2_GETSTATIC:
strcpy(bytecode->name, "getstatic");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_B3_PUTSTATIC:
strcpy(bytecode->name, "putstatic");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_POP;
break;
case BYTECODE_B4_GETFIELD:
strcpy(bytecode->name, "getfield");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case BYTECODE_B5_PUTFIELD:
strcpy(bytecode->name, "putfield");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 2;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_POP;
break;
case BYTECODE_B6_INVOKEVIRTUAL:
strcpy(bytecode->name, "invokevirtual");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UCALL;
break;
case BYTECODE_B7_INVOKESPECIAL:
strcpy(bytecode->name, "invokespecial");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UCALL;
break;
case BYTECODE_B8_INVOKESTATIC:
strcpy(bytecode->name, "invokestatic");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UCALL;
break;
case BYTECODE_B9_INVOKEINTERFACE:
strcpy(bytecode->name, "invokeinterface");
load_ut16_ut8(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, BYTECODE_TYPE_NUMBER, ut32, ut32);
bytecode->stack_input = 1;
bytecode->size = 5; // not an error
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UCALL;
break;
case BYTECODE_BA_INVOKEDYNAMIC:
strcpy(bytecode->name, "invokedynamic");
load_ut16_ut8(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, BYTECODE_TYPE_NUMBER, ut32, ut32);
bytecode->size = 5; // not an error
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UCALL;
break;
case BYTECODE_BB_NEW:
strcpy(bytecode->name, "new");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_NEW;
break;
case BYTECODE_BC_NEWARRAY:
/* bool 4, char 5, float 6, double 7, byte 8, short 9, int 10, long 11 */
strcpy(bytecode->name, "newarray");
load_ut8(bytecode, jvm, BYTECODE_TYPE_ATYPE, ut32);
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_NEW;
break;
case BYTECODE_BD_ANEWARRAY:
strcpy(bytecode->name, "anewarray");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_NEW;
break;
case BYTECODE_BE_ARRAYLENGTH:
strcpy(bytecode->name, "arraylength");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_LENGTH;
break;
case BYTECODE_BF_ATHROW:
strcpy(bytecode->name, "athrow");
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SWI;
break;
case BYTECODE_C0_CHECKCAST:
strcpy(bytecode->name, "checkcast");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UCJMP;
break;
case BYTECODE_C1_INSTANCEOF:
strcpy(bytecode->name, "instanceof");
load_ut16(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, ut32);
bytecode->stack_input = 1;
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case BYTECODE_C2_MONITORENTER:
strcpy(bytecode->name, "monitorenter");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SYNC;
break;
case BYTECODE_C3_MONITOREXIT:
strcpy(bytecode->name, "monitorexit");
bytecode->stack_input = 1;
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SYNC;
break;
case BYTECODE_C4_WIDE:
strcpy(bytecode->name, "wide");
bytecode->size = 1;
break;
case BYTECODE_C5_MULTIANEWARRAY:
strcpy(bytecode->name, "multianewarray");
load_ut16_ut8(bytecode, jvm, BYTECODE_TYPE_CONST_POOL, BYTECODE_TYPE_NUMBER, ut32, ut32);
bytecode->stack_input = 1;
bytecode->stack_output = 1;
break;
case BYTECODE_C6_IFNULL:
strcpy(bytecode->name, "ifnull");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
bytecode->stack_input = 1;
break;
case BYTECODE_C7_IFNONNULL:
strcpy(bytecode->name, "ifnonnull");
load_ut16(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st16);
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CJMP;
bytecode->stack_input = 1;
break;
case BYTECODE_C8_GOTO_W:
strcpy(bytecode->name, "goto_w");
load_ut32(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_JMP;
break;
case BYTECODE_C9_JSR_W:
strcpy(bytecode->name, "jsr_w");
load_ut32(bytecode, jvm, BYTECODE_TYPE_ADDRESS, st32);
bytecode->stack_output = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_CALL;
break;
case BYTECODE_CA_BREAKPOINT:
strcpy(bytecode->name, "breakpoint");
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SWI;
break;
case BYTECODE_FE_IMPDEP1:
strcpy(bytecode->name, "impdep1");
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SWI;
break;
case BYTECODE_FF_IMPDEP2:
strcpy(bytecode->name, "impdep2");
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_SWI;
break;
default:
strcpy(bytecode->name, "illegal");
bytecode->size = 1;
bytecode->atype = RZ_ANALYSIS_OP_TYPE_ILL;
jvm->current++;
return true;
}
if (!bytecode->atype) {
bytecode->atype = RZ_ANALYSIS_OP_TYPE_UNK;
}
bytecode->opcode = byte;
bytecode->pc = jvm->pc + jvm->current;
jvm->current += bytecode->size;
return true;
}
void bytecode_snprint(RzStrBuf *sb, Bytecode *bytecode) {
rz_return_if_fail(sb && bytecode);
ut64 address;
if (bytecode->opcode == BYTECODE_AA_TABLESWITCH) {
rz_return_if_fail(bytecode->extra);
TableSwitch *ts = (TableSwitch *)bytecode->extra;
address = bytecode->pc + ts->pc_default;
rz_strbuf_setf(sb, "%s default: 0x%" PFMT64x, bytecode->name, address);
} else if (bytecode->opcode == BYTECODE_AB_LOOKUPSWITCH) {
rz_return_if_fail(bytecode->extra);
LookupSwitch *ls = (LookupSwitch *)bytecode->extra;
address = bytecode->pc + ls->pc_default;
rz_strbuf_setf(sb, "%s default: 0x%" PFMT64x, bytecode->name, address);
} else if (bytecode->type[0] > 0 && !bytecode->type[1]) {
if (bytecode->type[0] == BYTECODE_TYPE_NUMBER) {
rz_strbuf_setf(sb, "%s %d", bytecode->name, bytecode->args[0]);
} else if (bytecode->type[0] == BYTECODE_TYPE_CONST_POOL) {
rz_strbuf_setf(sb, "%s " JAVA_ASM_CONSTANT_POOL_STR "%u", bytecode->name, bytecode->args[0]);
} else if (bytecode->type[0] == BYTECODE_TYPE_ADDRESS) {
address = bytecode->pc + bytecode->args[0];
rz_strbuf_setf(sb, "%s 0x%" PFMT64x, bytecode->name, address);
} else if (bytecode->type[0] == BYTECODE_TYPE_ATYPE) {
const char *type = NULL;
switch (bytecode->args[0]) {
case 4:
type = "bool";
break;
case 5:
type = "char";
break;
case 6:
type = "float";
break;
case 7:
type = "double";
break;
case 8:
type = "byte";
break;
case 9:
type = "short";
break;
case 10:
type = "int";
break;
case 11:
type = "long";
break;
default:
break;
}
if (type) {
rz_strbuf_setf(sb, "%s %s", bytecode->name, type);
} else {
rz_strbuf_setf(sb, "%s unknown_type_%u", bytecode->name, bytecode->args[0]);
}
} else {
rz_strbuf_setf(sb, "%s %u", bytecode->name, bytecode->args[0]);
rz_warn_if_reached();
}
} else if (bytecode->type[0] > 0 && bytecode->type[1] > 0) {
if (bytecode->type[0] == BYTECODE_TYPE_NUMBER &&
bytecode->type[1] == BYTECODE_TYPE_NUMBER) {
rz_strbuf_setf(sb, "%s %d %d", bytecode->name, bytecode->args[0], bytecode->args[1]);
} else if (bytecode->type[0] == BYTECODE_TYPE_CONST_POOL &&
bytecode->type[1] == BYTECODE_TYPE_NUMBER) {
rz_strbuf_setf(sb, "%s " JAVA_ASM_CONSTANT_POOL_STR "%u %d", bytecode->name, bytecode->args[0], bytecode->args[1]);
} else {
rz_strbuf_setf(sb, "%s %d %d", bytecode->name, bytecode->args[0], bytecode->args[1]);
rz_warn_if_reached();
}
} else {
rz_strbuf_setf(sb, "%s", bytecode->name);
}
}
void bytecode_clean(Bytecode *bytecode) {
rz_return_if_fail(bytecode);
free(bytecode->extra);
}
bool jvm_init(JavaVM *jvm, const ut8 *buffer, const ut32 size, ut64 pc, ut64 section) {
rz_return_val_if_fail(jvm && buffer && size > 0, false);
jvm->buffer = buffer;
jvm->size = size;
jvm->current = 0;
jvm->pc = pc;
jvm->section = section;
return true;
}
bool jvm_fetch(JavaVM *jvm, Bytecode *bytecode) {
rz_return_val_if_fail(jvm && bytecode, false);
return decode_instruction(jvm, bytecode);
}