This function computes all of the preliminary information needed for unflattening.
| 684 | |
| 685 | // This function computes all of the preliminary information needed for unflattening. |
| 686 | bool GetAssignedAndComparisonVariables(mbl_array_t *mba) |
| 687 | { |
| 688 | // Look for the variable that was used in the largest number of jcc comparisons against a constant. This is our "comparison" variable. |
| 689 | JZCollector jzc; |
| 690 | mba->for_all_topinsns(jzc); |
| 691 | if (jzc.m_nMaxJz < 0) { |
| 692 | MSG_UF3(("[I] No comparisons seen; failed\n")); |
| 693 | return false; |
| 694 | } |
| 695 | #if DEBUG_UF >= 4 |
| 696 | jzc.ShouldBlacklist(); |
| 697 | #endif |
| 698 | |
| 699 | //it maybe second pass for the same proc already cleared, recalc entropy again |
| 700 | if (jzc.m_SeenComparisons[jzc.m_nMaxJz].ShouldBlacklist()) { |
| 701 | size_t i = 0; //m_nMaxJz may be with low entropy but still exist flattened blocks, looks for more cmps |
| 702 | for (; i < jzc.m_SeenComparisons.size(); ++i) { |
| 703 | if (i != jzc.m_nMaxJz && !jzc.m_SeenComparisons[i].ShouldBlacklist()) { |
| 704 | jzc.m_nMaxJz = i; |
| 705 | break; |
| 706 | } |
| 707 | } |
| 708 | if(i == jzc.m_SeenComparisons.size()) |
| 709 | return false; |
| 710 | } |
| 711 | |
| 712 | MSG_UF1(("[I] ----------------------- Unflattening ---------------------------------\n")); |
| 713 | mblock_t *first = GetFirstBlock(mba); // Find the "first" block in the function, the one immediately before the control flow switch. |
| 714 | if (!first) |
| 715 | return false; |
| 716 | MSG_UF1(("[I] found first block %d (ea=%a), dispatcher %d (ea=%a) \n", this->iFirst, mba->get_mblock(this->iFirst)->start, this->iDispatch, mba->get_mblock(this->iDispatch)->start)); |
| 717 | |
| 718 | mop_t *opMax = jzc.m_SeenComparisons[jzc.m_nMaxJz].op;// opMax is our "comparison" variable used in the control flow switch. |
| 719 | MSG_UF3(("[I] Comparison variable: %s\n", opMax->dstr())); |
| 720 | // if there are nested control flow switches, we have to identify the opMax of the dispatcher |
| 721 | mblock_t* mb_dispatch = mba->get_mblock(this->iDispatch); |
| 722 | mop_t* opMaxMoreLikely = NULL; |
| 723 | mop_t* opMaxSub = NULL; |
| 724 | for (auto const& sc : jzc.m_SeenComparisons) { |
| 725 | if (sc.nSeen >= MIN_NUM_COMPARISONS) { |
| 726 | mop_t* op = sc.op; |
| 727 | //mlist_t ml; |
| 728 | //mb_dispatch->append_use_list(&ml, *op, MUST_ACCESS); |
| 729 | opMaxMoreLikely = opMaxSub = NULL; |
| 730 | for (minsn_t* p = mb_dispatch->tail; p != NULL; p = p->prev) { |
| 731 | //mlist_t def = mb_dispatch->build_def_list(*p, MAY_ACCESS | FULL_XDSU); |
| 732 | //if ((def.includes(ml) || |
| 733 | if (isRegOvar(p->l.t) && p->l.equal_mops(*op, EQ_IGNSIZE)) { |
| 734 | if (isUfJc(p->opcode)) |
| 735 | opMaxMoreLikely = op; |
| 736 | else if (opMaxMoreLikely != NULL && p->opcode == m_mov && isRegOvar(p->d.t)) |
| 737 | opMaxSub = &p->d; |
| 738 | } else if (p->opcode == m_and && isRegOvar(p->d.t) && p->d.equal_mops(*op, EQ_IGNSIZE)) |
| 739 | opMaxMoreLikely = op; |
| 740 | } |
| 741 | if (opMaxMoreLikely != NULL) |
| 742 | break; |
| 743 | } |
nothing calls this directly
no test coverage detected