From 45733eb653fe93cc821caec7df85399a245f042c Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Thu, 13 Apr 2023 22:37:39 +0800 Subject: [PATCH] Convert `pf` commands to rzshell --- librz/core/cmd/cmd_print.c | 354 ++++++++++------------------ librz/core/cmd_descs/cmd_descs.c | 257 ++++++++++++++++++++ librz/core/cmd_descs/cmd_descs.h | 20 ++ librz/core/cmd_descs/cmd_print.yaml | 195 +++++++++++++++ 4 files changed, 594 insertions(+), 232 deletions(-) diff --git a/librz/core/cmd/cmd_print.c b/librz/core/cmd/cmd_print.c index f488c15b800..be36bd4d0d6 100644 --- a/librz/core/cmd/cmd_print.c +++ b/librz/core/cmd/cmd_print.c @@ -180,76 +180,6 @@ static const char *help_msg_pf[] = { NULL }; -static const char *help_detail_pf[] = { - "pf:", PF_USAGE_STR, "", - "Format:", "", "", - " ", "b", "byte (unsigned)", - " ", "B", "resolve enum bitfield (see t?)", - " ", "c", "char (signed byte)", - " ", "C", "byte in decimal", - " ", "d", "0xHEX value (4 bytes) (see 'i' and 'x')", - " ", "D", "disassemble one opcode", - " ", "e", "temporally swap endian", - " ", "E", "resolve enum name (see t?)", - " ", "f", "float value (4 bytes)", - " ", "F", "double value (8 bytes)", - " ", "i", "signed integer value (4 bytes) (see 'd' and 'x')", - " ", "n", "next char specifies size of signed value (1, 2, 4 or 8 byte(s))", - " ", "N", "next char specifies size of unsigned value (1, 2, 4 or 8 byte(s))", - " ", "o", "octal value (4 byte)", - " ", "p", "pointer reference (2, 4 or 8 bytes)", - " ", "q", "quadword (8 bytes)", - " ", "Q", "uint128_t (16 bytes)", - " ", "r", "CPU register `pf r (eax)plop`", - " ", "s", "32bit pointer to string (4 bytes)", - " ", "S", "64bit pointer to string (8 bytes)", - " ", "t", "UNIX timestamp (4 bytes)", - " ", "T", "show Ten first bytes of buffer", - " ", "u", "uleb128 (variable length)", - " ", "w", "word (2 bytes unsigned short in hex)", - " ", "x", "0xHEX value and flag (fd @ addr) (see 'd' and 'i')", - " ", "X", "show formatted hexpairs", - " ", "z", "null terminated string", - " ", "Z", "null terminated wide string", - " ", "?", "data structure `pf ? (struct_name)example_name`", - " ", "*", "next char is pointer (honors asm.bits)", - " ", "+", "toggle show flags for each offset", - " ", ":", "skip 4 bytes", - " ", ".", "skip 1 byte", - " ", ";", "rewind 4 bytes", - " ", ",", "rewind 1 byte", - NULL -}; - -static const char *help_detail2_pf[] = { - "pf:", PF_USAGE_STR, "", - "Examples:", "", "", - "pf", " 3xi foo bar", "3-array of struct, each with named fields: 'foo' as hex, and 'bar' as int", - "pf", " B (BitFldType)arg_name`", "bitfield type", - "pf", " E (EnumType)arg_name`", "enum type", - "pf", " obj=xxdz prev next size name", "Same as above", - "pf", " *z*i*w nb name blob", "Print the pointers with given labels", - "pf", " iwq foo bar troll", "Print the iwq format with foo, bar, troll as the respective names for the fields", - "pf", " 0iwq foo bar troll", "Same as above, but considered as a union (all fields at offset 0)", - "pf.", "obj xxdz prev next size name", "Define the obj format as xxdz", - "pf.", "plop ? (troll)mystruct", "Use structure troll previously defined", - "pfj.", "plop @ 0x14", "Apply format object at the given offset", - "pf", " 10xiz pointer length string", "Print a size 10 array of the xiz struct with its field names", - "pf", " 5sqw string quad word", "Print an array with sqw struct along with its field names", - "pf", " {integer}? (bifc)", "Print integer times the following format (bifc)", - "pf", " [4]w[7]i", "Print an array of 4 words and then an array of 7 integers", - "pf", " ic...?i foo bar \"(pf xw yo foo)troll\" yo", "Print nested anonymous structures", - "pf", " ;..x", "Print value located 6 bytes from current offset", - "pf", " [10]z[3]i[10]Zb", "Print an fixed size str, widechar, and var", - "pfj", " +F @ 0x14", "Print the content at given offset with flag", - "pf", " n2", "print signed short (2 bytes) value. Use N instead of n for printing unsigned values", - "pf", " [2]? (plop)structname @ 0", "Prints an array of structs", - "pf", " eqew bigWord beef", "Swap endianness and print with given labels", - "pf", ".foo rr (eax)reg1 (eip)reg2", "Create object referencing to register values ", - "pf", " tt troll plop", "print time stamps with labels troll and plop", - NULL -}; - static const char *help_msg_px[] = { "Usage:", "px[0afoswqWqQ][f]", " # Print heXadecimal", "px", "", "show hexdump", @@ -988,127 +918,7 @@ static void cmd_print_format(RzCore *core, const char *_input, const ut8 *block, _input++; mode = RZ_PRINT_STRUCT; break; - case 's': { // "pfs" - const char *val = NULL; - _input += 2; - if (*_input == '.') { - _input++; - val = rz_type_db_format_get(core->analysis->typedb, _input); - if (val) { - rz_cons_printf("%d\n", rz_type_format_struct_size(core->analysis->typedb, val, mode, 0)); - } else { - RZ_LOG_ERROR("core: Struct %s not defined\nUsage: pfs.struct_name | pfs format\n", _input); - } - } else if (*_input == ' ') { - while (*_input == ' ' && *_input != '\0') { - _input++; - } - if (*_input) { - rz_cons_printf("%d\n", rz_type_format_struct_size(core->analysis->typedb, _input, mode, 0)); - } else { - RZ_LOG_ERROR("core: Struct %s not defined\nUsage: pfs.struct_name | pfs format\n", _input); - } - } else { - RZ_LOG_ERROR("core: Usage: pfs.struct_name | pfs format\n"); - } - return; - } - case '?': // "pf?" - _input += 2; - if (*_input) { - if (*_input == '?') { - _input++; - if (_input && *_input == '?') { - _input++; - if (_input && *_input == '?') { - print_format_help_help_help_help(core); - } else { - rz_core_cmd_help(core, help_detail2_pf); - } - } else { - rz_core_cmd_help(core, help_detail_pf); - } - } else { - const char *struct_name = rz_str_trim_head_ro(_input); - const char *val = rz_type_db_format_get(core->analysis->typedb, struct_name); - if (val) { - rz_cons_printf("%s\n", val); - } else { - RZ_LOG_ERROR("core: Struct %s is not defined\n", _input); - } - } - } else { - rz_core_cmd_help(core, help_msg_pf); - } - return; - case 'o': // "pfo" - if (_input[2] == '?') { - char *prefix = rz_path_prefix(NULL); - char *sdb_format = rz_path_home_prefix(RZ_SDB_FORMAT); - eprintf("|Usage: pfo [format-file]\n" - " %s\n" - " " RZ_JOIN_3_PATHS("%s", RZ_SDB_FORMAT, "") "\n", - sdb_format, prefix); - free(sdb_format); - free(prefix); - } else if (_input[2] == ' ') { - const char *fname = rz_str_trim_head_ro(_input + 3); - char *home_formats = rz_path_home_prefix(RZ_SDB_FORMAT); - char *home = rz_file_path_join(home_formats, fname); - free(home_formats); - char *system_formats = rz_path_system(RZ_SDB_FORMAT); - char *path = rz_file_path_join(system_formats, fname); - free(system_formats); - if (rz_str_endswith(_input, ".h")) { - char *error_msg = NULL; - const char *dir = rz_config_get(core->config, "dir.types"); - int result = rz_type_parse_file(core->analysis->typedb, path, dir, &error_msg); - if (!result) { - rz_core_cmd0(core, ".ts*"); - } else { - RZ_LOG_ERROR("core: Parse error: %s\n", error_msg); - free(error_msg); - } - } else { - if (!rz_core_cmd_file(core, home) && !rz_core_cmd_file(core, path)) { - if (!rz_core_cmd_file(core, _input + 3)) { - RZ_LOG_ERROR("core: pfo: cannot open format file at '%s'\n", path); - } - } - } - free(home); - free(path); - } else { - RzList *files; - RzListIter *iter; - const char *fn; - char *home = rz_path_home_prefix(RZ_SDB_FORMAT); - if (home) { - files = rz_sys_dir(home); - rz_list_foreach (files, iter, fn) { - if (*fn && *fn != '.') { - rz_cons_println(fn); - } - } - rz_list_free(files); - free(home); - } - char *path = rz_path_system(RZ_SDB_FORMAT); - if (path) { - files = rz_sys_dir(path); - rz_list_foreach (files, iter, fn) { - if (*fn && *fn != '.') { - rz_cons_println(fn); - } - } - rz_list_free(files); - free(path); - } - } - free(input); - return; } // switch - input = strdup(_input); /* syntax aliasing bridge for 'pf foo=xxd' -> 'pf.foo xxd' */ if (input[1] == ' ') { @@ -1143,13 +953,6 @@ static void cmd_print_format(RzCore *core, const char *_input, const ut8 *block, rz_cons_printf("pf.%s\n", fmt); } rz_list_free(fmtl); - /* delete a format */ - } else if (input[1] && input[2] == '-') { // "pf-" - if (input[3] == '*') { // "pf-*" - rz_type_db_format_purge(core->analysis->typedb); - } else { // "pf-xxx" - rz_type_db_format_delete(core->analysis->typedb, input + 3); - } } else { char *name = strdup(input + (input[1] ? 2 : 1)); char *space = strchr(name, ' '); @@ -1233,41 +1036,6 @@ static void cmd_print_format(RzCore *core, const char *_input, const ut8 *block, } free(name); } - } else { - /* This make sure the structure will be printed entirely */ - const char *fmt = rz_str_trim_head_ro(input + 1); - int struct_sz = rz_type_format_struct_size(core->analysis->typedb, fmt, mode, 0); - size_t size = RZ_MAX(core->blocksize, struct_sz); - ut8 *buf = calloc(1, size); - if (!buf) { - RZ_LOG_ERROR("core: cannot allocate %zu byte(s)\n", size); - goto stage_left; - } - memcpy(buf, core->block, core->blocksize); - /* check if fmt is '\d+ \d+<...>', common mistake due to usage string*/ - bool syntax_ok = true; - char *args = strdup(fmt); - if (!args) { - RZ_LOG_ERROR("core: Mem Allocation."); - free(args); - free(buf); - goto stage_left; - } - const char *arg1 = strtok(args, " "); - if (arg1 && rz_str_isnumber(arg1)) { - syntax_ok = false; - RZ_LOG_ERROR("core: Usage: pf [0|cnt][format-string]\n"); - } - free(args); - if (syntax_ok) { - char *format = rz_type_format_data(core->analysis->typedb, core->print, core->offset, - buf, size, fmt, mode, NULL, NULL); - if (format) { - rz_cons_print(format); - free(format); - } - } - free(buf); } stage_left: free(input); @@ -6351,6 +6119,33 @@ RZ_IPI RzCmdStatus rz_cmd_print_raw_printable_handler(RzCore *core, int argc, co return RZ_CMD_STATUS_OK; } +static RzCmdStatus print_format(RzCore *core, const char *fmt, int mode) { + core->print->reg = rz_core_reg_default(core); + core->print->get_register = rz_reg_get; + core->print->get_register_value = rz_reg_get_value; + + int o_blocksize = core->blocksize; + int struct_sz = rz_type_format_struct_size(core->analysis->typedb, fmt, mode, 0); + size_t size = RZ_MAX(core->blocksize, struct_sz); + ut8 *buf = calloc(1, size); + if (!buf) { + RZ_LOG_ERROR("core: cannot allocate %zu byte(s)\n", size); + goto stage_left; + } + memcpy(buf, core->block, core->blocksize); + char *format = rz_type_format_data(core->analysis->typedb, core->print, core->offset, + buf, size, fmt, mode, NULL, NULL); + if (format) { + rz_cons_print(format); + free(format); + } + free(buf); + +stage_left: + free(input); + rz_core_block_size(core, o_blocksize); +} + RZ_IPI RzCmdStatus rz_cmd_print_raw_string_handler(RzCore *core, int argc, const char **argv) { int len = argc > 1 ? rz_num_math(core->num, argv[1]) : strlen((const char *)core->block); if (len < 0) { @@ -6359,3 +6154,98 @@ RZ_IPI RzCmdStatus rz_cmd_print_raw_string_handler(RzCore *core, int argc, const printraw(core, len); return RZ_CMD_STATUS_OK; } + +RZ_IPI RzCmdStatus rz_cmd_print_format_handler(RzCore *core, int argc, const char **argv) { + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_delete_handler(RzCore *core, int argc, const char **argv) { + rz_type_db_format_delete(core->analysis->typedb, argv[1]); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_delete_all_handler(RzCore *core, int argc, const char **argv) { + rz_type_db_format_purge(core->analysis->typedb); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_named_handler(RzCore *core, int argc, const char **argv) { + int mode = RZ_PRINT_VALUE | RZ_PRINT_MUSTSEE; + return print_format(core, argv[1], mode); +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_file_handler(RzCore *core, int argc, const char **argv) { + if (argc < 2) { + RzList *files; + RzListIter *iter; + const char *fn; + char *home = rz_path_home_prefix(RZ_SDB_FORMAT); + if (home) { + files = rz_sys_dir(home); + rz_list_foreach (files, iter, fn) { + if (*fn && *fn != '.') { + rz_cons_println(fn); + } + } + rz_list_free(files); + free(home); + } + char *path = rz_path_system(RZ_SDB_FORMAT); + if (path) { + files = rz_sys_dir(path); + rz_list_foreach (files, iter, fn) { + if (*fn && *fn != '.') { + rz_cons_println(fn); + } + } + rz_list_free(files); + free(path); + } + return RZ_CMD_STATUS_OK; + } + char *home_formats = rz_path_home_prefix(RZ_SDB_FORMAT); + char *home = rz_file_path_join(home_formats, argv[1]); + free(home_formats); + char *system_formats = rz_path_system(RZ_SDB_FORMAT); + char *path = rz_file_path_join(system_formats, argv[1]); + free(system_formats); + if (rz_str_endswith(argv[1], ".h")) { + char *error_msg = NULL; + const char *dir = rz_config_get(core->config, "dir.types"); + int result = rz_type_parse_file(core->analysis->typedb, path, dir, &error_msg); + if (!result) { + rz_core_cmd0(core, ".ts*"); + } else { + RZ_LOG_ERROR("core: Parse error: %s\n", error_msg); + free(error_msg); + } + } else { + if (!rz_core_cmd_file(core, home) && !rz_core_cmd_file(core, path)) { + if (!rz_core_cmd_file(core, _input + 3)) { + RZ_LOG_ERROR("core: pfo: cannot open format file at '%s'\n", path); + } + } + } + free(home); + free(path); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_size_handler(RzCore *core, int argc, const char **argv) { + const char *val = rz_type_db_format_get(core->analysis->typedb, argv[1]); + if (!val) { + RZ_LOG_ERROR("Format \"%s\" could not be found\n", argv[1]); + return RZ_CMD_STATUS_ERROR; + } + int fmtsz = rz_type_format_struct_size(core->analysis->typedb, val, mode, 0); + rz_cons_printf("%d\n", fmtsz); + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_value_handler(RzCore *core, int argc, const char **argv) { + return RZ_CMD_STATUS_OK; +} + +RZ_IPI RzCmdStatus rz_cmd_print_format_write_handler(RzCore *core, int argc, const char **argv) { + return RZ_CMD_STATUS_OK; +} diff --git a/librz/core/cmd_descs/cmd_descs.c b/librz/core/cmd_descs/cmd_descs.c index b9dfcabda1c..ef849afd5e3 100644 --- a/librz/core/cmd_descs/cmd_descs.c +++ b/librz/core/cmd_descs/cmd_descs.c @@ -61,6 +61,7 @@ static const RzCmdDescDetail eval_getset_details[2]; static const RzCmdDescDetail egg_config_details[2]; static const RzCmdDescDetail history_list_or_exec_details[2]; static const RzCmdDescDetail cmd_print_byte_array_details[3]; +static const RzCmdDescDetail pf_details[3]; static const RzCmdDescDetail write_bits_details[2]; static const RzCmdDescDetail wv_details[2]; static const RzCmdDescDetail w1_details[2]; @@ -577,6 +578,15 @@ 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_print_format_args[2]; +static const RzCmdDescArg cmd_print_format_delete_args[2]; +static const RzCmdDescArg cmd_print_format_c_args[2]; +static const RzCmdDescArg cmd_print_format_dot_args[2]; +static const RzCmdDescArg cmd_print_format_named_args[3]; +static const RzCmdDescArg cmd_print_format_file_args[2]; +static const RzCmdDescArg cmd_print_format_size_args[2]; +static const RzCmdDescArg cmd_print_format_value_args[2]; +static const RzCmdDescArg cmd_print_format_write_args[3]; static const RzCmdDescArg cmd_print_gadget_add_args[6]; static const RzCmdDescArg cmd_print_gadget_move_args[6]; static const RzCmdDescArg cmd_print_hash_cfg_args[2]; @@ -12989,6 +12999,224 @@ static const RzCmdDescHelp cmd_disassemble_summarize_block_help = { .args = cmd_disassemble_summarize_block_args, }; +static const RzCmdDescDetailEntry pf_Formats_detail_entries[] = { + { .text = "b", .arg_str = NULL, .comment = "byte (unsigned)" }, + { .text = "B", .arg_str = NULL, .comment = "resolve enum bitfield (see t?)" }, + { .text = "c", .arg_str = NULL, .comment = "char (signed byte)" }, + { .text = "C", .arg_str = NULL, .comment = "byte in decimal" }, + { .text = "d", .arg_str = NULL, .comment = "0xHEX value (4 bytes) (see 'i' and 'x' formats)" }, + { .text = "D", .arg_str = NULL, .comment = "disassemble one opcode" }, + { .text = "e", .arg_str = NULL, .comment = "temporarily swap endian" }, + { .text = "E", .arg_str = NULL, .comment = "resolve enum name (see t?)" }, + { .text = "f", .arg_str = NULL, .comment = "float value (4 bytes)" }, + { .text = "F", .arg_str = NULL, .comment = "double float value (8 bytes)" }, + { .text = "i", .arg_str = NULL, .comment = "signed integer value (4 bytes) (see 'd' and 'x' formats)" }, + { .text = "n", .arg_str = NULL, .comment = "next char specifies size of signed value (1, 2, 4, or 8 byte(s))" }, + { .text = "N", .arg_str = NULL, .comment = "next char specifies size of unsigned value (1, 2, 4, or 8 byte(s))" }, + { .text = "o", .arg_str = NULL, .comment = "octal value (4 bytes)" }, + { .text = "p", .arg_str = NULL, .comment = "pointer reference (2, 4, or 8 bytes)" }, + { .text = "q", .arg_str = NULL, .comment = "quadword (8 bytes)" }, + { .text = "Q", .arg_str = NULL, .comment = "octoword (uint128_t) (16 bytes)" }, + { .text = "r", .arg_str = NULL, .comment = "CPU register (`pf r (eax)plop`)" }, + { .text = "s", .arg_str = NULL, .comment = "32 bit pointer to string (4 bytes)" }, + { .text = "s", .arg_str = NULL, .comment = "32 bit pointer to string (4 bytes)" }, + { .text = "t", .arg_str = NULL, .comment = "32 bit UNIX timestamp (4 bytes)" }, + { .text = "T", .arg_str = NULL, .comment = "show ten first bytes of buffer" }, + { .text = "u", .arg_str = NULL, .comment = "uleb128 (variable length)" }, + { .text = "w", .arg_str = NULL, .comment = "word (2 bytes unsigned short in hex)" }, + { .text = "x", .arg_str = NULL, .comment = "0xHEX value and flag (fd @ addr) (see 'd' and 'i' formats)" }, + { .text = "X", .arg_str = NULL, .comment = "show formatted hexpairs" }, + { .text = "z", .arg_str = NULL, .comment = "null terminated string" }, + { .text = "Z", .arg_str = NULL, .comment = "null terminated wide string" }, + { .text = "?", .arg_str = NULL, .comment = "data structure `pf ? (struct_name)example_name`" }, + { .text = "*", .arg_str = NULL, .comment = "next char is pointer (honors 'asm.bits')" }, + { .text = "+", .arg_str = NULL, .comment = "toggle show flags for each offset" }, + { .text = ":", .arg_str = NULL, .comment = "skip 4 bytes" }, + { .text = ".", .arg_str = NULL, .comment = "skip 1 byte" }, + { .text = ";", .arg_str = NULL, .comment = "rewind 4 bytes" }, + { .text = ",", .arg_str = NULL, .comment = "rewind 1 byte" }, + { 0 }, +}; + +static const RzCmdDescDetailEntry pf_Example_space_of_space_usages_detail_entries[] = { + { .text = "pf '3xi foo bar'", .arg_str = NULL, .comment = "3-array of structures, each with named fields: 'foo' as hex, 'bar' as int" }, + { .text = "pf 'B (BitFldType)arg_name'", .arg_str = NULL, .comment = "Resolve bitfield enum type for the arg_name" }, + { .text = "pf 'E (EnumType)arg_name'", .arg_str = NULL, .comment = "Resolve enum type for the arg_name" }, + { .text = "pf '*z*i*w nb name blob'", .arg_str = NULL, .comment = "Print pointers with the given labels" }, + { .text = "pf 'iwq foo bar troll'", .arg_str = NULL, .comment = "Print the iwq format with foo, bar, troll as respective fields" }, + { .text = "pf '0iwq foo bar troll'", .arg_str = NULL, .comment = "Same as above but considered as a union (all fields at offset 0)" }, + { .text = "pf 'obj xxdz prev next size name'", .arg_str = NULL, .comment = "Define the obj format as xxdz" }, + { .text = "pf. 'plop ? (troll)mystruct'", .arg_str = NULL, .comment = "Use previously defined structure 'troll'" }, + { .text = "pfj. plop @ 0x14", .arg_str = NULL, .comment = "Apply format object at the given offset" }, + { .text = "pf {N} (bifc)", .arg_str = NULL, .comment = "Print N times the following format (bifc)" }, + { .text = "pf [4]w[7]i", .arg_str = NULL, .comment = "Print an array of 4 words and then an array of 7 integers" }, + { .text = "pf ic...?i foo bar \"(pf xw yo foo)troll\" yo", .arg_str = NULL, .comment = "Print nested anonymous structures" }, + { .text = "pf ;..x", .arg_str = NULL, .comment = "Print value located 6 bytes from the current offset" }, + { .text = "pf [10]z[3]i[10]Zb", .arg_str = NULL, .comment = "Print a fixed size string, widechar, and var" }, + { .text = "pfj +F @ 0x14", .arg_str = NULL, .comment = "Print the content at given offset with a flag" }, + { .text = "pf n2", .arg_str = NULL, .comment = "Print signed short (2 bytes) value. Use N instead of n for printing unsigned values" }, + { .text = "pf [2]? (plop)structname @ 0x10", .arg_str = NULL, .comment = "Print an array of structures at the given offset" }, + { .text = "pf eqew bigWord beef", .arg_str = NULL, .comment = "Swap endianness and print with given labels" }, + { .text = "pf .foo rr (eax)reg1 (eip)reg2", .arg_str = NULL, .comment = "Create obect referencing to register values" }, + { .text = "pf tt troll plop", .arg_str = NULL, .comment = "Print time stamps with labels 'troll' and 'plop'" }, + { 0 }, +}; +static const RzCmdDescDetail pf_details[] = { + { .name = "Formats", .entries = pf_Formats_detail_entries }, + { .name = "Example of usages", .entries = pf_Example_space_of_space_usages_detail_entries }, + { 0 }, +}; +static const RzCmdDescHelp pf_help = { + .summary = "Print formatted data", + .details = pf_details, +}; +static const RzCmdDescArg cmd_print_format_args[] = { + { + .name = "format", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_help = { + .summary = "Show data using given format string", + .args = cmd_print_format_args, +}; + +static const RzCmdDescArg cmd_print_format_delete_args[] = { + { + .name = "formatname", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_delete_help = { + .summary = "Remove named format", + .args = cmd_print_format_delete_args, +}; + +static const RzCmdDescArg cmd_print_format_delete_all_args[] = { + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_delete_all_help = { + .summary = "Remove all named formats", + .args = cmd_print_format_delete_all_args, +}; + +static const RzCmdDescArg cmd_print_format_c_args[] = { + { + .name = "format", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_c_help = { + .summary = "Show data using given format string with C syntax", + .args = cmd_print_format_c_args, +}; + +static const RzCmdDescArg cmd_print_format_dot_args[] = { + { + .name = "format", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_dot_help = { + .summary = "Show data using given format string as DOT", + .args = cmd_print_format_dot_args, +}; + +static const RzCmdDescArg cmd_print_format_named_args[] = { + { + .name = "formatname", + .type = RZ_CMD_ARG_TYPE_STRING, + .optional = true, + + }, + { + .name = "formatstring", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_named_help = { + .summary = "Show data using given named format", + .args = cmd_print_format_named_args, +}; + +static const RzCmdDescArg cmd_print_format_file_args[] = { + { + .name = "file", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + .optional = true, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_file_help = { + .summary = "Load a Format Definition File (FDF)", + .args = cmd_print_format_file_args, +}; + +static const RzCmdDescArg cmd_print_format_size_args[] = { + { + .name = "format", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_size_help = { + .summary = "Print the size of format in bytes", + .args = cmd_print_format_size_args, +}; + +static const RzCmdDescArg cmd_print_format_value_args[] = { + { + .name = "format", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_value_help = { + .summary = "Print the value for named format", + .args = cmd_print_format_value_args, +}; + +static const RzCmdDescArg cmd_print_format_write_args[] = { + { + .name = "format", + .type = RZ_CMD_ARG_TYPE_STRING, + + }, + { + .name = "value", + .type = RZ_CMD_ARG_TYPE_STRING, + .flags = RZ_CMD_ARG_FLAG_LAST, + + }, + { 0 }, +}; +static const RzCmdDescHelp cmd_print_format_write_help = { + .summary = "Write data using given format string", + .args = cmd_print_format_write_args, +}; + static const RzCmdDescHelp pF_help = { .summary = "Print parsed ASN.1, PKCS, X509, ProtoBuf, AXML, etc.. formats", }; @@ -20939,6 +21167,35 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) { 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 *pf_cd = rz_cmd_desc_group_modes_new(core->rcmd, cmd_print_cd, "pf", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_RIZIN | RZ_OUTPUT_MODE_QUIET, rz_cmd_print_format_handler, &cmd_print_format_help, &pf_help); + rz_warn_if_fail(pf_cd); + RzCmdDesc *cmd_print_format_delete_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pf-", rz_cmd_print_format_delete_handler, &cmd_print_format_delete_help); + rz_warn_if_fail(cmd_print_format_delete_cd); + + RzCmdDesc *cmd_print_format_delete_all_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pf-*", rz_cmd_print_format_delete_all_handler, &cmd_print_format_delete_all_help); + rz_warn_if_fail(cmd_print_format_delete_all_cd); + + RzCmdDesc *cmd_print_format_c_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pfc", rz_cmd_print_format_c_handler, &cmd_print_format_c_help); + rz_warn_if_fail(cmd_print_format_c_cd); + + RzCmdDesc *cmd_print_format_dot_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pfd", rz_cmd_print_format_dot_handler, &cmd_print_format_dot_help); + rz_warn_if_fail(cmd_print_format_dot_cd); + + RzCmdDesc *cmd_print_format_named_cd = rz_cmd_desc_argv_modes_new(core->rcmd, pf_cd, "pf.", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_RIZIN | RZ_OUTPUT_MODE_QUIET, rz_cmd_print_format_named_handler, &cmd_print_format_named_help); + rz_warn_if_fail(cmd_print_format_named_cd); + + RzCmdDesc *cmd_print_format_file_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pfo", rz_cmd_print_format_file_handler, &cmd_print_format_file_help); + rz_warn_if_fail(cmd_print_format_file_cd); + + RzCmdDesc *cmd_print_format_size_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pfs", rz_cmd_print_format_size_handler, &cmd_print_format_size_help); + rz_warn_if_fail(cmd_print_format_size_cd); + + RzCmdDesc *cmd_print_format_value_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pfv", rz_cmd_print_format_value_handler, &cmd_print_format_value_help); + rz_warn_if_fail(cmd_print_format_value_cd); + + RzCmdDesc *cmd_print_format_write_cd = rz_cmd_desc_argv_new(core->rcmd, pf_cd, "pfw", rz_cmd_print_format_write_handler, &cmd_print_format_write_help); + rz_warn_if_fail(cmd_print_format_write_cd); + RzCmdDesc *pF_cd = rz_cmd_desc_group_new(core->rcmd, cmd_print_cd, "pF", NULL, NULL, &pF_help); rz_warn_if_fail(pF_cd); RzCmdDesc *cmd_print_asn1_cd = rz_cmd_desc_argv_modes_new(core->rcmd, pF_cd, "pFa", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_QUIET, rz_cmd_print_asn1_handler, &cmd_print_asn1_help); diff --git a/librz/core/cmd_descs/cmd_descs.h b/librz/core/cmd_descs/cmd_descs.h index 58f622027d6..b08c157d1f9 100644 --- a/librz/core/cmd_descs/cmd_descs.h +++ b/librz/core/cmd_descs/cmd_descs.h @@ -1807,6 +1807,26 @@ RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_n_bytes_handler(RzCore *core, in RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_function_handler(RzCore *core, int argc, const char **argv); // "pdsb" RZ_IPI RzCmdStatus rz_cmd_disassemble_summarize_block_handler(RzCore *core, int argc, const char **argv); +// "pf" +RZ_IPI RzCmdStatus rz_cmd_print_format_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode); +// "pf-" +RZ_IPI RzCmdStatus rz_cmd_print_format_delete_handler(RzCore *core, int argc, const char **argv); +// "pf-*" +RZ_IPI RzCmdStatus rz_cmd_print_format_delete_all_handler(RzCore *core, int argc, const char **argv); +// "pfc" +RZ_IPI RzCmdStatus rz_cmd_print_format_c_handler(RzCore *core, int argc, const char **argv); +// "pfd" +RZ_IPI RzCmdStatus rz_cmd_print_format_dot_handler(RzCore *core, int argc, const char **argv); +// "pf." +RZ_IPI RzCmdStatus rz_cmd_print_format_named_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode); +// "pfo" +RZ_IPI RzCmdStatus rz_cmd_print_format_file_handler(RzCore *core, int argc, const char **argv); +// "pfs" +RZ_IPI RzCmdStatus rz_cmd_print_format_size_handler(RzCore *core, int argc, const char **argv); +// "pfv" +RZ_IPI RzCmdStatus rz_cmd_print_format_value_handler(RzCore *core, int argc, const char **argv); +// "pfw" +RZ_IPI RzCmdStatus rz_cmd_print_format_write_handler(RzCore *core, int argc, const char **argv); // "pFa" RZ_IPI RzCmdStatus rz_cmd_print_asn1_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode); // "pFb" diff --git a/librz/core/cmd_descs/cmd_print.yaml b/librz/core/cmd_descs/cmd_print.yaml index 7eb5f0e327f..011caeb1b91 100644 --- a/librz/core/cmd_descs/cmd_print.yaml +++ b/librz/core/cmd_descs/cmd_print.yaml @@ -390,6 +390,201 @@ commands: summary: Summarize current block cname: cmd_disassemble_summarize_block args: [] + - name: pf + summary: Print formatted data + subcommands: + - name: pf + summary: Show data using given format string + cname: cmd_print_format + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + - RZ_OUTPUT_MODE_RIZIN + - RZ_OUTPUT_MODE_QUIET + args: + - name: format + type: RZ_CMD_ARG_TYPE_STRING + - name: pf- + summary: Remove named format + cname: cmd_print_format_delete + args: + - name: formatname + type: RZ_CMD_ARG_TYPE_STRING + - name: pf-* + summary: Remove all named formats + cname: cmd_print_format_delete_all + args: [] + - name: pfc + summary: Show data using given format string with C syntax + cname: cmd_print_format_c + args: + - name: format + type: RZ_CMD_ARG_TYPE_STRING + - name: pfd + summary: Show data using given format string as DOT + cname: cmd_print_format_dot + args: + - name: format + type: RZ_CMD_ARG_TYPE_STRING + - name: pf. + summary: Show data using given named format + cname: cmd_print_format_named + modes: + - RZ_OUTPUT_MODE_STANDARD + - RZ_OUTPUT_MODE_JSON + - RZ_OUTPUT_MODE_RIZIN + - RZ_OUTPUT_MODE_QUIET + args: + - name: formatname + type: RZ_CMD_ARG_TYPE_STRING + optional: true + - name: formatstring + type: RZ_CMD_ARG_TYPE_STRING + optional: true + - name: pfo + summary: Load a Format Definition File (FDF) + cname: cmd_print_format_file + args: + - name: file + type: RZ_CMD_ARG_TYPE_STRING + optional: true + - name: pfs + summary: Print the size of format in bytes + cname: cmd_print_format_size + args: + - name: format + type: RZ_CMD_ARG_TYPE_STRING + - name: pfv + summary: Print the value for named format + cname: cmd_print_format_value + args: + - name: format + type: RZ_CMD_ARG_TYPE_STRING + - name: pfw + summary: Write data using given format string + cname: cmd_print_format_write + args: + - name: format + type: RZ_CMD_ARG_TYPE_STRING + - name: value + type: RZ_CMD_ARG_TYPE_STRING + details: + - name: Formats + entries: + - text: "b" + comment: "byte (unsigned)" + - text: "B" + comment: "resolve enum bitfield (see t?)" + - text: "c" + comment: "char (signed byte)" + - text: "C" + comment: "byte in decimal" + - text: "d" + comment: "0xHEX value (4 bytes) (see 'i' and 'x' formats)" + - text: "D" + comment: "disassemble one opcode" + - text: "e" + comment: "temporarily swap endian" + - text: "E" + comment: "resolve enum name (see t?)" + - text: "f" + comment: "float value (4 bytes)" + - text: "F" + comment: "double float value (8 bytes)" + - text: "i" + comment: "signed integer value (4 bytes) (see 'd' and 'x' formats)" + - text: "n" + comment: "next char specifies size of signed value (1, 2, 4, or 8 byte(s))" + - text: "N" + comment: "next char specifies size of unsigned value (1, 2, 4, or 8 byte(s))" + - text: "o" + comment: "octal value (4 bytes)" + - text: "p" + comment: "pointer reference (2, 4, or 8 bytes)" + - text: "q" + comment: "quadword (8 bytes)" + - text: "Q" + comment: "octoword (uint128_t) (16 bytes)" + - text: "r" + comment: "CPU register (`pf r (eax)plop`)" + - text: "s" + comment: "32 bit pointer to string (4 bytes)" + - text: "s" + comment: "32 bit pointer to string (4 bytes)" + - text: "t" + comment: "32 bit UNIX timestamp (4 bytes)" + - text: "T" + comment: "show ten first bytes of buffer" + - text: "u" + comment: "uleb128 (variable length)" + - text: "w" + comment: "word (2 bytes unsigned short in hex)" + - text: "x" + comment: "0xHEX value and flag (fd @ addr) (see 'd' and 'i' formats)" + - text: "X" + comment: "show formatted hexpairs" + - text: "z" + comment: "null terminated string" + - text: "Z" + comment: "null terminated wide string" + - text: "?" + comment: "data structure `pf ? (struct_name)example_name`" + - text: "*" + comment: "next char is pointer (honors 'asm.bits')" + - text: "+" + comment: "toggle show flags for each offset" + - text: ":" + comment: "skip 4 bytes" + - text: "." + comment: "skip 1 byte" + - text: ";" + comment: "rewind 4 bytes" + - text: "," + comment: "rewind 1 byte" + - name: Example of usages + entries: + - text: "pf '3xi foo bar'" + comment: "3-array of structures, each with named fields: 'foo' as hex, 'bar' as int" + - text: "pf 'B (BitFldType)arg_name'" + comment: "Resolve bitfield enum type for the arg_name" + - text: "pf 'E (EnumType)arg_name'" + comment: "Resolve enum type for the arg_name" + - text: "pf '*z*i*w nb name blob'" + comment: "Print pointers with the given labels" + - text: "pf 'iwq foo bar troll'" + comment: "Print the iwq format with foo, bar, troll as respective fields" + - text: "pf '0iwq foo bar troll'" + comment: "Same as above but considered as a union (all fields at offset 0)" + - text: "pf 'obj xxdz prev next size name'" + comment: "Define the obj format as xxdz" + - text: "pf. 'plop ? (troll)mystruct'" + comment: "Use previously defined structure 'troll'" + - text: "pfj. plop @ 0x14" + comment: "Apply format object at the given offset" + - text: "pf {N} (bifc)" + comment: "Print N times the following format (bifc)" + - text: "pf [4]w[7]i" + comment: "Print an array of 4 words and then an array of 7 integers" + - text: "pf ic...?i foo bar \"(pf xw yo foo)troll\" yo" + comment: "Print nested anonymous structures" + - text: "pf ;..x" + comment: "Print value located 6 bytes from the current offset" + - text: "pf [10]z[3]i[10]Zb" + comment: "Print a fixed size string, widechar, and var" + - text: "pfj +F @ 0x14" + comment: "Print the content at given offset with a flag" + - text: "pf n2" + comment: "Print signed short (2 bytes) value. Use N instead of n for printing unsigned values" + - text: "pf [2]? (plop)structname @ 0x10" + comment: "Print an array of structures at the given offset" + - text: "pf eqew bigWord beef" + comment: "Swap endianness and print with given labels" + - text: "pf .foo rr (eax)reg1 (eip)reg2" + comment: "Create obect referencing to register values" + - text: "pf tt troll plop" + comment: "Print time stamps with labels 'troll' and 'plop'" + + - name: pF summary: Print parsed ASN.1, PKCS, X509, ProtoBuf, AXML, etc.. formats subcommands: