// SPDX-FileCopyrightText: 2009-2020 pancake // SPDX-License-Identifier: LGPL-3.0-only #include #include #include #include #include #include #include "../bin/pdb/pdb_downloader.h" #include "../core_private.h" static int bin_is_executable(RzBinObject *obj) { RzListIter *it; RzBinSection *sec; if (obj) { if (obj->info && obj->info->arch) { return true; } rz_list_foreach (obj->sections, it, sec) { if (sec->perm & RZ_PERM_X) { return true; } } } return false; } static bool is_equal_file_hashes(RzList /**/ *lfile_hashes, RzList /**/ *rfile_hashes, bool *equal) { rz_return_val_if_fail(lfile_hashes, false); rz_return_val_if_fail(rfile_hashes, false); rz_return_val_if_fail(equal, false); *equal = true; RzBinFileHash *fh_l, *fh_r; RzListIter *hiter_l, *hiter_r; rz_list_foreach (lfile_hashes, hiter_l, fh_l) { rz_list_foreach (rfile_hashes, hiter_r, fh_r) { if (strcmp(fh_l->type, fh_r->type)) { continue; } if (!!strcmp(fh_l->hex, fh_r->hex)) { *equal = false; return true; } } } return true; } static bool source_file_collect_cb(void *user, const void *k, const void *v) { RzPVector *r = user; char *f = strdup(k); if (f) { rz_pvector_push(r, f); } return true; } typedef enum { PRINT_SOURCE_INFO_LINES_ALL, PRINT_SOURCE_INFO_LINES_HERE, PRINT_SOURCE_INFO_FILES } PrintSourceInfoType; static bool print_source_info(RzCore *core, PrintSourceInfoType type, RzCmdStateOutput *state) { RzBinFile *binfile = core->bin->cur; if (!binfile || !binfile->o) { rz_cons_printf("No file loaded.\n"); return false; } RzBinSourceLineInfo *li = binfile->o->lines; if (!li) { rz_cons_printf("No source info available.\n"); return true; } switch (type) { case PRINT_SOURCE_INFO_FILES: { // collect all filenames uniquely HtPP *files = ht_pp_new0(); if (!files) { return false; } for (size_t i = 0; i < li->samples_count; i++) { RzBinSourceLineSample *s = &li->samples[i]; if (!s->line || !s->file) { continue; } ht_pp_insert(files, s->file, NULL); } // sort them alphabetically RzPVector sorter; rz_pvector_init(&sorter, free); ht_pp_foreach(files, source_file_collect_cb, &sorter); rz_pvector_sort(&sorter, (RzPVectorComparator)strcmp); ht_pp_free(files); // print them! if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_a(state->d.pj); void **it; rz_pvector_foreach (&sorter, it) { pj_s(state->d.pj, *it); } pj_end(state->d.pj); } else { rz_cons_printf("[Source file]\n"); void **it; rz_pvector_foreach (&sorter, it) { const char *file = *it; rz_cons_printf("%s\n", file); } } rz_pvector_fini(&sorter); break; } case PRINT_SOURCE_INFO_LINES_ALL: rz_core_bin_print_source_line_info(core, li, state); break; case PRINT_SOURCE_INFO_LINES_HERE: rz_cmd_state_output_array_start(state); for (const RzBinSourceLineSample *s = rz_bin_source_line_info_get_first_at(li, core->offset); s; s = rz_bin_source_line_info_get_next(li, s)) { rz_core_bin_print_source_line_sample(core, s, state); } rz_cmd_state_output_array_end(state); break; } return true; } RZ_IPI int rz_cmd_info_kuery(void *data, const char *input) { RzCore *core = (RzCore *)data; RzBinObject *o = rz_bin_cur_object(core->bin); Sdb *db = o ? o->kv : NULL; switch (input[0]) { case 'v': if (db) { char *o = sdb_querys(db, NULL, 0, input + 2); if (o && *o) { rz_cons_print(o); } free(o); } break; case '*': rz_core_bin_export_info(core, RZ_MODE_RIZINCMD); break; case '.': case ' ': if (db) { char *o = sdb_querys(db, NULL, 0, input + 1); if (o && *o) { rz_cons_print(o); } free(o); } break; case '\0': if (db) { char *o = sdb_querys(db, NULL, 0, "*"); if (o && *o) { rz_cons_print(o); } free(o); } break; case '?': default: RZ_LOG_ERROR("core: Usage: ik [sdb-query]\n"); RZ_LOG_ERROR("core: Usage: ik* # load all header information\n"); return 1; } return 0; } #define GET_CHECK_CUR_BINFILE(core) \ RzBinFile *bf = rz_bin_cur(core->bin); \ if (!bf) { \ RZ_LOG_ERROR("No binary object currently selected.\n"); \ return RZ_CMD_STATUS_ERROR; \ } RZ_IPI RzCmdStatus rz_cmd_info_archs_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { return bool2status(rz_core_bin_archs_print(core->bin, state)); } RZ_IPI RzCmdStatus rz_cmd_info_all_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); ut32 mask = RZ_CORE_BIN_ACC_INFO; mask |= RZ_CORE_BIN_ACC_IMPORTS; mask |= RZ_CORE_BIN_ACC_ENTRIES; mask |= RZ_CORE_BIN_ACC_EXPORTS; mask |= RZ_CORE_BIN_ACC_CLASSES; mask |= RZ_CORE_BIN_ACC_SYMBOLS; mask |= RZ_CORE_BIN_ACC_SECTIONS; mask |= RZ_CORE_BIN_ACC_MEM; mask |= RZ_CORE_BIN_ACC_STRINGS; if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_o(state->d.pj); } bool res = rz_core_bin_print(core, bf, mask, NULL, state, NULL); if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_end(state->d.pj); } return res ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR; } RZ_IPI RzCmdStatus rz_cmd_info_entry_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_entries_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_entryexits_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_initfini_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_exports_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_exports_print(core, bf, state, NULL)); } RZ_IPI RzCmdStatus rz_cmd_info_cur_export_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_cur_export_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_symbols_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_symbols_print(core, bf, state, NULL)); } RZ_IPI RzCmdStatus rz_cmd_info_cur_symbol_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_cur_symbol_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_imports_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_imports_print(core, bf, state, NULL)); } RZ_IPI RzCmdStatus rz_cmd_info_libs_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_libs_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_main_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_main_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_relocs_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_relocs_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_sections_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); RzList *hashes = rz_list_new_from_array((const void **)argv + 1, argc - 1); if (!hashes) { return RZ_CMD_STATUS_ERROR; } bool res = rz_core_bin_sections_print(core, bf, state, NULL, hashes); rz_list_free(hashes); return bool2status(res); } RZ_IPI RzCmdStatus rz_cmd_info_cur_section_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); RzList *hashes = rz_list_new_from_array((const void **)argv + 1, argc - 1); if (!hashes) { return RZ_CMD_STATUS_ERROR; } bool res = rz_core_bin_cur_section_print(core, bf, state, hashes); rz_list_free(hashes); return bool2status(res); } RZ_IPI RzCmdStatus rz_cmd_info_section_bars_handler(RzCore *core, int argc, const char **argv) { RzCmdStatus res = RZ_CMD_STATUS_ERROR; RzBinObject *o = rz_bin_cur_object(core->bin); if (!o) { RZ_LOG_ERROR("No binary object at current address\n"); return RZ_CMD_STATUS_ERROR; } RzList *sections = rz_bin_object_get_sections(o); if (!sections) { RZ_LOG_ERROR("Cannot retrieve sections\n"); return RZ_CMD_STATUS_ERROR; } int cols = rz_cons_get_size(NULL); RzList *list = rz_list_newf((RzListFree)rz_listinfo_free); if (!list) { goto sections_err; } RzListIter *iter; RzBinSection *section; rz_list_foreach (sections, iter, section) { char humansz[8]; RzInterval pitv = (RzInterval){ section->paddr, section->size }; RzInterval vitv = (RzInterval){ section->vaddr, section->vsize }; rz_num_units(humansz, sizeof(humansz), section->size); RzListInfo *info = rz_listinfo_new(section->name, pitv, vitv, section->perm, humansz); if (!info) { RZ_LOG_ERROR("Cannot print section bars\n"); goto list_err; } rz_list_append(list, info); } RzTable *table = rz_core_table(core); if (!table) { RZ_LOG_ERROR("Cannot print section bars\n"); goto list_err; } rz_table_visual_list(table, list, core->offset, -1, cols, core->io->va); char *s = rz_table_tostring(table); if (!s) { RZ_LOG_ERROR("Cannot print section bars\n"); goto table_err; } rz_cons_printf("%s\n", s); free(s); res = RZ_CMD_STATUS_OK; table_err: rz_table_free(table); list_err: rz_list_free(list); sections_err: rz_list_free(sections); return res; } RZ_IPI RzCmdStatus rz_cmd_info_segments_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); RzList *hashes = rz_list_new_from_array((const void **)argv + 1, argc - 1); if (!hashes) { return RZ_CMD_STATUS_ERROR; } bool res = rz_core_bin_segments_print(core, bf, state, NULL, hashes); rz_list_free(hashes); return bool2status(res); } RZ_IPI RzCmdStatus rz_cmd_info_cur_segment_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); RzList *hashes = rz_list_new_from_array((const void **)argv + 1, argc - 1); if (!hashes) { return RZ_CMD_STATUS_ERROR; } bool res = rz_core_bin_cur_segment_print(core, bf, state, hashes); rz_list_free(hashes); return bool2status(res); } RZ_IPI RzCmdStatus rz_cmd_info_strings_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_strings_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_whole_strings_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { RzBinFile *bf = rz_bin_cur(core->bin); return bool2status(rz_core_bin_whole_strings_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_purge_string_handler(RzCore *core, int argc, const char **argv) { char *strpurge = core->bin->strpurge; char tmp[2048]; rz_config_set(core->config, "bin.str.purge", rz_strf(tmp, "%s%s0x%" PFMT64x, strpurge ? strpurge : "", strpurge && *strpurge ? "," : "", core->offset)); return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_cmd_info_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { if (!core->file) { return RZ_CMD_STATUS_ERROR; } if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_o(state->d.pj); pj_k(state->d.pj, "core"); } RzBinFile *bf = rz_bin_cur(core->bin); bool res = rz_core_file_info_print(core, bf, state); if (bf && bin_is_executable(bf->o)) { if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_k(state->d.pj, "bin"); } rz_core_bin_info_print(core, bf, state); } if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_end(state->d.pj); } return bool2status(res); } RZ_IPI RzCmdStatus rz_cmd_info_classes_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_classes_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_class_as_source_handler(RzCore *core, int argc, const char **argv) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_class_as_source_print(core, bf, argv[1])); } RZ_IPI RzCmdStatus rz_cmd_info_class_fields_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_class_fields_print(core, bf, state, argv[1])); } RZ_IPI RzCmdStatus rz_cmd_info_class_methods_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_class_methods_print(core, bf, state, argv[1])); } RZ_IPI RzCmdStatus rz_cmd_info_signature_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_signatures_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_fields_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_fields_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_headers_handler(RzCore *core, int argc, const char **argv) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_headers_print(core, bf)); } RZ_IPI RzCmdStatus rz_cmd_info_binary_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_info_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_plugins_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { if (argc < 2) { rz_core_bin_plugins_print(core->bin, state); return RZ_CMD_STATUS_OK; } const char *plugin_name = argv[1]; const RzBinPlugin *bp = rz_bin_plugin_get(core->bin, plugin_name); if (bp) { rz_core_bin_plugin_print(bp, state); return RZ_CMD_STATUS_OK; } const RzBinXtrPlugin *xbp = rz_bin_xtrplugin_get(core->bin, plugin_name); if (xbp) { rz_core_binxtr_plugin_print(xbp, state); return RZ_CMD_STATUS_OK; } return RZ_CMD_STATUS_ERROR; } RZ_IPI RzCmdStatus rz_cmd_info_dwarf_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_dwarf_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_pdb_load_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { char *filename = argc > 1 ? strdup(argv[1]) : rz_core_bin_pdb_get_filename(core); if (!filename) { RZ_LOG_ERROR("Cannot find the right PDB file to load\n"); return RZ_CMD_STATUS_ERROR; } if (!rz_file_exists(filename)) { RZ_LOG_ERROR("Cannot open file '%s'\n", filename); free(filename); return RZ_CMD_STATUS_ERROR; } RzCmdStatus status = bool2status(rz_core_bin_pdb_load(core, filename)); free(filename); return status; } RZ_IPI RzCmdStatus rz_cmd_info_pdb_show_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { char *filename = argc > 1 ? strdup(argv[1]) : rz_core_bin_pdb_get_filename(core); if (!filename) { RZ_LOG_ERROR("Cannot find the right PDB file to load\n"); return RZ_CMD_STATUS_ERROR; } if (!rz_file_exists(filename)) { RZ_LOG_ERROR("Cannot open file '%s'\n", filename); free(filename); return RZ_CMD_STATUS_ERROR; } RzPdb *pdb = rz_core_pdb_load_info(core, filename); if (!pdb) { free(filename); return false; } rz_core_pdb_info_print(core, core->analysis->typedb, pdb, state); rz_bin_pdb_free(pdb); free(filename); return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_cmd_info_pdb_download_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { SPDBOptions pdbopts; pdbopts.extract = rz_config_get_i(core->config, "pdb.extract"); pdbopts.symbol_store_path = rz_config_get(core->config, "pdb.symstore"); pdbopts.symbol_server = rz_config_get(core->config, "pdb.server"); if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_o(state->d.pj); } int r = rz_bin_pdb_download(core->bin, state->mode == RZ_OUTPUT_MODE_JSON ? state->d.pj : NULL, state->mode == RZ_OUTPUT_MODE_JSON, &pdbopts); if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_end(state->d.pj); } if (r > 0 && state->mode != RZ_OUTPUT_MODE_JSON) { RZ_LOG_ERROR("Error while downloading pdb file\n"); return RZ_CMD_STATUS_ERROR; } return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_cmd_pdb_extract_handler(RzCore *core, int argc, const char **argv) { const char *file_cab = argv[1]; const char *output_dir = argv[2]; if (!rz_bin_pdb_extract_in_folder(file_cab, output_dir)) { return RZ_CMD_STATUS_ERROR; } return RZ_CMD_STATUS_OK; } static bool print_demangler_info(const RzDemanglerPlugin *plugin, void *user) { if (!user) { rz_cons_printf("%-6s %-8s %s\n", plugin->language, plugin->license, plugin->author); return true; } RzCmdStateOutput *state = (RzCmdStateOutput *)user; switch (state->mode) { case RZ_OUTPUT_MODE_QUIET: rz_cons_println(plugin->language); break; case RZ_OUTPUT_MODE_JSON: pj_o(state->d.pj); pj_ks(state->d.pj, "language", plugin->language); pj_ks(state->d.pj, "license", plugin->license); pj_ks(state->d.pj, "author", plugin->author); pj_end(state->d.pj); break; case RZ_OUTPUT_MODE_TABLE: rz_table_add_rowf(state->d.t, "sss", plugin->language, plugin->license, plugin->author); break; default: rz_warn_if_reached(); break; } return true; } RZ_IPI char **rz_cmd_info_demangle_lang_choices(RzCore *core) { char **res = RZ_NEWS0(char *, rz_list_length(core->bin->demangler->plugins) + 1); if (!res) { return NULL; } const RzDemanglerPlugin *plugin; RzListIter *it; int i = 0; rz_list_foreach (core->bin->demangler->plugins, it, plugin) { res[i++] = strdup(plugin->language); } return res; } RZ_IPI RzCmdStatus rz_cmd_info_demangle_handler(RzCore *core, int argc, const char **argv) { char *output = NULL; if (!rz_demangler_resolve(core->bin->demangler, argv[2], argv[1], &output)) { rz_cons_printf("Language '%s' is unsupported\nList of supported languages:\n", argv[1]); rz_demangler_plugin_iterate(core->bin->demangler, (RzDemanglerIter)print_demangler_info, NULL); return RZ_CMD_STATUS_ERROR; } rz_cons_println(output ? output : argv[2]); free(output); return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_cmd_info_demangle_list_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { rz_cmd_state_output_array_start(state); rz_cmd_state_output_set_columnsf(state, "sss", "language", "license", "author"); rz_demangler_plugin_iterate(core->bin->demangler, (RzDemanglerIter)print_demangler_info, state); rz_cmd_state_output_array_end(state); return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_cmd_info_memory_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_memory_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_resources_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); RzList *hashes = rz_list_new_from_array((const void **)argv + 1, argc - 1); if (!hashes) { return RZ_CMD_STATUS_ERROR; } bool res = rz_core_bin_resources_print(core, bf, state, hashes); rz_list_free(hashes); return bool2status(res); } RZ_IPI RzCmdStatus rz_cmd_info_hashes_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { ut64 limit = rz_config_get_i(core->config, "bin.hashlimit"); RzBinInfo *info = rz_bin_get_info(core->bin); if (!info) { RZ_LOG_ERROR("core: Cannot get bin info\n"); return RZ_CMD_STATUS_ERROR; } GET_CHECK_CUR_BINFILE(core); RzList *new_hashes = rz_bin_file_compute_hashes(core->bin, bf, limit); RzList *old_hashes = rz_bin_file_set_hashes(core->bin, new_hashes); bool equal = true; if (!rz_list_empty(new_hashes) && !rz_list_empty(old_hashes)) { if (!is_equal_file_hashes(new_hashes, old_hashes, &equal)) { RZ_LOG_ERROR("core: Cannot compare file hashes\n"); rz_list_free(old_hashes); return RZ_CMD_STATUS_ERROR; } } RzBinFileHash *fh_old, *fh_new; RzListIter *hiter_old, *hiter_new; switch (state->mode) { case RZ_OUTPUT_MODE_JSON: pj_o(state->d.pj); rz_list_foreach (new_hashes, hiter_new, fh_new) { pj_ks(state->d.pj, fh_new->type, fh_new->hex); } if (!equal) { // print old hashes prefixed with `o` character like `omd5` and `isha1` rz_list_foreach (old_hashes, hiter_old, fh_old) { char *key = rz_str_newf("o%s", fh_old->type); pj_ks(state->d.pj, key, fh_old->hex); free(key); } } pj_end(state->d.pj); break; case RZ_OUTPUT_MODE_STANDARD: if (!equal) { hiter_new = rz_list_iterator(new_hashes); hiter_old = rz_list_iterator(old_hashes); while (rz_list_iter_next(hiter_new) && rz_list_iter_next(hiter_old)) { fh_new = (RzBinFileHash *)rz_list_iter_get(hiter_new); fh_old = (RzBinFileHash *)rz_list_iter_get(hiter_old); if (strcmp(fh_new->type, fh_old->type)) { RZ_LOG_ERROR("core: Wrong file hashes structure"); } if (!strcmp(fh_new->hex, fh_old->hex)) { fprintf(stderr, "= %s %s\n", fh_new->type, fh_new->hex); // output one line because hash remains same `= hashtype hashval` } else { // output diff-like two lines, one with old hash val `- hashtype hashval` and one with new `+ hashtype hashval` fprintf(stderr, "- %s %s\n+ %s %s\n", fh_old->type, fh_old->hex, fh_new->type, fh_new->hex); } } } else { // hashes are equal rz_list_foreach (new_hashes, hiter_new, fh_new) { rz_cons_printf("%s %s\n", fh_new->type, fh_new->hex); } } break; default: rz_warn_if_reached(); break; } rz_list_free(old_hashes); return RZ_CMD_STATUS_OK; } RZ_IPI RzCmdStatus rz_cmd_info_versions_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_versions_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_trycatch_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); return bool2status(rz_core_bin_trycatch_print(core, bf, state)); } RZ_IPI RzCmdStatus rz_cmd_info_sourcelines_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { return bool2status(print_source_info(core, PRINT_SOURCE_INFO_LINES_ALL, state)); } RZ_IPI RzCmdStatus rz_cmd_info_sourcelines_here_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { return bool2status(print_source_info(core, PRINT_SOURCE_INFO_LINES_HERE, state)); } RZ_IPI RzCmdStatus rz_cmd_info_source_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { return bool2status(print_source_info(core, PRINT_SOURCE_INFO_FILES, state)); } RZ_IPI RzCmdStatus rz_cmd_info_guess_size_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) { GET_CHECK_CUR_BINFILE(core); if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_o(state->d.pj); pj_k(state->d.pj, "size"); } bool res = rz_core_bin_size_print(core, bf, state); if (state->mode == RZ_OUTPUT_MODE_JSON) { pj_end(state->d.pj); } return bool2status(res); }