488 lines
26 KiB
C
488 lines
26 KiB
C
// 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;
|
|
}
|