diff --git a/librz/arch/similarity.c b/librz/arch/similarity.c index 1ff9a7181d7..c702df3cecb 100644 --- a/librz/arch/similarity.c +++ b/librz/arch/similarity.c @@ -513,6 +513,40 @@ static void *analysis_match_functions(SharedContext *shared) { return NULL; } +static void *analysis_match_one_function(SharedContext *shared) { + RzAnalysisFunction *fcn_a = NULL, *fcn_b = NULL; + RzAnalysisMatchPair *pair = NULL; + ut32 size_a = 0, size_b = 0; + ut8 *buf_a = NULL, *buf_b = NULL; + + fcn_b = rz_list_first(shared->list_b); + if (!shared_context_alloc_a(shared, fcn_b, &buf_b, &size_b)) { + RZ_LOG_ERROR("analysis_match: cannot allocate buffer for function %s (B)\n", fcn_b->name); + return NULL; + } + + while (rz_atomic_bool_get(shared->loop) && (fcn_a = rz_th_queue_pop(shared->queue, false))) { + if (!shared_context_alloc_b(shared, fcn_a, &buf_a, &size_a)) { + RZ_LOG_ERROR("analysis_match: cannot allocate buffer for function %s (A)\n", fcn_a->name); + free(buf_b); + return NULL; + } + + double similarity = calculate_similarity(buf_a, size_a, buf_b, size_b); + free(buf_a); + + if (!(pair = match_pair_new(fcn_a, fcn_b, similarity))) { + RZ_LOG_ERROR("analysis_match: cannot allocate match pair\n"); + free(buf_b); + return NULL; + } + rz_th_queue_push(shared->matches, pair, true); + } + + free(buf_b); + return NULL; +} + /** * \brief Finds matching functions of 2 given lists of functions using the same RzAnalysis core * @@ -524,5 +558,8 @@ static void *analysis_match_functions(SharedContext *shared) { */ RZ_API RZ_OWN RzAnalysisMatchResult *rz_analysis_match_functions(RzList /**/ *list_a, RzList /**/ *list_b, RZ_NONNULL RzAnalysisMatchOpt *opt) { rz_return_val_if_fail(opt && opt->analysis_a && opt->analysis_b && list_a && list_b, NULL); + if (rz_list_length(list_a) == 1) { + return analysis_match_result_new(opt, list_b, list_a, (RzThreadFunction)analysis_match_one_function, (AllocateBuffer)function_data_new); + } return analysis_match_result_new(opt, list_a, list_b, (RzThreadFunction)analysis_match_functions, (AllocateBuffer)function_data_new); } diff --git a/librz/main/rz-diff.c b/librz/main/rz-diff.c index fbead524b21..145a9c72cca 100644 --- a/librz/main/rz-diff.c +++ b/librz/main/rz-diff.c @@ -229,6 +229,7 @@ static void rz_diff_show_help(bool usage_only) { "", "", " bytes | compare raw bytes in the files (only for small files)", "", "", " lines | compare text files", "", "", " functions | compare functions found in the files", + "", "", " | optional -0 to compare only one function", "", "", " classes | compare classes found in the files", "", "", " command | compare command output returned when executed in both files", "", "", " | require -0 and -1 is optional", @@ -365,9 +366,7 @@ static void rz_diff_parse_arguments(int argc, const char **argv, DiffContext *ct } else if (!strcmp(type, "lines")) { rz_diff_ctx_set_type(ctx, DIFF_TYPE_LINES); } else if (!strcmp(type, "functions")) { - if (ctx->input_a) { - rz_diff_error_opt(ctx, DIFF_OPT_ERROR, "option -t '%s' does not support -0.\n", type); - } else if (ctx->input_b) { + if (ctx->input_b) { rz_diff_error_opt(ctx, DIFF_OPT_ERROR, "option -t '%s' does not support -1.\n", type); } ctx->option = DIFF_OPT_GRAPH; @@ -2072,7 +2071,7 @@ static int comparePairFunctions(const RzAnalysisMatchPair *ma, const RzAnalysisM * Then the scores are shown in a table (when in quiet mode, the table * is headerless) * */ -static void core_diff_show(RzCore *core_a, RzCore *core_b, DiffMode mode, bool verbose) { +static void core_diff_show(RzCore *core_a, RzCore *core_b, const char *addr_a, DiffMode mode, bool verbose) { rz_return_if_fail(core_a && core_b); char *output = NULL; @@ -2085,8 +2084,22 @@ static void core_diff_show(RzCore *core_a, RzCore *core_b, DiffMode mode, bool v RzAnalysisFunction *fcn_a = NULL, *fcn_b = NULL; RzListIter *iter = NULL; bool color = false, no_name = false; - - fcns_a = rz_list_clone(rz_analysis_function_list(core_a->analysis)); + if (RZ_STR_ISEMPTY(addr_a)) { + fcns_a = rz_list_clone(rz_analysis_function_list(core_a->analysis)); + } else { + fcns_a = rz_list_new(); + if (!fcns_a) { + RZ_LOG_ERROR("rz-diff: failed to create new list.\n"); + goto fail; + } + ut64 addr = rz_num_get(core_a->num, addr_a); + RzAnalysisFunction *fcn = rz_analysis_get_function_at(core_a->analysis, addr); + if (!fcn) { + RZ_LOG_ERROR("rz-diff: failed to find %s in file0.\n", addr_a); + goto fail; + } + rz_list_append(fcns_a, fcn); + } if (rz_list_empty(fcns_a)) { RZ_LOG_ERROR("rz-diff: No functions found in file0.\n"); goto fail; @@ -2296,7 +2309,7 @@ static bool rz_diff_graphs_files(DiffContext *ctx) { if (ctx->verbose) { fprintf(stderr, "rz-diff: start diffing.\n"); } - core_diff_show(a->core, b->core, ctx->mode, ctx->verbose); + core_diff_show(a->core, b->core, ctx->input_a, ctx->mode, ctx->verbose); } success = true; diff --git a/test/db/tools/rz_diff b/test/db/tools/rz_diff index 4fe9b2e48b6..9d0634828dc 100644 --- a/test/db/tools/rz_diff +++ b/test/db/tools/rz_diff @@ -980,3 +980,22 @@ EXPECT=<