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
This commit is contained in:
Giovanni 2022-04-21 16:19:48 +02:00 committed by GitHub
parent 8df5d48b95
commit de8a5cac55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1361 additions and 94 deletions

View file

@ -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;
}

View file

@ -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 <hexpair> (also return in $?)
cname: cmd_cmp_hexpair_string

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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" : "");

View file

@ -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;

View file

@ -219,6 +219,7 @@ NAME=pdj 0
FILE=bins/elf/analysis/hello-arm32
CMDS=pdj 0
EXPECT=<<EOF
[]
EOF
RUN
@ -267,6 +268,8 @@ NAME=pdt 0
FILE=bins/elf/analysis/hello-arm32
CMDS=pdt 0
EXPECT=<<EOF
name addr bytes disasm comment esil refs xrefs
-----------------------------------------------
EOF
RUN

View file

@ -1132,7 +1132,7 @@ FILE=bins/elf/ls
CMDS=<<EOF
cwl
?e --------
cw 8 pd @ 0x5ae0
cw 8 'pd 2' @ 0x5ae0
cwl
?e --------
cwx @ 0x5ae0
@ -1148,6 +1148,20 @@ EXPECT=<<EOF
EOF
RUN
NAME=add memory watcher at the same address multiple times and do not crash
FILE=bins/elf/ls
CMDS=<<EOF
cw 8 'pd 2' @ 0x5ae0
cw 8 'pd 2' @ 0x5ae0
cw 8 'pd 2' @ 0x5ae0
cw 8 'pd 2' @ 0x5ae0
cwl*
EOF
EXPECT=<<EOF
cw 8 'pd 2' @ 0x00005ae0
EOF
RUN
NAME=cmd_cx
FILE=bins/elf/ls
CMDS=<<EOF

View file

@ -55,7 +55,7 @@ EXPECT=<<EOF
EOF
RUN
NAME=pd 4;?=
NAME=pd 4
FILE==
CMDS=<<EOF
wx 00000000000000000000
@ -63,28 +63,12 @@ e asm.arch=x86
e asm.bytes=true
e asm.bits=32
pd 4
?=
EOF
EXPECT=<<EOF
0x00000000 0000 add byte [eax], al
0x00000002 0000 add byte [eax], al
0x00000004 0000 add byte [eax], al
0x00000006 0000 add byte [eax], al
0x8
EOF
RUN
NAME=pd 4 > /dev/null; ?=
FILE==
CMDS=<<EOF
wx 00000000000000000000
e asm.arch=x86
e asm.bits=32
pd 4 > /dev/null
?=
EOF
EXPECT=<<EOF
0x8
EOF
RUN

View file

@ -658,6 +658,29 @@ EXPECT=<<EOF
0x100001114 call sym.imp.getenv
0x100001121 call sym.imp.atoi
0x10000112c call sym.imp.getuid
0x10000116e call newname
0x100001179 str.1_ABCFGHLOPRSTUWabcdefghiklmnopqrstuvwx
0x100001186 call sym.imp.getopt
0x100001233 str.CLICOLOR
0x100001246 call sym.imp.setenv
0x100001253 str.bin_ls
0x10000125a str.Unix2003
0x100001261 call sym.imp.compat_mode
0x10000128c str.bin_ls
0x100001293 str.Unix2003
0x10000129a call sym.imp.compat_mode
0x1000013a2 str.bin_ls
0x1000013a9 str.Unix2003
0x1000013b0 call sym.imp.compat_mode
0x1000013d3 str.bin_ls
0x1000013da str.Unix2003
0x1000013e1 call sym.imp.compat_mode
0x10000143a str.bin_ls
0x100001441 str.Unix2003
0x100001448 call sym.imp.compat_mode
0x10000145a str.bin_ls
0x100001461 str.Unix2003
0x100001468 call sym.imp.compat_mode
EOF
RUN
@ -2507,3 +2530,18 @@ xor ebp, ebp
xor ebp, ebp
EOF
RUN
NAME=pd is not limited by blocksize
FILE==
CMDS=<<EOF
b 10
pd~?
pd 3~?
pd 20~?
EOF
EXPECT=<<EOF
10
3
20
EOF
RUN

View file

@ -1,47 +0,0 @@
NAME=pdx medium size instructions
FILE==
ARGS=-a x86 -b 32
CMDS=pdx 9090909090
EXPECT=<<EOF
nop
nop
nop
nop
nop
EOF
RUN
NAME=pdx smaller instruction
FILE==
ARGS=-a x86 -b 32
CMDS=pdx 52ee
EXPECT=<<EOF
push edx
out dx, al
EOF
RUN
NAME=pdx large instruction
FILE==
ARGS=-a x86 -b 32
CMDS=pdx 31c09952682f636174682f62696e89e3526873737764682f2f7061682f65746389e1b00b52515389e1cd80
EXPECT=<<EOF
xor eax, eax
cdq
push edx
push 0x7461632f
push 0x6e69622f
mov ebx, esp
push edx
push 0x64777373
push 0x61702f2f
push 0x6374652f
mov ecx, esp
mov al, 0xb
push edx
push ecx
push ebx
mov ecx, esp
int 0x80
EOF
RUN

View file

@ -1,14 +0,0 @@
NAME=t/retries
FILE==
CMDS=<<EOF
b 10
pd~?
pd 3~?
pd 20~?
EOF
EXPECT=<<EOF
2
3
20
EOF
RUN