From de8a5cac5532845643a52d1231b17a7b34feb50a Mon Sep 17 00:00:00 2001 From: Giovanni <561184+wargio@users.noreply.github.com> Date: Thu, 21 Apr 2022 16:19:48 +0200 Subject: [PATCH] Porting pd and subcommands to newshell (#2552) * pd + pda[jJqi=] * Added pdb/pdC/pdf/pdk/pdl/pdp/pdr and removed pdi in favour of pdq * removed pdx since is an alias for 2 other commands. * Added pdR and pds[fb] * Added example and fixed bug when cw * Removed pdx test file since it is the same as cmd_pix --- librz/core/cmd/cmd_print.c | 784 +++++++++++++++++++++++++++- librz/core/cmd_descs/cmd_cmp.yaml | 11 + librz/core/cmd_descs/cmd_descs.c | 311 +++++++++++ librz/core/cmd_descs/cmd_descs.h | 19 + librz/core/cmd_descs/cmd_print.yaml | 182 +++++++ librz/core/cmp.c | 10 +- librz/core/disasm.c | 2 - test/db/cmd/cmd_0 | 3 + test/db/cmd/cmd_c | 16 +- test/db/cmd/cmd_disassembly | 18 +- test/db/cmd/cmd_pd | 38 ++ test/db/cmd/cmd_pdx | 47 -- test/db/cmd/retries | 14 - 13 files changed, 1361 insertions(+), 94 deletions(-) delete mode 100644 test/db/cmd/cmd_pdx delete mode 100644 test/db/cmd/retries diff --git a/librz/core/cmd/cmd_print.c b/librz/core/cmd/cmd_print.c index f98c44a79b..50655e67a9 100644 --- a/librz/core/cmd/cmd_print.c +++ b/librz/core/cmd/cmd_print.c @@ -18,7 +18,7 @@ static const char *help_msg_pa[] = { "Usage: pa[edD]", "[asm|hex]", "print (dis)assembled", "pa", " [assembly]", "print hexpairs of the given assembly expression", "paD", " [hexpairs]", "print assembly expression from hexpairs and show hexpairs", - "pad", " [hexpairs]", "print assembly expression from hexpairs (alias for pdx, pix)", + "pad", " [hexpairs]", "print assembly expression from hexpairs (alias for pix)", "pade", " [hexpairs]", "print ESIL expression from hexpairs", "pae", " [assembly]", "print ESIL expression of the given assembly expression", NULL @@ -328,7 +328,6 @@ static const char *help_msg_pd[] = { "pdr.", "", "recursive disassemble across the function graph (from current basic block)", "pds", "[?]", "disassemble summary (strings, calls, jumps, refs) (see pdsf and pdfs)", "pdt", " [n] [query]", "disassemble N instructions in a table (see dtd for debug traces)", - "pdx", " [hex]", "alias for pad or pix", NULL }; @@ -451,7 +450,7 @@ static const char *help_msg_pi[] = { "pij", "", "print N instructions in JSON", "pir", "", "like 'pdr' but with 'pI' output", "piu", "[q] [limit]", "disasm until ujmp or ret is found (see pdp)", - "pix", " [hexpairs]", "alias for pdx and pad", + "pix", " [hexpairs]", "alias for pad", NULL }; @@ -1005,7 +1004,7 @@ static void findMethodBounds(RzList *methods, ut64 *min, ut64 *max) { *max = at_max; } -static ut64 findClassBounds(RzCore *core, const char *input, int *len) { +static ut64 findClassBounds(RzCore *core, int *len) { ut64 min = 0, max = 0; RzListIter *iter; RzBinClass *c; @@ -5428,11 +5427,6 @@ RZ_IPI int rz_cmd_print(void *data, const char *input) { } } - if (input[1] == 'x') { // pdx - __cmd_pad(core, rz_str_trim_head_ro(input + 2)); - return 0; - } - const char *sp = NULL; if (input[1] == '.') { sp = input + 2; @@ -5478,7 +5472,7 @@ RZ_IPI int rz_cmd_print(void *data, const char *input) { case 'k': // "pdk" -print class { int len = 0; - ut64 at = findClassBounds(core, rz_str_trim_head_ro(input + 2), &len); + ut64 at = findClassBounds(core, &len); return rz_core_cmdf(core, "pD %d @ %" PFMT64u, len, at); } case 'i': // "pdi" // "pDi" @@ -7198,3 +7192,773 @@ CMD_PRINT_BYTE_ARRAY_HANDLER_NORMAL(rz_cmd_print_byte_array_swift_handler, RZ_LA CMD_PRINT_BYTE_ARRAY_HANDLER_NORMAL(rz_cmd_print_byte_array_yara_handler, RZ_LANG_BYTE_ARRAY_YARA); #undef CMD_PRINT_BYTE_ARRAY_HANDLER_NORMAL #undef CMD_PRINT_BYTE_ARRAY_HANDLER_ENDIAN + +static void disassembly_n_instructions_as_table(RzTable *t, RzCore *core, int n_instrs) { + ut8 buffer[256]; + rz_table_set_columnsf(t, "snssssss", "name", "addr", "bytes", "disasm", "comment", "esil", "refs", "xrefs"); + const int minopsz = 1; + const int options = RZ_ANALYSIS_OP_MASK_BASIC | RZ_ANALYSIS_OP_MASK_HINT | RZ_ANALYSIS_OP_MASK_DISASM | RZ_ANALYSIS_OP_MASK_ESIL; + ut64 offset = core->offset; + for (int i = 0; i < n_instrs; i++) { + RzAnalysisOp *op = rz_core_analysis_op(core, offset, options); + if (!op || op->size < 1) { + i += minopsz; + offset += minopsz; + continue; + } + const char *comment = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, offset); + if (!comment) { + comment = ""; + } + rz_io_read_at(core->io, offset, buffer, RZ_MIN(op->size, sizeof(buffer))); + char *bytes = rz_hex_bin2strdup(buffer, op->size); + RzFlagItem *flag = rz_flag_get_i(core->flags, offset); + char *function_name = flag ? flag->name : ""; + const char *esil = RZ_STRBUF_SAFEGET(&op->esil); + char *refs = __op_refs(core, op, 0); + char *xrefs = __op_refs(core, op, 1); + rz_table_add_rowf(t, "sXssssss", function_name, offset, bytes, op->mnemonic, comment, esil, refs, xrefs); + free(bytes); + free(xrefs); + free(refs); + offset += op->size; + rz_analysis_op_free(op); + } +} + +static void core_disassembly_n_instructions(RzCore *core, int n_instrs, RzCmdStateOutput *state) { + ut32 old_blocksize = core->blocksize; + ut64 old_offset = core->offset; + + if (n_instrs < 0) { + ut64 new_offset = old_offset; + if (!rz_core_prevop_addr(core, old_offset, -n_instrs, &new_offset)) { + new_offset = rz_core_prevop_addr_force(core, old_offset, -n_instrs); + } + ut32 new_blocksize = new_offset - old_blocksize; + if (new_blocksize > old_blocksize) { + rz_core_block_size(core, new_blocksize); + } + rz_core_seek(core, new_offset, true); + } + + switch (state->mode) { + case RZ_OUTPUT_MODE_STANDARD: + rz_core_print_disasm(core->print, core, core->offset, core->block, core->blocksize, RZ_ABS(n_instrs), 0, 0, false, NULL, NULL); + break; + case RZ_OUTPUT_MODE_TABLE: + disassembly_n_instructions_as_table(state->d.t, core, RZ_ABS(n_instrs)); + break; + case RZ_OUTPUT_MODE_JSON: + rz_cmd_state_output_array_start(state); + rz_core_print_disasm_json(core, core->offset, core->block, core->blocksize, RZ_ABS(n_instrs), state->d.pj); + rz_cmd_state_output_array_end(state); + break; + case RZ_OUTPUT_MODE_QUIET: + rz_core_disasm_pdi(core, RZ_ABS(n_instrs), 0, 0); + break; + default: + rz_warn_if_reached(); + break; + } + + if (n_instrs < 0) { + rz_core_block_size(core, old_blocksize); + rz_core_seek(core, old_offset, true); + } +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_n_instructions_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + st64 parsed = argc > 1 ? (st64)rz_num_math(core->num, argv[1]) : 0; + if (parsed > ST16_MAX || parsed < ST16_MIN) { + RZ_LOG_ERROR("the number of instructions is too big (%d < n_instrs < %d).\n", ST16_MAX, ST16_MIN); + return RZ_CMD_STATUS_ERROR; + } + ut32 old_blocksize = core->blocksize; + int n_instrs = parsed; + if (argc > 1 && !n_instrs) { + core->blocksize = 0; + } + + core_disassembly_n_instructions(core, n_instrs, state); + + if (argc > 1 && !n_instrs) { + core->blocksize = old_blocksize; + } + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_all_possible_opcodes_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + ut64 n_bytes = argc > 1 ? rz_num_math(core->num, argv[1]) : core->blocksize; + bool color = rz_config_get_i(core->config, "scr.color") > 0; + RzAsmOp asm_op = { 0 }; + ut32 old_blocksize = core->blocksize; + const char *pal_reg = core->cons->context->pal.reg; + const char *pal_num = core->cons->context->pal.num; + + if (n_bytes > old_blocksize) { + rz_core_block_size(core, n_bytes); + rz_core_block_read(core); + } + + rz_cmd_state_output_array_start(state); + rz_cons_break_push(NULL, NULL); + for (ut64 position = 0; position < n_bytes && !rz_cons_is_breaked(); position++) { + ut64 offset = core->offset + position; + rz_asm_set_pc(core->rasm, offset); + ut8 *buffer = core->block + position; + ut32 length = n_bytes - position; + int op_size = rz_asm_disassemble(core->rasm, &asm_op, buffer, length); + char *op_hex = rz_hex_bin2strdup(buffer, RZ_MAX(op_size, 1)); + char *assembly = strdup(op_size > 0 ? rz_asm_op_get_asm(&asm_op) : "illegal"); + char *colored = NULL; + + if (color && state->mode != RZ_OUTPUT_MODE_JSON) { + RzAnalysisOp aop = { 0 }; + rz_analysis_op(core->analysis, &aop, offset, buffer, length, RZ_ANALYSIS_OP_MASK_ALL); + char *tmp = rz_print_colorize_opcode(core->print, assembly, pal_reg, pal_num, false, 0); + colored = rz_str_newf("%s%s" Color_RESET, rz_print_color_op_type(core->print, aop.type), tmp); + free(tmp); + } + + switch (state->mode) { + case RZ_OUTPUT_MODE_STANDARD: + rz_cons_printf("0x%08" PFMT64x " %20s %s\n", offset, op_hex, colored ? colored : assembly); + break; + case RZ_OUTPUT_MODE_JSON: + pj_o(state->d.pj); + pj_kn(state->d.pj, "addr", offset); + pj_ks(state->d.pj, "bytes", op_hex); + pj_ks(state->d.pj, "inst", assembly); + pj_end(state->d.pj); + break; + case RZ_OUTPUT_MODE_QUIET: + rz_cons_printf("%s\n", colored ? colored : assembly); + break; + default: + rz_warn_if_reached(); + break; + } + free(op_hex); + free(assembly); + free(colored); + } + rz_cons_break_pop(); + rz_cmd_state_output_array_end(state); + + if (n_bytes > old_blocksize) { + rz_core_block_size(core, old_blocksize); + rz_core_block_read(core); + } + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_all_possible_opcodes_treeview_handler(RzCore *core, int argc, const char **argv) { + bool color = rz_config_get_i(core->config, "scr.color") > 0; + RzAsmOp asm_op = { 0 }; + const ut32 n_bytes = 28; // uses 56 chars + ut32 old_blocksize = core->blocksize; + const char *pal_reg = core->cons->context->pal.reg; + const char *pal_num = core->cons->context->pal.num; + + if (old_blocksize < n_bytes) { + rz_core_block_size(core, 256); + rz_core_block_read(core); + } + + rz_cons_break_push(NULL, NULL); + for (ut32 position = 0; position < n_bytes && !rz_cons_is_breaked(); position++) { + ut64 offset = core->offset + position; + rz_asm_set_pc(core->rasm, offset); + ut8 *buffer = core->block + position; + ut32 length = RZ_MAX(n_bytes - position, core->blocksize - position); + int op_size = rz_asm_disassemble(core->rasm, &asm_op, buffer, length); + if (op_size < 1) { + continue; + } + op_size = RZ_MAX(op_size, 1); + char *op_hex = rz_hex_bin2strdup(buffer, op_size); + char *assembly = strdup(op_size > 0 ? rz_asm_op_get_asm(&asm_op) : "illegal"); + char *colored = NULL; + + if (color) { + RzAnalysisOp aop = { 0 }; + rz_analysis_op(core->analysis, &aop, offset, buffer, length, RZ_ANALYSIS_OP_MASK_ALL); + char *tmp = rz_print_colorize_opcode(core->print, assembly, pal_reg, pal_num, false, 0); + colored = rz_str_newf("%s%s" Color_RESET, rz_print_color_op_type(core->print, aop.type), tmp); + free(tmp); + } + + int padding = position * 2; + int space = 60 - padding; + + if ((position + op_size) >= 30) { + ut32 last = (30 - position) * 2; + op_hex[last - 1] = '.'; + op_hex[last] = 0; + } + + rz_cons_printf("0x%08" PFMT64x " %*s%*s %s\n", offset, padding, "", -space, op_hex, colored ? colored : assembly); + free(op_hex); + free(assembly); + free(colored); + } + rz_cons_break_pop(); + + if (old_blocksize < n_bytes) { + rz_core_block_size(core, old_blocksize); + rz_core_block_read(core); + } + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_basic_block_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + RzAnalysisBlock *b = rz_analysis_find_most_relevant_block_in(core->analysis, core->offset); + core->num->value = 0; + if (!b) { + RZ_LOG_ERROR("Cannot find function at 0x%08" PFMT64x "\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + + ut8 *block = malloc(b->size + 1); + if (!block) { + RZ_LOG_ERROR("Cannot allocate buffer\n"); + return RZ_CMD_STATUS_ERROR; + } + rz_io_read_at(core->io, b->addr, block, b->size); + + rz_cmd_state_output_array_start(state); + switch (state->mode) { + case RZ_OUTPUT_MODE_STANDARD: + core->num->value = rz_core_print_disasm(core->print, core, b->addr, block, b->size, 9999, 0, 2, false, NULL, NULL); + break; + case RZ_OUTPUT_MODE_JSON: + core->num->value = 1; + rz_core_print_disasm_json(core, b->addr, block, b->size, 0, state->d.pj); + break; + default: + rz_warn_if_reached(); + break; + } + rz_cmd_state_output_array_end(state); + + free(block); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_basic_block_as_text_json_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + RzAnalysisBlock *b = rz_analysis_find_most_relevant_block_in(core->analysis, core->offset); + core->num->value = 0; + if (!b) { + RZ_LOG_ERROR("Cannot find function at 0x%08" PFMT64x "\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + + ut8 *block = malloc(b->size + 1); + if (!block) { + RZ_LOG_ERROR("Cannot allocate buffer\n"); + return RZ_CMD_STATUS_ERROR; + } + rz_io_read_at(core->io, b->addr, block, b->size); + + core->num->value = rz_core_print_disasm(core->print, core, b->addr, block, b->size, 9999, 0, 2, true, state->d.pj, NULL); + + free(block); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_comments_in_n_instructions_handler(RzCore *core, int argc, const char **argv) { + st64 parsed = argc > 1 ? (st64)rz_num_math(core->num, argv[1]) : core->blocksize; + if (parsed > ST16_MAX || parsed < ST16_MIN) { + RZ_LOG_ERROR("the number of instructions is too big (%d < n_instrs < %d).\n", ST16_MAX, ST16_MIN); + return RZ_CMD_STATUS_ERROR; + } + int n_instrs = parsed; + if (rz_core_disasm_pdi(core, n_instrs, 0, 'C') < 0) { + return RZ_CMD_STATUS_ERROR; + } + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_n_instructions_with_flow_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + st64 parsed = argc > 1 ? (st64)rz_num_math(core->num, argv[1]) : (core->blocksize / 4); + if (parsed > ST16_MAX || parsed < ST16_MIN) { + RZ_LOG_ERROR("the number of instructions is too big (%d < n_instrs < %d).\n", ST16_MAX, ST16_MIN); + return RZ_CMD_STATUS_ERROR; + } + int n_instrs = parsed; + int mode = 0; + switch (state->mode) { + case RZ_OUTPUT_MODE_STANDARD: + mode = RZ_MODE_PRINT; + break; + case RZ_OUTPUT_MODE_JSON: + mode = RZ_MODE_JSON; + break; + case RZ_OUTPUT_MODE_QUIET: + mode = RZ_MODE_SIMPLE; + break; + case RZ_OUTPUT_MODE_QUIETEST: + mode = RZ_MODE_SIMPLEST; + break; + default: + rz_warn_if_reached(); + return RZ_CMD_STATUS_ERROR; + } + // this command is going to be removed when esil will be removed. + rz_core_disasm_pde(core, n_instrs, mode); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_function_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + core->num->value = 0; + ut32 old_blocksize = core->blocksize; + RzAnalysisFunction *function = rz_analysis_get_fcn_in(core->analysis, core->offset, RZ_ANALYSIS_FCN_TYPE_ROOT); + if (!function) { + function = rz_analysis_get_fcn_in(core->analysis, core->offset, 0); + } + if (!function) { + RZ_LOG_ERROR("Cannot find function at 0x%08" PFMT64x "\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + + if (state->mode == RZ_OUTPUT_MODE_JSON) { + bool ret = rz_core_print_function_disasm_json(core, function, state->d.pj); + rz_core_block_size(core, old_blocksize); + return ret ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR; + } + + ut64 linear_size = rz_analysis_function_linear_size(function); + ut64 max_real_size = rz_analysis_function_realsize(function) + 4096; + if (max_real_size < linear_size) { + RZ_LOG_ERROR("Linear size differs too much from the bbsum, please use pdr instead.\n"); + return RZ_CMD_STATUS_ERROR; + } + + ut64 start = function->addr; // For pdf, start disassembling at the entrypoint + ut64 end = rz_analysis_function_max_addr(function); + if (end <= start) { + RZ_LOG_ERROR("Cannot print function because the end offset is less or equal to the start offset\n"); + return RZ_CMD_STATUS_ERROR; + } + + ut64 size = end - start; + ut8 *bytes = malloc(size); + if (!bytes) { + RZ_LOG_ERROR("Cannot allocate buffer\n"); + return RZ_CMD_STATUS_ERROR; + } + + (void)rz_io_read_at(core->io, start, bytes, size); + core->num->value = rz_core_print_disasm(core->print, core, start, bytes, size, size, 0, 1, 0, NULL, function); + free(bytes); + + rz_core_block_size(core, old_blocksize); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_function_summary_handler(RzCore *core, int argc, const char **argv) { + ut64 old_offset = core->offset; + ut32 old_blocksize = core->blocksize; + RzAnalysisFunction *function = rz_analysis_get_fcn_in(core->analysis, core->offset, RZ_ANALYSIS_FCN_TYPE_FCN | RZ_ANALYSIS_FCN_TYPE_SYM); + if (!function) { + RZ_LOG_ERROR("Cannot find function at 0x%08" PFMT64x "\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + ut32 rs = rz_analysis_function_realsize(function); + ut32 fs = rz_analysis_function_linear_size(function); + rz_core_seek(core, old_offset, SEEK_SET); + rz_core_block_size(core, RZ_MAX(rs, fs)); + disasm_strings(core, "dfs", function); + + rz_core_block_size(core, old_blocksize); + rz_core_seek(core, old_offset, SEEK_SET); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_n_instrs_as_text_json_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + ut32 old_blocksize = core->blocksize; + ut64 old_offset = core->offset; + core->num->value = 0; + + st64 parsed = argc > 1 ? (st64)rz_num_math(core->num, argv[1]) : 0; + if (parsed > ST16_MAX || parsed < ST16_MIN) { + RZ_LOG_ERROR("the number of instructions is too big (%d < n_instrs < %d).\n", ST16_MAX, ST16_MIN); + return RZ_CMD_STATUS_ERROR; + } + int n_instrs = parsed; + if (n_instrs < 0) { + ut64 new_offset = old_offset; + if (!rz_core_prevop_addr(core, old_offset, -n_instrs, &new_offset)) { + new_offset = rz_core_prevop_addr_force(core, old_offset, -n_instrs); + } + ut32 new_blocksize = new_offset - old_blocksize; + if (new_blocksize > old_blocksize) { + rz_core_block_size(core, new_blocksize); + } + rz_core_seek(core, new_offset, true); + } + if (rz_cons_singleton()->is_html) { + rz_cons_singleton()->is_html = false; + rz_cons_singleton()->was_html = true; + } + + core->num->value = rz_core_print_disasm(core->print, core, core->offset, core->block, core->blocksize, RZ_ABS(n_instrs), 0, 1, true, NULL, NULL); + rz_cons_newline(); + + if (n_instrs < 0) { + rz_core_block_size(core, old_blocksize); + rz_core_seek(core, old_offset, true); + } + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassembly_all_methods_class_handler(RzCore *core, int argc, const char **argv) { + ut32 old_blocksize = core->blocksize; + ut64 old_offset = core->offset; + + int len = 0; + ut64 at = findClassBounds(core, &len); + if (!at) { + RZ_LOG_ERROR("Cannot find class at 0x%" PFMT64x ".\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + + rz_core_seek(core, at, true); + + // TODO: remove this and use C api. + // on success returns 0 else negative + int ret = rz_core_cmdf(core, "pD %d", len); + + rz_core_block_size(core, old_blocksize); + rz_core_seek(core, old_offset, true); + return ret >= 0 ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR; +} + +RZ_IPI RzCmdStatus rz_cmd_sizes_of_n_instructions_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + ut32 old_blocksize = core->blocksize; + ut64 old_offset = core->offset; + st64 ret = 0; + + st64 parsed = argc > 1 ? (st64)rz_num_math(core->num, argv[1]) : (core->blocksize / 4); + if (parsed > ST16_MAX || parsed < ST16_MIN) { + RZ_LOG_ERROR("the number of instructions is too big (%d < n_instrs < %d).\n", ST16_MAX, ST16_MIN); + return RZ_CMD_STATUS_ERROR; + } + int n_instrs = parsed; + if (n_instrs < 0) { + ut64 new_offset = old_offset; + if (!rz_core_prevop_addr(core, old_offset, -n_instrs, &new_offset)) { + new_offset = rz_core_prevop_addr_force(core, old_offset, -n_instrs); + } + ut32 new_blocksize = new_offset - old_blocksize; + if (new_blocksize > old_blocksize) { + rz_core_block_size(core, new_blocksize); + } + rz_core_seek(core, new_offset, true); + } + + rz_cmd_state_output_array_start(state); + rz_cons_break_push(NULL, NULL); + for (ut32 i = 0, j = 0; i < core->blocksize && j < RZ_ABS(n_instrs); i += ret, j++) { + RzAsmOp asm_op = { 0 }; + ret = rz_asm_disassemble(core->rasm, &asm_op, core->block + i, core->blocksize - i); + if (rz_cons_is_breaked()) { + break; + } + // be sure to return 0 when it fails to disassemble the + // instruction to uniform the output across all disassemblers. + int op_size = ret < 1 ? 0 : ret; + switch (state->mode) { + case RZ_OUTPUT_MODE_STANDARD: + rz_cons_printf("%d\n", op_size); + break; + case RZ_OUTPUT_MODE_JSON: + pj_N(state->d.pj, op_size); + break; + default: + rz_warn_if_reached(); + return RZ_CMD_STATUS_ERROR; + } + if (ret < 1) { + ret = 1; + } + } + rz_cons_break_pop(); + rz_cmd_state_output_array_end(state); + + if (n_instrs < 0) { + rz_core_block_size(core, old_blocksize); + rz_core_seek(core, old_offset, true); + } + return RZ_CMD_STATUS_OK; +} + +static void disassemble_till_return_is_found(RzCore *core, ut64 offset, ut64 limit, RzCmdStateOutput *state) { + bool src_color = rz_config_get_i(core->config, "scr.color") > 0; + const char *off_color = src_color ? rz_cons_singleton()->context->pal.b0x00 : ""; + const char *ret_color = src_color ? rz_cons_singleton()->context->pal.jmp : ""; + const char *end_color = src_color ? Color_RESET : ""; + + for (ut64 i = 0; i < limit; i++) { + RzAnalysisOp *op = rz_core_analysis_op(core, offset, RZ_ANALYSIS_OP_MASK_BASIC | RZ_ANALYSIS_OP_MASK_DISASM); + if (!op) { + return; + } + + switch (state->mode) { + case RZ_OUTPUT_MODE_QUIET: + rz_cons_printf("%s%s%s\n", ret_color, op->mnemonic, end_color); + break; + case RZ_OUTPUT_MODE_STANDARD: + rz_cons_printf("%s0x%08" PFMT64x "%s %-11s%s\n", off_color, core->offset + i, ret_color, op->mnemonic, end_color); + break; + case RZ_OUTPUT_MODE_JSON: + pj_o(state->d.pj); + pj_ks(state->d.pj, "mnemonic", op->mnemonic); + pj_kn(state->d.pj, "address", core->offset + i); + pj_end(state->d.pj); + break; + default: + rz_warn_if_reached(); + break; + } + + if (!(op->type & (RZ_ANALYSIS_OP_TYPE_RET | RZ_ANALYSIS_OP_TYPE_UJMP))) { + rz_analysis_op_free(op); + return; + } + + if (op->type == RZ_ANALYSIS_OP_TYPE_JMP) { + offset = op->jump; + } else { + offset += op->size; + } + + rz_analysis_op_free(op); + } +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_ropchain_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + ut64 limit = argc > 1 ? rz_num_math(core->num, argv[1]) : 1024; + if (limit > 1024) { + RZ_LOG_ERROR("the limit value exceeds the max value (1024).\n"); + return RZ_CMD_STATUS_ERROR; + } + ut64 asm_bits = core->rasm->bits; + bool big_endian = rz_config_get_b(core->config, "cfg.bigendian"); + bool src_color = rz_config_get_i(core->config, "scr.color") > 0; + + const char *off_color = src_color ? rz_cons_singleton()->context->pal.offset : ""; + const char *num_color = src_color ? rz_cons_singleton()->context->pal.num : ""; + const char *end_color = src_color ? Color_RESET : ""; + + if (asm_bits < 64) { + asm_bits = 32; + } + + ut32 asm_bytes = asm_bits / 8; + if (core->blocksize < asm_bytes) { + RZ_LOG_ERROR("block size is not enough big to host a word (needs to be >= %u bytes).\n", asm_bytes); + return RZ_CMD_STATUS_ERROR; + } + + ut8 *bytes = RZ_NEWS0(ut8, core->blocksize); + if (!bytes) { + RZ_LOG_ERROR("cannot allocate buffer.\n"); + return RZ_CMD_STATUS_ERROR; + } + + (void)rz_io_read_at(core->io, core->offset, bytes, core->blocksize); + + rz_cmd_state_output_array_start(state); + for (ut32 i = 0; i < core->blocksize - asm_bytes; i += asm_bytes) { + ut64 number = rz_read_ble(bytes + i, big_endian, asm_bits); + switch (state->mode) { + case RZ_OUTPUT_MODE_QUIET: + rz_cons_printf("%s0x%08" PFMT64x "%s %s0x%08" PFMT64x "%s\n", off_color, core->offset + i, end_color, num_color, number, end_color); + disassemble_till_return_is_found(core, core->offset + i, limit, state); + break; + case RZ_OUTPUT_MODE_STANDARD: + rz_cons_printf("[%s0x%08" PFMT64x "%s] %s0x%08" PFMT64x "%s\n", off_color, core->offset + i, end_color, num_color, number, end_color); + disassemble_till_return_is_found(core, core->offset + i, limit, state); + break; + case RZ_OUTPUT_MODE_JSON: + pj_o(state->d.pj); + pj_kn(state->d.pj, "address", core->offset + i); + pj_kn(state->d.pj, "bits", asm_bits); + pj_kn(state->d.pj, "word", number); + pj_ka(state->d.pj, "opcodes"); + disassemble_till_return_is_found(core, core->offset + i, limit, state); + pj_end(state->d.pj); + pj_end(state->d.pj); + break; + default: + rz_warn_if_reached(); + return RZ_CMD_STATUS_ERROR; + } + } + rz_cmd_state_output_array_end(state); + + return RZ_CMD_STATUS_OK; +} + +static bool core_walk_function_blocks(RzCore *core, RzAnalysisFunction *f, RzCmdStateOutput *state, char type_print, bool fromHere) { + RzListIter *iter; + RzAnalysisBlock *b = NULL; + const char *orig_bb_middle = rz_config_get(core->config, "asm.bb.middle"); + rz_config_set_i(core->config, "asm.bb.middle", false); + + if (rz_list_length(f->bbs) >= 1) { + ut32 fcn_size = rz_analysis_function_realsize(f); + b = rz_list_get_top(f->bbs); + if (b->size > fcn_size) { + b->size = fcn_size; + } + } + + rz_list_sort(f->bbs, (RzListComparator)bbcmp); + if (state->mode == RZ_OUTPUT_MODE_JSON) { + rz_list_foreach (f->bbs, iter, b) { + ut8 *buf = malloc(b->size); + if (!buf) { + RZ_LOG_ERROR("cannot allocate %" PFMT64u " byte(s)\n", b->size); + return false; + } + (void)rz_io_read_at(core->io, b->addr, buf, b->size); + rz_core_print_disasm_json(core, b->addr, buf, b->size, 0, state->d.pj); + free(buf); + } + } else { + bool asm_lines = rz_config_get_i(core->config, "asm.lines.bb"); + bool emu = rz_config_get_i(core->config, "asm.emu"); + ut64 saved_gp = 0; + ut8 *saved_arena = NULL; + int saved_stackptr = core->analysis->stackptr; + if (emu) { + saved_gp = core->analysis->gp; + saved_arena = rz_reg_arena_peek(core->analysis->reg); + } + rz_config_set_i(core->config, "asm.lines.bb", 0); + rz_list_foreach (f->bbs, iter, b) { + pr_bb(core, f, b, emu, saved_gp, saved_arena, type_print, fromHere); + } + if (emu) { + core->analysis->gp = saved_gp; + if (saved_arena) { + rz_reg_arena_poke(core->analysis->reg, saved_arena); + RZ_FREE(saved_arena); + } + } + core->analysis->stackptr = saved_stackptr; + rz_config_set_i(core->config, "asm.lines.bb", asm_lines); + } + rz_config_set(core->config, "asm.bb.middle", orig_bb_middle); + return true; +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_recursively_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + RzAnalysisFunction *function = rz_analysis_get_fcn_in(core->analysis, core->offset, 0); + // RZ_ANALYSIS_FCN_TYPE_FCN|RZ_ANALYSIS_FCN_TYPE_SYM); + if (!function) { + RZ_LOG_ERROR("Cannot find function at 0x%08" PFMT64x "\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + + rz_cmd_state_output_array_start(state); + bool ret = core_walk_function_blocks(core, function, state, 'D', false); + rz_cmd_state_output_array_end(state); + return ret ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR; +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_recursively_from_current_block_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + RzAnalysisFunction *function = rz_analysis_get_fcn_in(core->analysis, core->offset, 0); + // RZ_ANALYSIS_FCN_TYPE_FCN|RZ_ANALYSIS_FCN_TYPE_SYM); + if (!function) { + RZ_LOG_ERROR("Cannot find function at 0x%08" PFMT64x "\n", core->offset); + return RZ_CMD_STATUS_ERROR; + } + + rz_cmd_state_output_array_start(state); + bool ret = core_walk_function_blocks(core, function, state, 'D', true); + rz_cmd_state_output_array_end(state); + return ret ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR; +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_recursively_no_function_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { + ut64 old_offset = core->offset; + RzAnalysisOp aop = { 0 }; + ut32 aop_type; + ut64 aop_jump; + int aop_size; + + rz_cmd_state_output_array_start(state); + for (ut64 count = core->blocksize, offset = core->offset; count > 0; count--) { + rz_core_seek(core, offset, true); + + rz_analysis_op_init(&aop); + int ret = rz_analysis_op(core->analysis, &aop, offset, core->block, core->blocksize, RZ_ANALYSIS_OP_MASK_BASIC); + if (ret > 0) { + aop_type = aop.type; + aop_jump = aop.jump; + aop_size = aop.size; + } + rz_analysis_op_fini(&aop); + + if (ret < 1 || aop_size < 1) { + offset++; + continue; + } + + core_disassembly_n_instructions(core, 1, state); + + switch (aop_type) { + case RZ_ANALYSIS_OP_TYPE_JMP: + offset = aop_jump; + continue; + case RZ_ANALYSIS_OP_TYPE_UCJMP: + break; + case RZ_ANALYSIS_OP_TYPE_RET: + count = 1; // stop disassembling when hitting RET + break; + default: + break; + } + offset += aop_size; + } + rz_cmd_state_output_array_end(state); + + rz_core_seek(core, old_offset, true); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_n_bytes_handler(RzCore *core, int argc, const char **argv) { + ut64 n_bytes = argc > 1 ? rz_num_math(core->num, argv[1]) : 0; + + // small patch to reuse disasm_strings which + // needs to be rewritten entirely + char input_cmd[256]; + rz_strf(input_cmd, "ds 0x%" PFMT64x, n_bytes); + disasm_strings(core, argc > 1 ? input_cmd : "ds", NULL); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_function_handler(RzCore *core, int argc, const char **argv) { + disasm_strings(core, "dsf", NULL); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_block_handler(RzCore *core, int argc, const char **argv) { + ut64 n_bytes = argc > 1 ? rz_num_math(core->num, argv[1]) : 0; + if (!n_bytes) { + RZ_LOG_ERROR("Invalid number of bytes\n"); + return RZ_CMD_STATUS_ERROR; + } + + // small patch to reuse disasm_strings which + // needs to be rewritten entirely + char input_cmd[256]; + rz_strf(input_cmd, "dsb 0x%" PFMT64x, n_bytes); + disasm_strings(core, input_cmd, NULL); + return RZ_CMD_STATUS_OK; +} diff --git a/librz/core/cmd_descs/cmd_cmp.yaml b/librz/core/cmd_descs/cmd_cmp.yaml index 4fa10eab3c..44155410b3 100644 --- a/librz/core/cmd_descs/cmd_cmp.yaml +++ b/librz/core/cmd_descs/cmd_cmp.yaml @@ -147,6 +147,17 @@ commands: summary: Remove watcher at current offset cname: cmd_cmp_remove_watcher args: [] + details: + - name: Compare memory locations and check if there is a difference + entries: + - text: "cw 32 'pD 32' @ 0x1234" + comment: + Adds a memory region watcher of 32 bytes + at 0x1234, where it executes the command 'pD 32'. + - text: "cwl" + comment: Lists all the memory region watchers and notifies of any changes + - text: "cwx @ 0x1234" + comment: Removes the memory region watchers at 0x1234 - name: cx summary: Compare data at current offset with a hexpair string (also return in $?) cname: cmd_cmp_hexpair_string diff --git a/librz/core/cmd_descs/cmd_descs.c b/librz/core/cmd_descs/cmd_descs.c index 3a564feb10..87780baa07 100644 --- a/librz/core/cmd_descs/cmd_descs.c +++ b/librz/core/cmd_descs/cmd_descs.c @@ -32,6 +32,7 @@ static const RzCmdDescDetail analysis_hint_set_optype_details[2]; static const RzCmdDescDetail analysis_hint_set_immbase_details[3]; static const RzCmdDescDetail analysis_hint_set_offset_details[2]; static const RzCmdDescDetail cmd_cmp_unified_details[2]; +static const RzCmdDescDetail cw_details[2]; static const RzCmdDescDetail cmd_debug_list_bp_details[2]; static const RzCmdDescDetail cmd_debug_add_cond_bp_details[2]; static const RzCmdDescDetail cmd_debug_add_watchpoint_details[2]; @@ -419,6 +420,16 @@ static const RzCmdDescArg open_maps_prioritize_binid_args[2]; static const RzCmdDescArg open_maps_deprioritize_args[2]; static const RzCmdDescArg open_maps_prioritize_fd_args[2]; static const RzCmdDescArg open_exchange_args[3]; +static const RzCmdDescArg cmd_disassembly_n_instructions_args[2]; +static const RzCmdDescArg cmd_disassembly_all_possible_opcodes_args[2]; +static const RzCmdDescArg cmd_disassembly_all_possible_opcodes_treeview_args[2]; +static const RzCmdDescArg cmd_comments_in_n_instructions_args[2]; +static const RzCmdDescArg cmd_disassembly_n_instructions_with_flow_args[2]; +static const RzCmdDescArg cmd_disassembly_n_instrs_as_text_json_args[2]; +static const RzCmdDescArg cmd_sizes_of_n_instructions_args[2]; +static const RzCmdDescArg cmd_disassemble_ropchain_args[2]; +static const RzCmdDescArg cmd_disassemble_summarize_n_bytes_args[2]; +static const RzCmdDescArg cmd_disassemble_summarize_block_args[2]; static const RzCmdDescArg cmd_print_gadget_add_args[6]; static const RzCmdDescArg cmd_print_gadget_move_args[6]; static const RzCmdDescArg cmd_print_msg_digest_args[2]; @@ -4531,8 +4542,19 @@ static const RzCmdDescHelp cmd_cmp_unified_disasm_help = { .args = cmd_cmp_unified_disasm_args, }; +static const RzCmdDescDetailEntry cw_Compare_space_memory_space_locations_space_and_space_check_space_if_space_there_space_is_space_a_space_difference_detail_entries[] = { + { .text = "cw 32 'pD 32' @ 0x1234", .arg_str = NULL, .comment = "Adds a memory region watcher of 32 bytes at 0x1234, where it executes the command 'pD 32'." }, + { .text = "cwl", .arg_str = NULL, .comment = "Lists all the memory region watchers and notifies of any changes" }, + { .text = "cwx @ 0x1234", .arg_str = NULL, .comment = "Removes the memory region watchers at 0x1234" }, + { 0 }, +}; +static const RzCmdDescDetail cw_details[] = { + { .name = "Compare memory locations and check if there is a difference", .entries = cw_Compare_space_memory_space_locations_space_and_space_check_space_if_space_there_space_is_space_a_space_difference_detail_entries }, + { 0 }, +}; static const RzCmdDescHelp cw_help = { .summary = "Compare watcher commands", + .details = cw_details, }; static const RzCmdDescArg cmd_cmp_add_memory_watcher_args[] = { { @@ -9725,6 +9747,244 @@ static const RzCmdDescHelp cmd_print_byte_array_rizin_help = { .args = cmd_print_byte_array_rizin_args, }; +static const RzCmdDescHelp cmd_print_disassembly_help = { + .summary = "Print Disassembly", +}; +static const RzCmdDescArg cmd_disassembly_n_instructions_args[] = { + { + .name = "n_instrs", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_n_instructions_help = { + .summary = "Disassemble N instructions (can be negative)", + .args = cmd_disassembly_n_instructions_args, +}; + +static const RzCmdDescHelp cmd_disassembly_all_opcodes_help = { + .summary = "Disassemble all possible opcodes (byte per byte)", +}; +static const RzCmdDescArg cmd_disassembly_all_possible_opcodes_args[] = { + { + .name = "n_bytes", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_all_possible_opcodes_help = { + .summary = "Disassemble all possible opcodes (byte per byte)", + .args = cmd_disassembly_all_possible_opcodes_args, +}; + +static const RzCmdDescArg cmd_disassembly_all_possible_opcodes_treeview_args[] = { + { + .name = "n_bytes", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_all_possible_opcodes_treeview_help = { + .summary = "Disassemble all possible opcodes (treeview)", + .args = cmd_disassembly_all_possible_opcodes_treeview_args, +}; + +static const RzCmdDescHelp cmd_disasm_basic_block_help = { + .summary = "Disassemble basic block", +}; +static const RzCmdDescArg cmd_disassembly_basic_block_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_basic_block_help = { + .summary = "Disassemble basic block", + .args = cmd_disassembly_basic_block_args, +}; + +static const RzCmdDescArg cmd_disassembly_basic_block_as_text_json_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_basic_block_as_text_json_help = { + .summary = "Disassemble basic block as json containing the printed text", + .args = cmd_disassembly_basic_block_as_text_json_args, +}; + +static const RzCmdDescArg cmd_comments_in_n_instructions_args[] = { + { + .name = "n_instrs", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_comments_in_n_instructions_help = { + .summary = "Prints the comments found in N instructions", + .args = cmd_comments_in_n_instructions_args, +}; + +static const RzCmdDescArg cmd_disassembly_n_instructions_with_flow_args[] = { + { + .name = "n_instrs", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_n_instructions_with_flow_help = { + .summary = "Disassemble N instructions following execution flow from current PC", + .args = cmd_disassembly_n_instructions_with_flow_args, +}; + +static const RzCmdDescHelp cmd_disasm_func_help = { + .summary = "Disassemble a function", +}; +static const RzCmdDescArg cmd_disassembly_function_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_function_help = { + .summary = "Disassemble a function", + .args = cmd_disassembly_function_args, +}; + +static const RzCmdDescArg cmd_disassembly_function_summary_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_function_summary_help = { + .summary = "Disassemble a function and outputs the summary of it.", + .args = cmd_disassembly_function_summary_args, +}; + +static const RzCmdDescArg cmd_disassembly_n_instrs_as_text_json_args[] = { + { + .name = "n_instrs", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_n_instrs_as_text_json_help = { + .summary = "Disassemble N instructions as json containing the printed text", + .args = cmd_disassembly_n_instrs_as_text_json_args, +}; + +static const RzCmdDescArg cmd_disassembly_all_methods_class_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassembly_all_methods_class_help = { + .summary = "Disassemble all methods of a class", + .args = cmd_disassembly_all_methods_class_args, +}; + +static const RzCmdDescArg cmd_sizes_of_n_instructions_args[] = { + { + .name = "n_instrs", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_sizes_of_n_instructions_help = { + .summary = "Disassemble N instructions and prints its sizes", + .args = cmd_sizes_of_n_instructions_args, +}; + +static const RzCmdDescArg cmd_disassemble_ropchain_args[] = { + { + .name = "limit", + .type = RZ_CMD_ARG_TYPE_NUM, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_ropchain_help = { + .summary = "Disassemble instructions and follows pointers to read ropchains", + .args = cmd_disassemble_ropchain_args, +}; + +static const RzCmdDescHelp cmd_disassemble_recursive_help = { + .summary = "Disassemble recursively across the function graph", +}; +static const RzCmdDescArg cmd_disassemble_recursively_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_recursively_help = { + .summary = "Disassemble recursively across the function graph", + .args = cmd_disassemble_recursively_args, +}; + +static const RzCmdDescArg cmd_disassemble_recursively_from_current_block_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_recursively_from_current_block_help = { + .summary = "Disassemble recursively across the function graph (from current basic block)", + .args = cmd_disassemble_recursively_from_current_block_args, +}; + +static const RzCmdDescArg cmd_disassemble_recursively_no_function_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_recursively_no_function_help = { + .summary = "Disassemble recursively the block size bytes without analyzing functions", + .args = cmd_disassemble_recursively_no_function_args, +}; + +static const RzCmdDescHelp cmd_disassemble_summarize_help = { + .summary = "Summarize N bytes or current block or a function (strings, calls, jumps, refs)", +}; +static const RzCmdDescArg cmd_disassemble_summarize_n_bytes_args[] = { + { + .name = "n_bytes", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_summarize_n_bytes_help = { + .summary = "Summarize N bytes", + .args = cmd_disassemble_summarize_n_bytes_args, +}; + +static const RzCmdDescArg cmd_disassemble_summarize_function_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_summarize_function_help = { + .summary = "Summarize the current function", + .args = cmd_disassemble_summarize_function_args, +}; + +static const RzCmdDescArg cmd_disassemble_summarize_block_args[] = { + { + .name = "n_bytes", + .type = RZ_CMD_ARG_TYPE_RZNUM, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_disassemble_summarize_block_help = { + .summary = "Summarize current block", + .args = cmd_disassemble_summarize_block_args, +}; + static const RzCmdDescHelp cmd_print_gadget_help = { .summary = "Print gadgets", }; @@ -15335,6 +15595,57 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) { RzCmdDesc *cmd_print_byte_array_rizin_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_print_byte_array_cd, "pc*", rz_cmd_print_byte_array_rizin_handler, &cmd_print_byte_array_rizin_help); rz_warn_if_fail(cmd_print_byte_array_rizin_cd); + RzCmdDesc *cmd_print_disassembly_cd = rz_cmd_desc_group_state_new(core->rcmd, cmd_print_cd, "pd", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_QUIET | RZ_OUTPUT_MODE_TABLE | RZ_OUTPUT_MODE_JSON, rz_cmd_disassembly_n_instructions_handler, &cmd_disassembly_n_instructions_help, &cmd_print_disassembly_help); + rz_warn_if_fail(cmd_print_disassembly_cd); + RzCmdDesc *cmd_disassembly_all_opcodes_cd = rz_cmd_desc_group_state_new(core->rcmd, cmd_print_disassembly_cd, "pda", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_QUIET | RZ_OUTPUT_MODE_JSON, rz_cmd_disassembly_all_possible_opcodes_handler, &cmd_disassembly_all_possible_opcodes_help, &cmd_disassembly_all_opcodes_help); + rz_warn_if_fail(cmd_disassembly_all_opcodes_cd); + RzCmdDesc *cmd_disassembly_all_possible_opcodes_treeview_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_disassembly_all_opcodes_cd, "pda=", rz_cmd_disassembly_all_possible_opcodes_treeview_handler, &cmd_disassembly_all_possible_opcodes_treeview_help); + rz_warn_if_fail(cmd_disassembly_all_possible_opcodes_treeview_cd); + + RzCmdDesc *cmd_disasm_basic_block_cd = rz_cmd_desc_group_state_new(core->rcmd, cmd_print_disassembly_cd, "pdb", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_disassembly_basic_block_handler, &cmd_disassembly_basic_block_help, &cmd_disasm_basic_block_help); + rz_warn_if_fail(cmd_disasm_basic_block_cd); + RzCmdDesc *cmd_disassembly_basic_block_as_text_json_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_disasm_basic_block_cd, "pdbJ", RZ_OUTPUT_MODE_STANDARD, rz_cmd_disassembly_basic_block_as_text_json_handler, &cmd_disassembly_basic_block_as_text_json_help); + rz_warn_if_fail(cmd_disassembly_basic_block_as_text_json_cd); + + RzCmdDesc *cmd_comments_in_n_instructions_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_print_disassembly_cd, "pdC", rz_cmd_comments_in_n_instructions_handler, &cmd_comments_in_n_instructions_help); + rz_warn_if_fail(cmd_comments_in_n_instructions_cd); + + RzCmdDesc *cmd_disassembly_n_instructions_with_flow_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_print_disassembly_cd, "pde", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_QUIET | RZ_OUTPUT_MODE_QUIETEST, rz_cmd_disassembly_n_instructions_with_flow_handler, &cmd_disassembly_n_instructions_with_flow_help); + rz_warn_if_fail(cmd_disassembly_n_instructions_with_flow_cd); + + RzCmdDesc *cmd_disasm_func_cd = rz_cmd_desc_group_state_new(core->rcmd, cmd_print_disassembly_cd, "pdf", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_disassembly_function_handler, &cmd_disassembly_function_help, &cmd_disasm_func_help); + rz_warn_if_fail(cmd_disasm_func_cd); + RzCmdDesc *cmd_disassembly_function_summary_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_disasm_func_cd, "pdfs", rz_cmd_disassembly_function_summary_handler, &cmd_disassembly_function_summary_help); + rz_warn_if_fail(cmd_disassembly_function_summary_cd); + + RzCmdDesc *cmd_disassembly_n_instrs_as_text_json_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_print_disassembly_cd, "pdJ", RZ_OUTPUT_MODE_STANDARD, rz_cmd_disassembly_n_instrs_as_text_json_handler, &cmd_disassembly_n_instrs_as_text_json_help); + rz_warn_if_fail(cmd_disassembly_n_instrs_as_text_json_cd); + + RzCmdDesc *cmd_disassembly_all_methods_class_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_print_disassembly_cd, "pdk", rz_cmd_disassembly_all_methods_class_handler, &cmd_disassembly_all_methods_class_help); + rz_warn_if_fail(cmd_disassembly_all_methods_class_cd); + + RzCmdDesc *cmd_sizes_of_n_instructions_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_print_disassembly_cd, "pdl", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_sizes_of_n_instructions_handler, &cmd_sizes_of_n_instructions_help); + rz_warn_if_fail(cmd_sizes_of_n_instructions_cd); + + RzCmdDesc *cmd_disassemble_ropchain_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_print_disassembly_cd, "pdp", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_QUIET | RZ_OUTPUT_MODE_JSON, rz_cmd_disassemble_ropchain_handler, &cmd_disassemble_ropchain_help); + rz_warn_if_fail(cmd_disassemble_ropchain_cd); + + RzCmdDesc *cmd_disassemble_recursive_cd = rz_cmd_desc_group_state_new(core->rcmd, cmd_print_disassembly_cd, "pdr", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_disassemble_recursively_handler, &cmd_disassemble_recursively_help, &cmd_disassemble_recursive_help); + rz_warn_if_fail(cmd_disassemble_recursive_cd); + RzCmdDesc *cmd_disassemble_recursively_from_current_block_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_disassemble_recursive_cd, "pdr.", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_disassemble_recursively_from_current_block_handler, &cmd_disassemble_recursively_from_current_block_help); + rz_warn_if_fail(cmd_disassemble_recursively_from_current_block_cd); + + RzCmdDesc *cmd_disassemble_recursively_no_function_cd = rz_cmd_desc_argv_state_new(core->rcmd, cmd_print_disassembly_cd, "pdR", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_QUIET | RZ_OUTPUT_MODE_JSON, rz_cmd_disassemble_recursively_no_function_handler, &cmd_disassemble_recursively_no_function_help); + rz_warn_if_fail(cmd_disassemble_recursively_no_function_cd); + + RzCmdDesc *cmd_disassemble_summarize_cd = rz_cmd_desc_group_new(core->rcmd, cmd_print_disassembly_cd, "pds", rz_cmd_disassemble_summarize_n_bytes_handler, &cmd_disassemble_summarize_n_bytes_help, &cmd_disassemble_summarize_help); + rz_warn_if_fail(cmd_disassemble_summarize_cd); + RzCmdDesc *cmd_disassemble_summarize_function_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_disassemble_summarize_cd, "pdsf", rz_cmd_disassemble_summarize_function_handler, &cmd_disassemble_summarize_function_help); + rz_warn_if_fail(cmd_disassemble_summarize_function_cd); + + RzCmdDesc *cmd_disassemble_summarize_block_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_disassemble_summarize_cd, "pdsb", rz_cmd_disassemble_summarize_block_handler, &cmd_disassemble_summarize_block_help); + rz_warn_if_fail(cmd_disassemble_summarize_block_cd); + RzCmdDesc *cmd_print_gadget_cd = rz_cmd_desc_group_new(core->rcmd, cmd_print_cd, "pg", rz_cmd_print_gadget_add_handler, &cmd_print_gadget_add_help, &cmd_print_gadget_help); rz_warn_if_fail(cmd_print_gadget_cd); RzCmdDesc *cmd_print_gadget_print_as_rizin_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_print_gadget_cd, "pg*", rz_cmd_print_gadget_print_as_rizin_handler, &cmd_print_gadget_print_as_rizin_help); diff --git a/librz/core/cmd_descs/cmd_descs.h b/librz/core/cmd_descs/cmd_descs.h index 0fcbb32545..5d17154102 100644 --- a/librz/core/cmd_descs/cmd_descs.h +++ b/librz/core/cmd_descs/cmd_descs.h @@ -708,6 +708,25 @@ RZ_IPI RzCmdStatus rz_cmd_print_byte_array_rust_handler(RzCore *core, int argc, RZ_IPI RzCmdStatus rz_cmd_print_byte_array_swift_handler(RzCore *core, int argc, const char **argv); RZ_IPI RzCmdStatus rz_cmd_print_byte_array_yara_handler(RzCore *core, int argc, const char **argv); RZ_IPI RzCmdStatus rz_cmd_print_byte_array_rizin_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_disassembly_n_instructions_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassembly_all_possible_opcodes_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassembly_all_possible_opcodes_treeview_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_disassembly_basic_block_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassembly_basic_block_as_text_json_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_comments_in_n_instructions_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_disassembly_n_instructions_with_flow_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassembly_function_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassembly_function_summary_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_disassembly_n_instrs_as_text_json_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassembly_all_methods_class_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_sizes_of_n_instructions_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassemble_ropchain_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassemble_recursively_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassemble_recursively_from_current_block_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassemble_recursively_no_function_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state); +RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_n_bytes_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_function_handler(RzCore *core, int argc, const char **argv); +RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_block_handler(RzCore *core, int argc, const char **argv); RZ_IPI RzCmdStatus rz_cmd_print_gadget_add_handler(RzCore *core, int argc, const char **argv); RZ_IPI RzCmdStatus rz_cmd_print_gadget_print_as_rizin_handler(RzCore *core, int argc, const char **argv); RZ_IPI RzCmdStatus rz_cmd_print_gadget_remove_handler(RzCore *core, int argc, const char **argv); diff --git a/librz/core/cmd_descs/cmd_print.yaml b/librz/core/cmd_descs/cmd_print.yaml index b2a33f2c9c..5c3544c4ab 100644 --- a/librz/core/cmd_descs/cmd_print.yaml +++ b/librz/core/cmd_descs/cmd_print.yaml @@ -90,6 +90,188 @@ commands: summary: Generate a rizin commands for writing the byte array. cname: cmd_print_byte_array_rizin args: [] + - name: pd + summary: Print Disassembly + cname: cmd_print_disassembly + subcommands: + - name: pd + summary: Disassemble N instructions (can be negative) + cname: cmd_disassembly_n_instructions + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_QUIET # replaces pdi + - RZ_OUTPUT_MODE_TABLE + - RZ_OUTPUT_MODE_JSON + args: + - name: n_instrs + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pda + summary: Disassemble all possible opcodes (byte per byte) + cname: cmd_disassembly_all_opcodes + subcommands: + - name: pda + summary: Disassemble all possible opcodes (byte per byte) + cname: cmd_disassembly_all_possible_opcodes + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_QUIET + - RZ_OUTPUT_MODE_JSON + args: + - name: n_bytes + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pda= + summary: Disassemble all possible opcodes (treeview) + cname: cmd_disassembly_all_possible_opcodes_treeview + args: + - name: n_bytes + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pdb + summary: Disassemble basic block + cname: cmd_disasm_basic_block + subcommands: + - name: pdb + summary: Disassemble basic block + cname: cmd_disassembly_basic_block + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + args: [] + - name: pdbJ + summary: Disassemble basic block as json containing the printed text + cname: cmd_disassembly_basic_block_as_text_json + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + args: [] + - name: pdC + summary: Prints the comments found in N instructions + cname: cmd_comments_in_n_instructions + args: + - name: n_instrs + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pde + summary: Disassemble N instructions following execution flow from current PC + cname: cmd_disassembly_n_instructions_with_flow + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + - RZ_OUTPUT_MODE_QUIET + - RZ_OUTPUT_MODE_QUIETEST + args: + - name: n_instrs + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pdf + summary: Disassemble a function + cname: cmd_disasm_func + subcommands: + - name: pdf + summary: Disassemble a function + cname: cmd_disassembly_function + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + args: [] + - name: pdfs + summary: Disassemble a function and outputs the summary of it. + cname: cmd_disassembly_function_summary + args: [] + - name: pdJ + summary: Disassemble N instructions as json containing the printed text + cname: cmd_disassembly_n_instrs_as_text_json + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + args: + - name: n_instrs + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pdk + summary: Disassemble all methods of a class + cname: cmd_disassembly_all_methods_class + args: [] + - name: pdl + summary: Disassemble N instructions and prints its sizes + cname: cmd_sizes_of_n_instructions + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + args: + - name: n_instrs + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pdp + summary: Disassemble instructions and follows pointers to read ropchains + cname: cmd_disassemble_ropchain + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_QUIET + - RZ_OUTPUT_MODE_JSON + args: + - name: limit + type: RZ_CMD_ARG_TYPE_NUM + optional: true + - name: pdr + summary: Disassemble recursively across the function graph + cname: cmd_disassemble_recursive + subcommands: + - name: pdr + summary: Disassemble recursively across the function graph + cname: cmd_disassemble_recursively + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + args: [] + - name: pdr. + summary: Disassemble recursively across the function graph (from current basic block) + cname: cmd_disassemble_recursively_from_current_block + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + args: [] + - name: pdR + summary: Disassemble recursively the block size bytes without analyzing functions + cname: cmd_disassemble_recursively_no_function + type: RZ_CMD_DESC_TYPE_ARGV_STATE + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_QUIET + - RZ_OUTPUT_MODE_JSON + args: [] + - name: pds + summary: Summarize N bytes or current block or a function (strings, calls, jumps, refs) + cname: cmd_disassemble_summarize + subcommands: + - name: pds + summary: Summarize N bytes + cname: cmd_disassemble_summarize_n_bytes + args: + - name: n_bytes + type: RZ_CMD_ARG_TYPE_RZNUM + optional: true + - name: pdsf + summary: Summarize the current function + cname: cmd_disassemble_summarize_function + args: [] + - name: pdsb + summary: Summarize current block + cname: cmd_disassemble_summarize_block + args: + - name: n_bytes + type: RZ_CMD_ARG_TYPE_RZNUM - name: pg summary: Print gadgets cname: cmd_print_gadget diff --git a/librz/core/cmp.c b/librz/core/cmp.c index 0a3dc6a263..5482d81ee1 100644 --- a/librz/core/cmp.c +++ b/librz/core/cmp.c @@ -337,11 +337,13 @@ RZ_API RzCoreCmpWatcher *rz_core_cmpwatch_get(RzCore *core, ut64 addr) { RZ_API bool rz_core_cmpwatch_add(RzCore *core, ut64 addr, int size, const char *cmd) { rz_return_val_if_fail(core, false); RzCoreCmpWatcher *cmpw; + bool to_add = false; if (size < 1) { return false; } cmpw = rz_core_cmpwatch_get(core, addr); if (!cmpw) { + to_add = true; cmpw = RZ_NEW(RzCoreCmpWatcher); if (!cmpw) { return false; @@ -357,7 +359,9 @@ RZ_API bool rz_core_cmpwatch_add(RzCore *core, ut64 addr, int size, const char * return false; } rz_io_nread_at(core->io, addr, cmpw->ndata, size); - rz_list_append(core->watchers, cmpw); + if (to_add) { + rz_list_append(core->watchers, cmpw); + } return true; } @@ -402,8 +406,8 @@ RZ_API void rz_core_cmpwatch_show(RzCore *core, ut64 addr, RzOutputMode mode) { int is_diff = w->odata ? memcmp(w->odata, w->ndata, w->size) : 0; switch (mode) { case RZ_OUTPUT_MODE_RIZIN: - rz_cons_printf("cw 0x%08" PFMT64x " %d %s%s\n", - w->addr, w->size, w->cmd, is_diff ? " # differs" : ""); + rz_cons_printf("cw %d '%s' @ 0x%08" PFMT64x "%s\n", + w->size, w->cmd, w->addr, is_diff ? " # differs" : ""); break; case RZ_OUTPUT_MODE_STANDARD: rz_cons_printf("0x%08" PFMT64x "%s\n", w->addr, is_diff ? " modified" : ""); diff --git a/librz/core/disasm.c b/librz/core/disasm.c index ece9eed14d..8b23730747 100644 --- a/librz/core/disasm.c +++ b/librz/core/disasm.c @@ -6258,8 +6258,6 @@ RZ_API int rz_core_print_disasm_json(RzCore *core, ut64 addr, ut8 *buf, int nb_b rz_analysis_op_fini(&ds->analysis_op); ds_free(ds); if (!result) { - pj_o(pj); - pj_end(pj); result = true; } return result; diff --git a/test/db/cmd/cmd_0 b/test/db/cmd/cmd_0 index ebc2d0062d..5ea59140a9 100644 --- a/test/db/cmd/cmd_0 +++ b/test/db/cmd/cmd_0 @@ -219,6 +219,7 @@ NAME=pdj 0 FILE=bins/elf/analysis/hello-arm32 CMDS=pdj 0 EXPECT=< /dev/null; ?= -FILE== -CMDS=< /dev/null -?= -EOF -EXPECT=<