From 18db8301a4cb3b3bc4ab026bcf9b822eb03f86e4 Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Sat, 13 Nov 2021 10:57:17 +0800 Subject: [PATCH] Provide API for calculating sections digests (#1955) (#1970) --- librz/bin/bin.c | 2 +- librz/core/cbin.c | 110 +++++++++++++++++++++++++--------------- librz/include/rz_bin.h | 2 +- librz/include/rz_core.h | 1 + 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/librz/bin/bin.c b/librz/bin/bin.c index d89c1443d0..84d0b45173 100644 --- a/librz/bin/bin.c +++ b/librz/bin/bin.c @@ -1090,7 +1090,7 @@ RZ_API void rz_bin_map_free(RzBinMap *map) { * but if it is, plugins can use this function as their maps callback, * which will generate mappings for sections. * */ -RZ_API RzList *rz_bin_maps_of_file_sections(RzBinFile *binfile) { +RZ_API RZ_OWN RzList *rz_bin_maps_of_file_sections(RZ_NONNULL RzBinFile *binfile) { rz_return_val_if_fail(binfile, NULL); if (!binfile->o || !binfile->o->plugin || !binfile->o->plugin->sections) { return NULL; diff --git a/librz/core/cbin.c b/librz/core/cbin.c index 69c8786e25..a46e83c4dd 100644 --- a/librz/core/cbin.c +++ b/librz/core/cbin.c @@ -1622,6 +1622,46 @@ RZ_API bool rz_core_bin_apply_resources(RzCore *core, RzBinFile *binfile) { return true; } +static void digests_ht_free(HtPPKv *kv) { + free(kv->key); + free(kv->value); +} + +/** + * \brief Create a hashtable of digests for the RzBinSection + * + * Digest names are supplied as a list of `char *` strings. + * Returns the hashtable with keys of digest names and values of + * strings containing requested digests. + * */ +RZ_API RZ_OWN HtPP *rz_core_bin_section_digests(RzCore *core, RzBinSection *section, RzList *digests) { + rz_return_val_if_fail(section && digests, NULL); + HtPP *r = ht_pp_new(NULL, digests_ht_free, NULL); + if (!r) { + goto err; + } + RzListIter *it; + char *digest; + rz_list_foreach (digests, it, digest) { + ut8 *data = malloc(section->size); + if (!data) { + ht_pp_free(r); + return NULL; + goto err; + } + ut32 datalen = section->size; + rz_io_pread_at(core->io, section->paddr, data, datalen); + char *chkstr = rz_msg_digest_calculate_small_block_string(digest, data, datalen, NULL, false); + if (!chkstr) { + continue; + } + ht_pp_insert(r, digest, chkstr); + free(data); + } +err: + return r; +} + RZ_API int rz_core_bin_set_cur(RzCore *core, RzBinFile *binfile) { if (!core->bin) { return false; @@ -2338,6 +2378,13 @@ static ut64 get_section_addr(RzCore *core, RzBinObject *o, RzBinSection *section return rva(o, section->paddr, section->vaddr, va); } +static bool digests_pj_cb(void *user, const void *k, const void *v) { + rz_return_val_if_fail(user && k && v, false); + PJ *pj = user; + pj_ks(pj, k, v); + return true; +} + static void sections_print_json(RzCore *core, PJ *pj, RzBinObject *o, RzBinSection *section, RzList *hashes) { ut64 addr = get_section_addr(core, o, section); char perms[5]; @@ -2374,24 +2421,13 @@ static void sections_print_json(RzCore *core, PJ *pj, RzBinObject *o, RzBinSecti pj_kN(pj, "align", section->align); } if (hashes && section->size > 0) { - ut8 *data = malloc(section->size); - if (data) { - ut32 datalen = section->size; - RzListIter *iter; - char *hashname; - - rz_io_pread_at(core->io, section->paddr, data, datalen); - - rz_list_foreach (hashes, iter, hashname) { - char *chkstr = rz_msg_digest_calculate_small_block_string(hashname, data, datalen, NULL, false); - if (!chkstr) { - continue; - } - pj_ks(pj, hashname, chkstr); - free(chkstr); - } - free(data); + HtPP *digests = rz_core_bin_section_digests(core, section, hashes); + if (!digests) { + pj_end(pj); + return; } + ht_pp_foreach(digests, digests_pj_cb, pj); + ht_pp_free(digests); } pj_end(pj); } @@ -2423,37 +2459,31 @@ static bool sections_print_table(RzCore *core, RzTable *t, RzBinObject *o, RzBin if (!section->is_segment) { rz_table_add_row_columnsf(t, "ss", section_type, section_flags_str); } + bool result = false; if (hashes && section->size > 0) { - ut8 *data = malloc(section->size); - if (data) { - ut32 datalen = section->size; - RzListIter *iter; - char *hashname; - - rz_io_pread_at(core->io, section->paddr, data, datalen); - - rz_list_foreach (hashes, iter, hashname) { - const RzMsgDigestPlugin *msg_plugin = rz_msg_digest_plugin_by_name(hashname); - if (!msg_plugin) { - continue; - } - char *chkstr = rz_msg_digest_calculate_small_block_string(hashname, data, datalen, NULL, false); - if (!chkstr) { - rz_table_add_row_columnsf(t, "s", NULL); - continue; - } - rz_table_add_row_columnsf(t, "s", chkstr); - free(chkstr); - } - free(data); + HtPP *digests = rz_core_bin_section_digests(core, section, hashes); + if (!digests) { + goto cleanup; } + RzListIter *it; + char *hash; + bool found = false; + rz_list_foreach (hashes, it, hash) { + char *digest = ht_pp_find(digests, hash, &found); + if (found && t) { + rz_table_add_row_columnsf(t, "s", digest); + } + } + ht_pp_free(digests); } + result = true; +cleanup: if (section_name != section->name) { free(section_name); } free(section_type); free(section_flags_str); - return true; + return result; } static void sections_headers_setup(RzCore *core, RzCmdStateOutput *state, RzList *hashes) { diff --git a/librz/include/rz_bin.h b/librz/include/rz_bin.h index a37ecc631b..c0e443c28b 100644 --- a/librz/include/rz_bin.h +++ b/librz/include/rz_bin.h @@ -815,7 +815,7 @@ typedef struct rz_bin_bind_t { RZ_API void rz_bin_virtual_file_free(RzBinVirtualFile *vfile); RZ_API void rz_bin_map_free(RzBinMap *map); -RZ_API RzList *rz_bin_maps_of_file_sections(RzBinFile *binfile); +RZ_API RzList *rz_bin_maps_of_file_sections(RZ_NONNULL RzBinFile *binfile); RZ_API RzList *rz_bin_sections_of_maps(RzList /**/ *maps); RZ_API ut64 rz_bin_find_free_base_addr(RzList /**/ *maps, ut64 align); RZ_IPI RzBinSection *rz_bin_section_new(const char *name); diff --git a/librz/include/rz_core.h b/librz/include/rz_core.h index 77c472eaaa..c52d8ac057 100644 --- a/librz/include/rz_core.h +++ b/librz/include/rz_core.h @@ -763,6 +763,7 @@ RZ_API void rz_core_bin_export_info(RzCore *core, int mode); RZ_API int rz_core_bin_list(RzCore *core, int mode); RZ_API bool rz_core_bin_delete(RzCore *core, RzBinFile *bf); RZ_API ut64 rz_core_bin_impaddr(RzBin *bin, int va, const char *name); +RZ_API RZ_OWN HtPP *rz_core_bin_section_digests(RzCore *core, RzBinSection *section, RzList *digests); RZ_API void rz_core_bin_print_source_line_sample(RzCore *core, const RzBinSourceLineSample *s, RzCmdStateOutput *state); RZ_API void rz_core_bin_print_source_line_info(RzCore *core, const RzBinSourceLineInfo *li, RzCmdStateOutput *state);