Compare our (source) function to a potential binary match. Args: bin_ctx (ComparableContext): context representing a binary function (potential match) logger (logger): logger instance Return Value: floating point score for the entire match
(self, bin_ctx, logger)
| 585 | return True |
| 586 | |
| 587 | def compare(self, bin_ctx, logger): |
| 588 | """Compare our (source) function to a potential binary match. |
| 589 | |
| 590 | Args: |
| 591 | bin_ctx (ComparableContext): context representing a binary function (potential match) |
| 592 | logger (logger): logger instance |
| 593 | |
| 594 | Return Value: |
| 595 | floating point score for the entire match |
| 596 | """ |
| 597 | score = 0 |
| 598 | logger.addIndent() |
| 599 | # 0. prepare the instruction ratio (if has one already) |
| 600 | instr_ratio = (src_instr_count * 1.0 / bin_instr_count) if num_instr_samples >= INSTR_RATIO_COUNT_THRESHOLD else 1 |
| 601 | boost_score = len(self.blocks) <= MINIMAL_BLOCKS_BOOST and len(bin_ctx.blocks) <= MINIMAL_BLOCKS_BOOST |
| 602 | boost_score = boost_score and bin_ctx.call_hints is None and len(bin_ctx.xref_hints) == 0 |
| 603 | # 1. Match constants |
| 604 | const_score = ComparableContext.compareConsts(self, bin_ctx) |
| 605 | logger.debug("Const score: %f", const_score) |
| 606 | score += const_score |
| 607 | # 2. Match strings |
| 608 | string_score = ComparableContext.compareString(self, bin_ctx) |
| 609 | logger.debug("String score: %f", string_score) |
| 610 | score += string_score |
| 611 | # 3. Match sizes |
| 612 | function_size_score = -1 * abs(self.instrs - bin_ctx.instrs * instr_ratio) * INSTR_COUNT_SCORE |
| 613 | # check for a probable match |
| 614 | if abs(function_size_score) <= INSTR_COUNT_THRESHOLD * INSTR_COUNT_SCORE: |
| 615 | function_size_score += ARTIFACT_MATCH_SCORE |
| 616 | logger.debug("Function size score: %f", function_size_score) |
| 617 | score += function_size_score |
| 618 | # 4. Match stack frames |
| 619 | frame_size_score = -1 * abs(self.frame - bin_ctx.frame) * FUNC_FRAME_SCORE |
| 620 | # check for a probable match |
| 621 | if abs(frame_size_score) <= FRAME_SIZE_THRESHOLD * FUNC_FRAME_SCORE: |
| 622 | frame_size_score += ARTIFACT_MATCH_SCORE |
| 623 | logger.debug("Frame size score: %f", frame_size_score) |
| 624 | score += frame_size_score |
| 625 | # 5. Match calls |
| 626 | calls_score = ComparableContext.compareCalls(self, bin_ctx) |
| 627 | logger.debug("Calls score: %f", calls_score) |
| 628 | score += calls_score |
| 629 | # 6. Match code blocks |
| 630 | code_blocks_score = 0 |
| 631 | for index, block in enumerate(self.blocks): |
| 632 | code_blocks_score -= abs(self.blocks[index] - ((bin_ctx.blocks[index] * instr_ratio) if index < len(bin_ctx.blocks) else 0)) * BLOCK_MATCH_SCORE |
| 633 | for j in range(index + 1, len(bin_ctx.blocks)): |
| 634 | code_blocks_score -= bin_ctx.blocks[j] * BLOCK_MISMATCH_SCORE * instr_ratio |
| 635 | # check for a probable match |
| 636 | if abs(code_blocks_score) <= INSTR_COUNT_THRESHOLD * INSTR_COUNT_SCORE: |
| 637 | code_blocks_score += ARTIFACT_MATCH_SCORE |
| 638 | logger.debug("Code blocks score: %f", code_blocks_score) |
| 639 | score += code_blocks_score |
| 640 | # 7. Match function calls (hints) |
| 641 | call_hints_score = 0 |
| 642 | merged_hints = 0 |
| 643 | if bin_ctx.call_hints is not None and len(bin_ctx.call_hints) > 0 and self in bin_ctx.call_hints: |
| 644 | merged_hints = len([x for x in bin_ctx.call_hints if x.hash == self.hash]) |
nothing calls this directly
no test coverage detected