Java assembler (#903)

This commit is contained in:
Giovanni 2021-03-25 10:52:36 +01:00 committed by GitHub
parent 2172b195f6
commit 34e8f7e768
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 761 additions and 40 deletions

View file

@ -0,0 +1,488 @@
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include "assembler.h"
#include "const.h"
#define return_error_if_size_lt(a, b) \
do { \
if (a < b) { \
RZ_LOG_ERROR("[!] java_assembler: no enough output buffer (requires %d bytes).\n", b); \
return false; \
} \
} while (0)
#define return_error_if_empty_input(a, b) \
do { \
if (RZ_STR_ISEMPTY(a) || b < 1) { \
RZ_LOG_ERROR("[!] java_assembler: the input is empty.\n"); \
return false; \
} \
} while (0)
typedef bool (*AsmEncoder)(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written);
typedef struct _jasm {
const char *opcode;
st32 length;
ut8 bytecode;
AsmEncoder encode;
} JavaAsm;
static bool encode_not_implemented(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
RZ_LOG_ERROR("[!] java_assembler: not implemented.\n");
return false;
}
static bool encode_only_bcode(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 1);
*written = 1;
output[0] = bytecode;
return true;
}
static bool encode_st8(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 2);
return_error_if_empty_input(input, input_size);
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between %d and %d (inclusive).\n", input, INT8_MIN, INT8_MAX);
return false;
}
*written = 2;
output[0] = bytecode;
((st8 *)output)[1] = (st8)strtoll(input, NULL, 0);
return true;
}
static bool encode_ut8(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 2);
return_error_if_empty_input(input, input_size);
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between %d and %d (inclusive).\n", input, INT8_MIN, INT8_MAX);
return false;
}
*written = 2;
output[0] = bytecode;
output[1] = (ut8)strtoll(input, NULL, 0);
return true;
}
static bool encode_addr32(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 5);
return_error_if_empty_input(input, input_size);
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between %d and %d (inclusive).\n", input, INT16_MIN, INT16_MAX);
return false;
}
*written = 5;
output[0] = bytecode;
st64 n = strtoll(input, NULL, 0);
st32 addr = n - pc;
rz_write_be32(output + 1, addr);
return true;
}
static bool encode_addr16(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 3);
return_error_if_empty_input(input, input_size);
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between %d and %d (inclusive).\n", input, INT16_MIN, INT16_MAX);
return false;
}
*written = 3;
output[0] = bytecode;
st64 n = strtoll(input, NULL, 0);
st16 addr = n - pc;
rz_write_be16(output + 1, addr);
return true;
}
static bool encode_st16(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 3);
return_error_if_empty_input(input, input_size);
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between %d and %d (inclusive).\n", input, INT16_MIN, INT16_MAX);
return false;
}
*written = 3;
output[0] = bytecode;
st16 n = strtoll(input, NULL, 0);
rz_write_be16(output + 1, n);
return true;
}
static bool encode_const_pool8(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 2);
return_error_if_empty_input(input, input_size);
ut32 cpool_len = strlen(JAVA_ASM_CONSTANT_POOL_STR);
if (!strncmp(input, JAVA_ASM_CONSTANT_POOL_STR, cpool_len)) {
input += cpool_len;
}
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", input, UINT8_MAX);
return false;
}
*written = 2;
output[0] = bytecode;
output[1] = (ut8)strtoll(input, NULL, 0);
return true;
}
static bool encode_const_pool16(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 3);
return_error_if_empty_input(input, input_size);
ut32 cpool_len = strlen(JAVA_ASM_CONSTANT_POOL_STR);
if (!strncmp(input, JAVA_ASM_CONSTANT_POOL_STR, cpool_len)) {
input += cpool_len;
}
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", input, UINT16_MAX);
return false;
}
*written = 3;
output[0] = bytecode;
ut16 n = (ut16)strtoll(input, NULL, 0);
rz_write_be16(output + 1, n);
return true;
}
static bool encode_const_pool16_ut8(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 4);
return_error_if_empty_input(input, input_size);
ut32 cpool_len = strlen(JAVA_ASM_CONSTANT_POOL_STR);
if (!strncmp(input, JAVA_ASM_CONSTANT_POOL_STR, cpool_len)) {
input += cpool_len;
}
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", input, UINT16_MAX);
return false;
}
const char *next = NULL;
char *tmp = NULL;
ut16 cpool = (ut16)strtoll(input, &tmp, 0);
if (!tmp || tmp == (input + input_size) || !(next = rz_str_trim_head_ro(tmp))) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", tmp, UINT8_MAX);
}
if (!rz_is_valid_input_num_value(NULL, next)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", input, UINT8_MAX);
return false;
}
ut8 num = (ut8)strtoll(next, NULL, 0);
*written = 4;
output[0] = bytecode;
rz_write_be16(output + 1, cpool);
output[3] = num;
return true;
}
static bool encode_ut8x2(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 3);
return_error_if_empty_input(input, input_size);
if (!rz_is_valid_input_num_value(NULL, input)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", input, UINT8_MAX);
return false;
}
const char *next = NULL;
char *tmp = NULL;
ut16 arg0 = (ut16)strtoll(input, &tmp, 0);
if (!tmp || tmp == (input + input_size) || !(next = rz_str_trim_head_ro(tmp))) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", tmp, UINT8_MAX);
}
if (!rz_is_valid_input_num_value(NULL, next)) {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid number between 0 and %u (inclusive).\n", input, UINT8_MAX);
return false;
}
ut8 arg1 = (ut8)strtoll(next, NULL, 0);
*written = 3;
output[0] = bytecode;
output[1] = arg0;
output[2] = arg1;
return true;
}
static bool encode_atype(ut8 bytecode, const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
return_error_if_size_lt(output_size, 2);
return_error_if_empty_input(input, input_size);
ut8 byte = 0;
/* bool 4, char 5, float 6, double 7, byte 8, short 9, int 10, long 11 */
if (!strncmp(input, "bool", strlen("bool"))) {
byte = 4;
} else if (!strncmp(input, "char", strlen("char"))) {
byte = 5;
} else if (!strncmp(input, "float", strlen("float"))) {
byte = 6;
} else if (!strncmp(input, "double", strlen("double"))) {
byte = 7;
} else if (!strncmp(input, "byte", strlen("byte"))) {
byte = 8;
} else if (!strncmp(input, "short", strlen("short"))) {
byte = 9;
} else if (!strncmp(input, "int", strlen("int"))) {
byte = 10;
} else if (!strncmp(input, "long", strlen("long"))) {
byte = 11;
} else {
RZ_LOG_ERROR("[!] java_assembler: '%s' is not a valid native type (accepted: bool, char, float, double, byte, short, int, long).\n", input);
return false;
}
*written = 2;
output[0] = bytecode;
output[1] = byte;
return true;
}
#define NS(x) x, (sizeof(x) - 1)
static const JavaAsm instructions[205] = {
{ NS("wide") /* */, BYTECODE_C4_WIDE /* */, encode_only_bcode },
{ NS("tableswitch") /* */, BYTECODE_AA_TABLESWITCH /* */, encode_not_implemented },
{ NS("swap") /* */, BYTECODE_5F_SWAP /* */, encode_only_bcode },
{ NS("sipush") /* */, BYTECODE_11_SIPUSH /* */, encode_st16 },
{ NS("sastore") /* */, BYTECODE_56_SASTORE /* */, encode_only_bcode },
{ NS("saload") /* */, BYTECODE_35_SALOAD /* */, encode_only_bcode },
{ NS("return") /* */, BYTECODE_B1_RETURN /* */, encode_only_bcode },
{ NS("ret") /* */, BYTECODE_A9_RET /* */, encode_ut8 },
{ NS("putstatic") /* */, BYTECODE_B3_PUTSTATIC /* */, encode_const_pool16 },
{ NS("putfield") /* */, BYTECODE_B5_PUTFIELD /* */, encode_const_pool16 },
{ NS("pop2") /* */, BYTECODE_58_POP2 /* */, encode_only_bcode },
{ NS("pop") /* */, BYTECODE_57_POP /* */, encode_only_bcode },
{ NS("nop") /* */, BYTECODE_00_NOP /* */, encode_only_bcode },
{ NS("newarray") /* */, BYTECODE_BC_NEWARRAY /* */, encode_atype },
{ NS("new") /* */, BYTECODE_BB_NEW /* */, encode_const_pool16 },
{ NS("multianewarray") /* */, BYTECODE_C5_MULTIANEWARRAY /* */, encode_const_pool16_ut8 },
{ NS("monitorexit") /* */, BYTECODE_C3_MONITOREXIT /* */, encode_only_bcode },
{ NS("monitorenter") /* */, BYTECODE_C2_MONITORENTER /* */, encode_only_bcode },
{ NS("lxor") /* */, BYTECODE_83_LXOR /* */, encode_only_bcode },
{ NS("lushr") /* */, BYTECODE_7D_LUSHR /* */, encode_only_bcode },
{ NS("lsub") /* */, BYTECODE_65_LSUB /* */, encode_only_bcode },
{ NS("lstore_3") /* */, BYTECODE_42_LSTORE_3 /* */, encode_only_bcode },
{ NS("lstore_2") /* */, BYTECODE_41_LSTORE_2 /* */, encode_only_bcode },
{ NS("lstore_1") /* */, BYTECODE_40_LSTORE_1 /* */, encode_only_bcode },
{ NS("lstore_0") /* */, BYTECODE_3F_LSTORE_0 /* */, encode_only_bcode },
{ NS("lstore") /* */, BYTECODE_37_LSTORE /* */, encode_ut8 },
{ NS("lshr") /* */, BYTECODE_7B_LSHR /* */, encode_only_bcode },
{ NS("lshl") /* */, BYTECODE_79_LSHL /* */, encode_only_bcode },
{ NS("lreturn") /* */, BYTECODE_AD_LRETURN /* */, encode_only_bcode },
{ NS("lrem") /* */, BYTECODE_71_LREM /* */, encode_only_bcode },
{ NS("lor") /* */, BYTECODE_81_LOR /* */, encode_only_bcode },
{ NS("lookupswitch") /* */, BYTECODE_AB_LOOKUPSWITCH /* */, encode_not_implemented },
{ NS("lneg") /* */, BYTECODE_75_LNEG /* */, encode_only_bcode },
{ NS("lmul") /* */, BYTECODE_69_LMUL /* */, encode_only_bcode },
{ NS("lload_3") /* */, BYTECODE_21_LLOAD_3 /* */, encode_only_bcode },
{ NS("lload_2") /* */, BYTECODE_20_LLOAD_2 /* */, encode_only_bcode },
{ NS("lload_1") /* */, BYTECODE_1F_LLOAD_1 /* */, encode_only_bcode },
{ NS("lload_0") /* */, BYTECODE_1E_LLOAD_0 /* */, encode_only_bcode },
{ NS("lload") /* */, BYTECODE_16_LLOAD /* */, encode_ut8 },
{ NS("ldiv") /* */, BYTECODE_6D_LDIV /* */, encode_only_bcode },
{ NS("ldc_w") /* */, BYTECODE_13_LDC_W /* */, encode_const_pool16 },
{ NS("ldc2_w") /* */, BYTECODE_14_LDC2_W /* */, encode_const_pool16 },
{ NS("ldc") /* */, BYTECODE_12_LDC /* */, encode_const_pool8 },
{ NS("lconst_1") /* */, BYTECODE_0A_LCONST_1 /* */, encode_only_bcode },
{ NS("lconst_0") /* */, BYTECODE_09_LCONST_0 /* */, encode_only_bcode },
{ NS("lcmp") /* */, BYTECODE_94_LCMP /* */, encode_only_bcode },
{ NS("lastore") /* */, BYTECODE_50_LASTORE /* */, encode_only_bcode },
{ NS("land") /* */, BYTECODE_7F_LAND /* */, encode_only_bcode },
{ NS("laload") /* */, BYTECODE_2F_LALOAD /* */, encode_only_bcode },
{ NS("ladd") /* */, BYTECODE_61_LADD /* */, encode_only_bcode },
{ NS("l2i") /* */, BYTECODE_88_L2I /* */, encode_only_bcode },
{ NS("l2f") /* */, BYTECODE_89_L2F /* */, encode_only_bcode },
{ NS("l2d") /* */, BYTECODE_8A_L2D /* */, encode_only_bcode },
{ NS("jsr_w") /* */, BYTECODE_C9_JSR_W /* */, encode_addr32 },
{ NS("jsr") /* */, BYTECODE_A8_JSR /* */, encode_addr16 },
{ NS("ixor") /* */, BYTECODE_82_IXOR /* */, encode_only_bcode },
{ NS("iushr") /* */, BYTECODE_7C_IUSHR /* */, encode_only_bcode },
{ NS("isub") /* */, BYTECODE_64_ISUB /* */, encode_only_bcode },
{ NS("istore_3") /* */, BYTECODE_3E_ISTORE_3 /* */, encode_only_bcode },
{ NS("istore_2") /* */, BYTECODE_3D_ISTORE_2 /* */, encode_only_bcode },
{ NS("istore_1") /* */, BYTECODE_3C_ISTORE_1 /* */, encode_only_bcode },
{ NS("istore_0") /* */, BYTECODE_3B_ISTORE_0 /* */, encode_only_bcode },
{ NS("istore") /* */, BYTECODE_36_ISTORE /* */, encode_ut8 },
{ NS("ishr") /* */, BYTECODE_7A_ISHR /* */, encode_only_bcode },
{ NS("ishl") /* */, BYTECODE_78_ISHL /* */, encode_only_bcode },
{ NS("ireturn") /* */, BYTECODE_AC_IRETURN /* */, encode_only_bcode },
{ NS("irem") /* */, BYTECODE_70_IREM /* */, encode_only_bcode },
{ NS("ior") /* */, BYTECODE_80_IOR /* */, encode_only_bcode },
{ NS("invokevirtual") /* */, BYTECODE_B6_INVOKEVIRTUAL /* */, encode_const_pool16 },
{ NS("invokestatic") /* */, BYTECODE_B8_INVOKESTATIC /* */, encode_const_pool16 },
{ NS("invokespecial") /* */, BYTECODE_B7_INVOKESPECIAL /* */, encode_const_pool16 },
{ NS("invokeinterface") /**/, BYTECODE_B9_INVOKEINTERFACE /**/, encode_const_pool16_ut8 },
{ NS("invokedynamic") /* */, BYTECODE_BA_INVOKEDYNAMIC /* */, encode_const_pool16_ut8 },
{ NS("instanceof") /* */, BYTECODE_C1_INSTANCEOF /* */, encode_const_pool16 },
{ NS("ineg") /* */, BYTECODE_74_INEG /* */, encode_only_bcode },
{ NS("imul") /* */, BYTECODE_68_IMUL /* */, encode_only_bcode },
{ NS("impdep2") /* */, BYTECODE_FF_IMPDEP2 /* */, encode_only_bcode },
{ NS("impdep1") /* */, BYTECODE_FE_IMPDEP1 /* */, encode_only_bcode },
{ NS("iload_3") /* */, BYTECODE_1D_ILOAD_3 /* */, encode_only_bcode },
{ NS("iload_2") /* */, BYTECODE_1C_ILOAD_2 /* */, encode_only_bcode },
{ NS("iload_1") /* */, BYTECODE_1B_ILOAD_1 /* */, encode_only_bcode },
{ NS("iload_0") /* */, BYTECODE_1A_ILOAD_0 /* */, encode_only_bcode },
{ NS("iload") /* */, BYTECODE_15_ILOAD /* */, encode_ut8 },
{ NS("iinc") /* */, BYTECODE_84_IINC /* */, encode_ut8x2 },
{ NS("ifnull") /* */, BYTECODE_C6_IFNULL /* */, encode_addr16 },
{ NS("ifnonnull") /* */, BYTECODE_C7_IFNONNULL /* */, encode_addr16 },
{ NS("ifne") /* */, BYTECODE_9A_IFNE /* */, encode_addr16 },
{ NS("iflt") /* */, BYTECODE_9B_IFLT /* */, encode_addr16 },
{ NS("ifle") /* */, BYTECODE_9E_IFLE /* */, encode_addr16 },
{ NS("ifgt") /* */, BYTECODE_9D_IFGT /* */, encode_addr16 },
{ NS("ifge") /* */, BYTECODE_9C_IFGE /* */, encode_addr16 },
{ NS("ifeq") /* */, BYTECODE_99_IFEQ /* */, encode_addr16 },
{ NS("if_icmpne") /* */, BYTECODE_A0_IF_ICMPNE /* */, encode_addr16 },
{ NS("if_icmplt") /* */, BYTECODE_A1_IF_ICMPLT /* */, encode_addr16 },
{ NS("if_icmple") /* */, BYTECODE_A4_IF_ICMPLE /* */, encode_addr16 },
{ NS("if_icmpgt") /* */, BYTECODE_A3_IF_ICMPGT /* */, encode_addr16 },
{ NS("if_icmpge") /* */, BYTECODE_A2_IF_ICMPGE /* */, encode_addr16 },
{ NS("if_icmpeq") /* */, BYTECODE_9F_IF_ICMPEQ /* */, encode_addr16 },
{ NS("if_acmpne") /* */, BYTECODE_A6_IF_ACMPNE /* */, encode_addr16 },
{ NS("if_acmpeq") /* */, BYTECODE_A5_IF_ACMPEQ /* */, encode_addr16 },
{ NS("idiv") /* */, BYTECODE_6C_IDIV /* */, encode_only_bcode },
{ NS("iconst_m1") /* */, BYTECODE_02_ICONST_M1 /* */, encode_only_bcode },
{ NS("iconst_5") /* */, BYTECODE_08_ICONST_5 /* */, encode_only_bcode },
{ NS("iconst_4") /* */, BYTECODE_07_ICONST_4 /* */, encode_only_bcode },
{ NS("iconst_3") /* */, BYTECODE_06_ICONST_3 /* */, encode_only_bcode },
{ NS("iconst_2") /* */, BYTECODE_05_ICONST_2 /* */, encode_only_bcode },
{ NS("iconst_1") /* */, BYTECODE_04_ICONST_1 /* */, encode_only_bcode },
{ NS("iconst_0") /* */, BYTECODE_03_ICONST_0 /* */, encode_only_bcode },
{ NS("iastore") /* */, BYTECODE_4F_IASTORE /* */, encode_only_bcode },
{ NS("iand") /* */, BYTECODE_7E_IAND /* */, encode_only_bcode },
{ NS("iaload") /* */, BYTECODE_2E_IALOAD /* */, encode_only_bcode },
{ NS("iadd") /* */, BYTECODE_60_IADD /* */, encode_only_bcode },
{ NS("i2s") /* */, BYTECODE_93_I2S /* */, encode_only_bcode },
{ NS("i2l") /* */, BYTECODE_85_I2L /* */, encode_only_bcode },
{ NS("i2f") /* */, BYTECODE_86_I2F /* */, encode_only_bcode },
{ NS("i2d") /* */, BYTECODE_87_I2D /* */, encode_only_bcode },
{ NS("i2c") /* */, BYTECODE_92_I2C /* */, encode_only_bcode },
{ NS("i2b") /* */, BYTECODE_91_I2B /* */, encode_only_bcode },
{ NS("goto_w") /* */, BYTECODE_C8_GOTO_W /* */, encode_addr32 },
{ NS("goto") /* */, BYTECODE_A7_GOTO /* */, encode_addr16 },
{ NS("getstatic") /* */, BYTECODE_B2_GETSTATIC /* */, encode_const_pool16 },
{ NS("getfield") /* */, BYTECODE_B4_GETFIELD /* */, encode_const_pool16 },
{ NS("fsub") /* */, BYTECODE_66_FSUB /* */, encode_only_bcode },
{ NS("fstore_3") /* */, BYTECODE_46_FSTORE_3 /* */, encode_only_bcode },
{ NS("fstore_2") /* */, BYTECODE_45_FSTORE_2 /* */, encode_only_bcode },
{ NS("fstore_1") /* */, BYTECODE_44_FSTORE_1 /* */, encode_only_bcode },
{ NS("fstore_0") /* */, BYTECODE_43_FSTORE_0 /* */, encode_only_bcode },
{ NS("fstore") /* */, BYTECODE_38_FSTORE /* */, encode_ut8 },
{ NS("freturn") /* */, BYTECODE_AE_FRETURN /* */, encode_only_bcode },
{ NS("frem") /* */, BYTECODE_72_FREM /* */, encode_only_bcode },
{ NS("fneg") /* */, BYTECODE_76_FNEG /* */, encode_only_bcode },
{ NS("fmul") /* */, BYTECODE_6A_FMUL /* */, encode_only_bcode },
{ NS("fload_3") /* */, BYTECODE_25_FLOAD_3 /* */, encode_only_bcode },
{ NS("fload_2") /* */, BYTECODE_24_FLOAD_2 /* */, encode_only_bcode },
{ NS("fload_1") /* */, BYTECODE_23_FLOAD_1 /* */, encode_only_bcode },
{ NS("fload_0") /* */, BYTECODE_22_FLOAD_0 /* */, encode_only_bcode },
{ NS("fload") /* */, BYTECODE_17_FLOAD /* */, encode_ut8 },
{ NS("fdiv") /* */, BYTECODE_6E_FDIV /* */, encode_only_bcode },
{ NS("fconst_2") /* */, BYTECODE_0D_FCONST_2 /* */, encode_only_bcode },
{ NS("fconst_1") /* */, BYTECODE_0C_FCONST_1 /* */, encode_only_bcode },
{ NS("fconst_0") /* */, BYTECODE_0B_FCONST_0 /* */, encode_only_bcode },
{ NS("fcmpl") /* */, BYTECODE_95_FCMPL /* */, encode_only_bcode },
{ NS("fcmpg") /* */, BYTECODE_96_FCMPG /* */, encode_only_bcode },
{ NS("fastore") /* */, BYTECODE_51_FASTORE /* */, encode_only_bcode },
{ NS("faload") /* */, BYTECODE_30_FALOAD /* */, encode_only_bcode },
{ NS("fadd") /* */, BYTECODE_62_FADD /* */, encode_only_bcode },
{ NS("f2l") /* */, BYTECODE_8C_F2L /* */, encode_only_bcode },
{ NS("f2i") /* */, BYTECODE_8B_F2I /* */, encode_only_bcode },
{ NS("f2d") /* */, BYTECODE_8D_F2D /* */, encode_only_bcode },
{ NS("dup_x2") /* */, BYTECODE_5B_DUP_X2 /* */, encode_only_bcode },
{ NS("dup_x1") /* */, BYTECODE_5A_DUP_X1 /* */, encode_only_bcode },
{ NS("dup2_x2") /* */, BYTECODE_5E_DUP2_X2 /* */, encode_only_bcode },
{ NS("dup2_x1") /* */, BYTECODE_5D_DUP2_X1 /* */, encode_only_bcode },
{ NS("dup2") /* */, BYTECODE_5C_DUP2 /* */, encode_only_bcode },
{ NS("dup") /* */, BYTECODE_59_DUP /* */, encode_only_bcode },
{ NS("dsub") /* */, BYTECODE_67_DSUB /* */, encode_only_bcode },
{ NS("dstore_3") /* */, BYTECODE_4A_DSTORE_3 /* */, encode_only_bcode },
{ NS("dstore_2") /* */, BYTECODE_49_DSTORE_2 /* */, encode_only_bcode },
{ NS("dstore_1") /* */, BYTECODE_48_DSTORE_1 /* */, encode_only_bcode },
{ NS("dstore_0") /* */, BYTECODE_47_DSTORE_0 /* */, encode_only_bcode },
{ NS("dstore") /* */, BYTECODE_39_DSTORE /* */, encode_ut8 },
{ NS("dreturn") /* */, BYTECODE_AF_DRETURN /* */, encode_only_bcode },
{ NS("drem") /* */, BYTECODE_73_DREM /* */, encode_only_bcode },
{ NS("dneg") /* */, BYTECODE_77_DNEG /* */, encode_only_bcode },
{ NS("dmul") /* */, BYTECODE_6B_DMUL /* */, encode_only_bcode },
{ NS("dload_3") /* */, BYTECODE_29_DLOAD_3 /* */, encode_only_bcode },
{ NS("dload_2") /* */, BYTECODE_28_DLOAD_2 /* */, encode_only_bcode },
{ NS("dload_1") /* */, BYTECODE_27_DLOAD_1 /* */, encode_only_bcode },
{ NS("dload_0") /* */, BYTECODE_26_DLOAD_0 /* */, encode_only_bcode },
{ NS("dload") /* */, BYTECODE_18_DLOAD /* */, encode_ut8 },
{ NS("ddiv") /* */, BYTECODE_6F_DDIV /* */, encode_only_bcode },
{ NS("dconst_1") /* */, BYTECODE_0F_DCONST_1 /* */, encode_only_bcode },
{ NS("dconst_0") /* */, BYTECODE_0E_DCONST_0 /* */, encode_only_bcode },
{ NS("dcmpl") /* */, BYTECODE_97_DCMPL /* */, encode_only_bcode },
{ NS("dcmpg") /* */, BYTECODE_98_DCMPG /* */, encode_only_bcode },
{ NS("dastore") /* */, BYTECODE_52_DASTORE /* */, encode_only_bcode },
{ NS("daload") /* */, BYTECODE_31_DALOAD /* */, encode_only_bcode },
{ NS("dadd") /* */, BYTECODE_63_DADD /* */, encode_only_bcode },
{ NS("d2l") /* */, BYTECODE_8F_D2L /* */, encode_only_bcode },
{ NS("d2i") /* */, BYTECODE_8E_D2I /* */, encode_only_bcode },
{ NS("d2f") /* */, BYTECODE_90_D2F /* */, encode_only_bcode },
{ NS("checkcast") /* */, BYTECODE_C0_CHECKCAST /* */, encode_const_pool16 },
{ NS("castore") /* */, BYTECODE_55_CASTORE /* */, encode_only_bcode },
{ NS("caload") /* */, BYTECODE_34_CALOAD /* */, encode_only_bcode },
{ NS("breakpoint") /* */, BYTECODE_CA_BREAKPOINT /* */, encode_only_bcode },
{ NS("bipush") /* */, BYTECODE_10_BIPUSH /* */, encode_st8 },
{ NS("bastore") /* */, BYTECODE_54_BASTORE /* */, encode_only_bcode },
{ NS("baload") /* */, BYTECODE_33_BALOAD /* */, encode_only_bcode },
{ NS("athrow") /* */, BYTECODE_BF_ATHROW /* */, encode_only_bcode },
{ NS("astore_3") /* */, BYTECODE_4E_ASTORE_3 /* */, encode_only_bcode },
{ NS("astore_2") /* */, BYTECODE_4D_ASTORE_2 /* */, encode_only_bcode },
{ NS("astore_1") /* */, BYTECODE_4C_ASTORE_1 /* */, encode_only_bcode },
{ NS("astore_0") /* */, BYTECODE_4B_ASTORE_0 /* */, encode_only_bcode },
{ NS("astore") /* */, BYTECODE_3A_ASTORE /* */, encode_ut8 },
{ NS("arraylength") /* */, BYTECODE_BE_ARRAYLENGTH /* */, encode_only_bcode },
{ NS("areturn") /* */, BYTECODE_B0_ARETURN /* */, encode_only_bcode },
{ NS("anewarray") /* */, BYTECODE_BD_ANEWARRAY /* */, encode_const_pool16 },
{ NS("aload_3") /* */, BYTECODE_2D_ALOAD_3 /* */, encode_only_bcode },
{ NS("aload_2") /* */, BYTECODE_2C_ALOAD_2 /* */, encode_only_bcode },
{ NS("aload_1") /* */, BYTECODE_2B_ALOAD_1 /* */, encode_only_bcode },
{ NS("aload_0") /* */, BYTECODE_2A_ALOAD_0 /* */, encode_only_bcode },
{ NS("aload") /* */, BYTECODE_19_ALOAD /* */, encode_ut8 },
{ NS("aconst_null") /* */, BYTECODE_01_ACONST_NULL /* */, encode_only_bcode },
{ NS("aastore") /* */, BYTECODE_53_AASTORE /* */, encode_only_bcode },
{ NS("aaload") /* */, BYTECODE_32_AALOAD /* */, encode_only_bcode }
};
#undef NS
bool java_assembler(const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written) {
rz_return_val_if_fail(input && output && input_size > 0 && output_size > 0, false);
for (ut32 i = 0; i < RZ_ARRAY_SIZE(instructions); ++i) {
if (input_size < instructions[i].length) {
continue;
}
if (!rz_str_ncasecmp(input, instructions[i].opcode, instructions[i].length)) {
const char *p = rz_str_trim_head_ro(input + instructions[i].length);
st32 used = p ? (p - input) : input_size;
return instructions[i].encode(instructions[i].bytecode, p, input_size - used, output, output_size, pc, written);
}
}
RZ_LOG_ERROR("[!] java_assembler: invalid assembly.\n");
return false;
}

