* Build the initial trampoline entry set. */
| 23 | * Build the initial trampoline entry set. |
| 24 | */ |
| 25 | void buildEntrySet(Binary *B) |
| 26 | { |
| 27 | // The entry points are only needed when trampoline prologues are enabled. |
| 28 | if (!option_batch || !option_Opeephole || |
| 29 | option_Oprologue == 0 || option_Oprologue_size == 0) |
| 30 | return; |
| 31 | |
| 32 | const Instr *I = B->Is.back(), *J = nullptr; |
| 33 | if (I == nullptr) |
| 34 | return; |
| 35 | unsigned num = 0, size = 0; |
| 36 | while (I != nullptr) |
| 37 | { |
| 38 | if (I->patch) |
| 39 | { |
| 40 | J = I; |
| 41 | num = size = 0; |
| 42 | } |
| 43 | else if (isCFT(I->ORIG, I->size, CFT_CALL | CFT_RET | CFT_JMP)) |
| 44 | J = nullptr; |
| 45 | if (J != nullptr && num <= option_Oprologue && |
| 46 | size <= option_Oprologue_size) |
| 47 | { |
| 48 | EntryPoint E = {J, INTPTR_MIN, false, false}; |
| 49 | B->Es.insert({I->addr, E}); |
| 50 | } |
| 51 | num += 1; |
| 52 | size += I->size; |
| 53 | I = I->prev(); |
| 54 | if (I == nullptr || I->next() != I->succ()) |
| 55 | J = nullptr; |
| 56 | } |
| 57 | |
| 58 | for (const Instr *I = B->Is.front(); I != nullptr; I = I->next()) |
| 59 | { |
| 60 | if (I->patch) |
| 61 | continue; |
| 62 | bool is_rel8 = false; |
| 63 | switch (I->ORIG[0]) |
| 64 | { |
| 65 | case 0xEB: case 0xE3: |
| 66 | case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: |
| 67 | case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: |
| 68 | case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: |
| 69 | case 0x7F: |
| 70 | if (I->size != /*sizeof(jmp/jcc rel8)*/2) |
| 71 | continue; |
| 72 | is_rel8 = true; |
| 73 | break; |
| 74 | case 0x66: |
| 75 | if (I->size != /*sizeof(jecxz rel8)*/3 || I->ORIG[1] != 0xE3) |
| 76 | continue; |
| 77 | is_rel8 = true; |
| 78 | break; |
| 79 | case 0xE8: case 0xE9: |
| 80 | if (I->size != /*sizeof(jmpq/call rel32)=*/5) |
| 81 | continue; |
| 82 | break; |