Skip to content

Commit

Permalink
Add one similarity against all functions of another binary (#4584)
Browse files Browse the repository at this point in the history
  • Loading branch information
wargio authored Aug 7, 2024
1 parent c02c0b7 commit 819812c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 7 deletions.
37 changes: 37 additions & 0 deletions librz/arch/similarity.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -524,5 +558,8 @@ static void *analysis_match_functions(SharedContext *shared) {
*/
RZ_API RZ_OWN RzAnalysisMatchResult *rz_analysis_match_functions(RzList /*<RzAnalysisFunction *>*/ *list_a, RzList /*<RzAnalysisFunction *>*/ *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);
}
27 changes: 20 additions & 7 deletions librz/main/rz-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <fcn name|offset> to compare only one function",
"", "", " classes | compare classes found in the files",
"", "", " command | compare command output returned when executed in both files",
"", "", " | require -0 <cmd> and -1 <cmd> is optional",
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions test/db/tools/rz_diff
Original file line number Diff line number Diff line change
Expand Up @@ -980,3 +980,22 @@ EXPECT=<<EOF
`-------------------------------------------------------------------------------------------------'
EOF
RUN

NAME=rz-diff functions comparison against only one function
FILE==
CMDS=!rz-diff -e 'analysis.fcnprefix=test' -e 'analysis.limits=true' -e 'analysis.from=0x401460' -e 'analysis.to=0x4033d0' -C -t functions -0 test.00401ae0 bins/other/rz-diff/true bins/other/rz-diff/false
EXPECT=<<EOF
.-------------------------------------------------------------------------------------------------.
| name0 | size0 | addr0 | type | similarity | addr1 | size1 | name1 |
)-------------------------------------------------------------------------------------------------(
| test.00401470 | 41 | 0x00401470 | UNLIKE | 0.0746 | 0x00401ae0 | 228 | test.00401ae0 |
| test.004019a0 | 137 | 0x004019a0 | UNLIKE | 0.1228 | 0x00401ae0 | 228 | test.00401ae0 |
| test.00401a30 | 162 | 0x00401a30 | UNLIKE | 0.0746 | 0x00401ae0 | 228 | test.00401ae0 |
| test.00401af0 | 228 | 0x00401af0 | PARTIAL | 0.964912 | 0x00401ae0 | 228 | test.00401ae0 |
| test.00401bf0 | 2728 | 0x00401bf0 | UNLIKE | 0.0433 | 0x00401ae0 | 228 | test.00401ae0 |
| test.00402740 | 425 | 0x00402740 | UNLIKE | 0.1106 | 0x00401ae0 | 228 | test.00401ae0 |
| test.004029b0 | 50 | 0x004029b0 | UNLIKE | 0.0702 | 0x00401ae0 | 228 | test.00401ae0 |
| test.00402e30 | 204 | 0x00402e30 | UNLIKE | 0.1140 | 0x00401ae0 | 228 | test.00401ae0 |
`-------------------------------------------------------------------------------------------------'
EOF
RUN

0 comments on commit 819812c

Please sign in to comment.