View file

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef RZ_ASM_JAVA_ASSEMBLER_H
#define RZ_ASM_JAVA_ASSEMBLER_H
#include <rz_types.h>
#include <rz_util.h>
#include "bytecode.h"
bool java_assembler(const char *input, st32 input_size, ut8 *output, st32 output_size, ut64 pc, st32 *written);
#endif /* RZ_ASM_JAVA_ASSEMBLER_H */

View file

@ -202,7 +202,7 @@
#define BYTECODE_C2_MONITORENTER (0xC2)
#define BYTECODE_C3_MONITOREXIT (0xC3)
#define BYTECODE_C4_WIDE (0xC4)
#define BYTECODE_C5_MULTINEWARRAY (0xC5)
#define BYTECODE_C5_MULTIANEWARRAY (0xC5)
#define BYTECODE_C6_IFNULL (0xC6)
#define BYTECODE_C7_IFNONNULL (0xC7)
#define BYTECODE_C8_GOTO_W (0xC8)

View file

@ -36,9 +36,9 @@
#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 + 2); \
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 + 1); \
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) \
@ -1394,8 +1394,8 @@ static bool decode_instruction(JavaVM *jvm, Bytecode *bytecode) {
strcpy(bytecode->name, "wide");
bytecode->size = 1;
break;
case BYTECODE_C5_MULTINEWARRAY:
strcpy(bytecode->name, "multinewarray");
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;

View file

@ -112,6 +112,7 @@ rz_asm_sources = [
#'arch/i4004/i4004dis.c',
#'arch/i8080/i8080dis.c',
'arch/java/jvm.c',
'arch/java/assembler.c',
'arch/lanai/gnu/lanai-dis.c',
'arch/lanai/gnu/lanai-opc.c',
'arch/luac/lua_arch.c',

View file

@ -8,6 +8,7 @@
#include <rz_core.h>
#include "../arch/java/jvm.h"
#include "../arch/java/assembler.h"
typedef struct java_analysis_context_t {
LookupSwitch ls;
@ -121,6 +122,19 @@ static bool java_fini(void *user) {
return true;
}
static int java_assemble(RzAsm *a, RzAsmOp *ao, const char *str) {
ut8 buffer[128];
st32 written = 0;
st32 slen = strlen(str);
if (!java_assembler(str, slen, buffer, sizeof(buffer), a->pc, &written)) {
return -1;
}
rz_strbuf_setbin(&ao->buf, (const ut8 *)&buffer, written);
return written;
}
RzAsmPlugin rz_asm_plugin_java = {
.name = "java",
.desc = "Java bytecode disassembler",
@ -132,6 +146,7 @@ RzAsmPlugin rz_asm_plugin_java = {
.init = java_init,
.fini = java_fini,
.disassemble = &java_disassemble,
.assemble = &java_assemble,
};
#ifndef RZ_PLUGIN_INCORE

View file

@ -1,35 +1,240 @@
d "aload_0" 2a
d "bipush 100" 1064 0x00000006
d "bipush 32" 1020
d "bipush 33" 1021
d "goto 0x10" a70007 0x00000009
d "goto 0x10" a70007 0x00000009
d "goto 0x19" a70010 0x00000009
d "goto 0x3b" a70037 0x00000004
d "goto 0x10" a70007 0x00000009
d "i2b" 91
d "iadd" 60
d "iconst_0" 03
d "iconst_1" 04
d "if_icmpeq 0xc" 9f0008 0x00000004
d "if_icmpge 0xc" a20008 0x00000004
d "if_icmpgt 0xc" a30008 0x00000004
d "if_icmple 0xc" a40008 0x00000004
d "if_icmplt 0xc" a10008 0x00000004
d "if_icmplt 0xc" a1ffe7 0x00000025
d "if_icmplt 0xc" a1fff1 0x0000001b
d "if_icmpne 0x1a" a00006 0x00000014
d "if_icmpne 0xc" a00008 0x00000004
d "iinc 0 1" 840001
d "iload_0" 1a
d "iload_1" 1b
d "iload_2" 1c
d "irem" 70
d "ireturn" ac
d "ireturn" ac 0x00000011
d "istore_1" 3c
d "istore_2" 3d
d "ixor" 82
d "nop" 00
d "return" b1
d "sipush 255" 1100ff
ad "aaload" 32
ad "aastore" 53
ad "aconst_null" 01
ad "aload 10" 190a
ad "aload_0" 2a
ad "aload_1" 2b
ad "aload_2" 2c
ad "aload_3" 2d
ad "anewarray constant_pool.511" bd01ff
a "anewarray 511" bd01ff
ad "areturn" b0
ad "arraylength" be
ad "astore 10" 3a0a
ad "astore_0" 4b
ad "astore_1" 4c
ad "astore_2" 4d
ad "astore_3" 4e
ad "athrow" bf
ad "baload" 33
ad "bastore" 54
ad "bipush 100" 1064
ad "bipush 100" 1064 0x00000006
ad "bipush 32" 1020
ad "bipush 33" 1021
ad "breakpoint" ca
ad "caload" 34
ad "castore" 55
ad "checkcast constant_pool.511" c001ff
a "checkcast 511" c001ff
ad "d2f" 90
ad "d2i" 8e
ad "d2l" 8f
ad "dadd" 63
ad "daload" 31
ad "dastore" 52
ad "dcmpg" 98
ad "dcmpl" 97
ad "dconst_0" 0e
ad "dconst_1" 0f
ad "ddiv" 6f
ad "dload 10" 180a
ad "dload_0" 26
ad "dload_1" 27
ad "dload_2" 28
ad "dload_3" 29
ad "dmul" 6b
ad "dneg" 77
ad "drem" 73
ad "dreturn" af
ad "dstore 10" 390a
ad "dstore_0" 47
ad "dstore_1" 48
ad "dstore_2" 49
ad "dstore_3" 4a
ad "dsub" 67
ad "dup" 59
ad "dup2" 5c
ad "dup2_x1" 5d
ad "dup2_x2" 5e
ad "dup_x1" 5a
ad "dup_x2" 5b
ad "f2d" 8d
ad "f2i" 8b
ad "f2l" 8c
ad "fadd" 62
ad "faload" 30
ad "fastore" 51
ad "fcmpg" 96
ad "fcmpl" 95
ad "fconst_0" 0b
ad "fconst_1" 0c
ad "fconst_2" 0d
ad "fdiv" 6e
ad "fload 10" 170a
ad "fload_0" 22
ad "fload_1" 23
ad "fload_2" 24
ad "fload_3" 25
ad "fmul" 6a
ad "fneg" 76
ad "frem" 72
ad "freturn" ae
ad "fstore 10" 380a
ad "fstore_0" 43
ad "fstore_1" 44
ad "fstore_2" 45
ad "fstore_3" 46
ad "fsub" 66
ad "getfield constant_pool.511" b401ff
a "getfield 511" b401ff
ad "getstatic constant_pool.511" b201ff
a "getstatic 511" b201ff
ad "goto 0x10" a70007 0x00000009
ad "goto 0x10" a70007 0x00000009
ad "goto 0x19" a70010 0x00000009
ad "goto 0x1ff" a701ff
ad "goto 0x3b" a70037 0x00000004
ad "goto_w 0xa64" c800000a64
ad "i2b" 91
ad "i2c" 92
ad "i2d" 87
ad "i2f" 86
ad "i2l" 85
ad "i2s" 93
ad "iadd" 60
ad "iaload" 2e
ad "iand" 7e
ad "iastore" 4f
ad "iconst_0" 03
ad "iconst_1" 04
ad "iconst_2" 05
ad "iconst_3" 06
ad "iconst_4" 07
ad "iconst_5" 08
ad "iconst_m1" 02
ad "idiv" 6c
ad "if_acmpeq 0xc" a50008 0x00000004
ad "if_acmpne 0xc" a60008 0x00000004
ad "if_icmpeq 0xc" 9f0008 0x00000004
ad "if_icmpge 0xc" a20008 0x00000004
ad "if_icmpgt 0xc" a30008 0x00000004
ad "if_icmple 0xc" a40008 0x00000004
ad "if_icmplt 0xc" a10008 0x00000004
ad "if_icmplt 0xc" a1ffe7 0x00000025
ad "if_icmplt 0xc" a1fff1 0x0000001b
ad "if_icmpne 0x1a" a00006 0x00000014
ad "if_icmpne 0xc" a00008 0x00000004
ad "ifeq 0xc" 990008 0x00000004
ad "ifge 0xc" 9c0008 0x00000004
ad "ifgt 0xc" 9d0008 0x00000004
ad "ifle 0xc" 9e0008 0x00000004
ad "iflt 0xc" 9b0008 0x00000004
ad "ifne 0xc" 9a0008 0x00000004
ad "ifnonnull 0xc" c70008 0x00000004
ad "ifnull 0xc" c60008 0x00000004
ad "iinc 0 1" 840001
ad "iinc 5 15" 84050f
ad "iload 10" 150a
ad "iload_0" 1a
ad "iload_1" 1b
ad "iload_2" 1c
ad "iload_3" 1d
ad "impdep1" fe
ad "impdep2" ff
ad "imul" 68
ad "ineg" 74
ad "instanceof constant_pool.511" c101ff
a "instanceof 511" c101ff
ad "invokedynamic constant_pool.511 10" ba01ff0a
a "invokedynamic 511 10" ba01ff0a
ad "invokeinterface constant_pool.511 10" b901ff0a
a "invokeinterface 511 10" b901ff0a
ad "invokespecial constant_pool.511" b701ff
a "invokespecial 511" b701ff
ad "invokestatic constant_pool.511" b801ff
a "invokestatic 511" b801ff
ad "invokevirtual constant_pool.511" b601ff
a "invokevirtual 511" b601ff
ad "ior" 80
ad "irem" 70
ad "ireturn" ac
ad "ireturn" ac 0x00000011
ad "ishl" 78
ad "ishr" 7a
ad "istore 10" 360a
ad "istore_0" 3b
ad "istore_1" 3c
ad "istore_2" 3d
ad "istore_3" 3e
ad "isub" 64
ad "iushr" 7c
ad "ixor" 82
ad "jsr 0x1ff" a801ff
ad "jsr_w 0xa64" c900000a64
ad "l2d" 8a
ad "l2f" 89
ad "l2i" 88
ad "ladd" 61
ad "laload" 2f
ad "land" 7f
ad "lastore" 50
ad "lcmp" 94
ad "lconst_0" 09
ad "lconst_1" 0a
ad "ldc constant_pool.255" 12ff
a "ldc 255" 12ff
ad "ldc2_w constant_pool.511" 1401ff
a "ldc2_w 511" 1401ff
ad "ldc_w constant_pool.511" 1301ff
a "ldc_w 511" 1301ff
ad "ldiv" 6d
ad "lload 10" 160a
ad "lload_0" 1e
ad "lload_1" 1f
ad "lload_2" 20
ad "lload_3" 21
ad "lmul" 69
ad "lneg" 75
ad "lor" 81
ad "lrem" 71
ad "lreturn" ad
ad "lshl" 79
ad "lshr" 7b
ad "lstore 10" 370a
ad "lstore_0" 3f
ad "lstore_1" 40
ad "lstore_2" 41
ad "lstore_3" 42
ad "lsub" 65
ad "lushr" 7d
ad "lxor" 83
ad "monitorenter" c2
ad "monitorexit" c3
ad "multianewarray constant_pool.10 100" c5000a64
a "multianewarray 10 100" c5000a64
ad "new constant_pool.511" bb01ff
a "new 511" bb01ff
ad "newarray bool" bc04
ad "newarray byte" bc08
ad "newarray char" bc05
ad "newarray double" bc07
ad "newarray float" bc06
ad "newarray int" bc0a
ad "newarray long" bc0b
ad "newarray short" bc09
ad "nop" 00
ad "pop" 57
ad "pop2" 58
ad "putfield constant_pool.511" b501ff
a "putfield 511" b501ff
ad "putstatic constant_pool.511" b301ff
a "putstatic 511" b301ff
ad "ret 7" a907
ad "return" b1
ad "saload" 35
ad "sastore" 56
ad "sipush 100" 110064
ad "sipush 511" 1101ff
ad "swap" 5f
ad "wide" c4