Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "courgette/rel32_finder_x64.h" | 5 #include "courgette/rel32_finder_x64.h" |
| 6 | 6 |
| 7 namespace courgette { | 7 namespace courgette { |
| 8 | 8 |
| 9 Rel32FinderX64::Rel32FinderX64(RVA relocs_start_rva, | 9 Rel32FinderX64::Rel32FinderX64(RVA relocs_start_rva, |
| 10 RVA relocs_end_rva, | 10 RVA relocs_end_rva, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 bool is_rip_relative = false; | 49 bool is_rip_relative = false; |
| 50 | 50 |
| 51 if (p + 5 <= end_pointer) { | 51 if (p + 5 <= end_pointer) { |
| 52 if (p[0] == 0xE8 || p[0] == 0xE9) // jmp rel32 and call rel32 | 52 if (p[0] == 0xE8 || p[0] == 0xE9) // jmp rel32 and call rel32 |
| 53 rel32 = p + 1; | 53 rel32 = p + 1; |
| 54 } | 54 } |
| 55 if (p + 6 <= end_pointer) { | 55 if (p + 6 <= end_pointer) { |
| 56 if (p[0] == 0x0F && (p[1] & 0xF0) == 0x80) { // Jcc long form | 56 if (p[0] == 0x0F && (p[1] & 0xF0) == 0x80) { // Jcc long form |
| 57 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely | 57 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely |
| 58 rel32 = p + 2; | 58 rel32 = p + 2; |
| 59 } else if (p[0] == 0xFF && (p[1] == 0x15 || p[1] == 0x25)) { | 59 } else if ((p[0] == 0xFF && |
| 60 // rip relative CALL/JMP | 60 (p[1] == 0x15 || p[1] == 0x25)) || |
| 61 ((p[0] == 0x89 || p[0] == 0x8B || p[0] == 0x8D) && | |
| 62 (p[1] & 0xC7) == 0x05)) { | |
| 63 // 6-byte instructions: | |
| 64 // [2-byte opcode] [disp32]: | |
| 65 // Opcode | |
| 66 // FF 15: call QWORD PTR [rip+disp32] | |
| 67 // FF 25: jmp QWORD PTR [rip+disp32] | |
| 68 // | |
| 69 // [1-byte opcode] [ModR/M] [disp32]: | |
| 70 // Opcode | |
| 71 // 89: mov DWORD PTR [rip+disp32],reg | |
| 72 // 8B: mov reg,DWORD PTR [rip+disp32] | |
| 73 // 8D: lea reg,[rip+disp32] | |
| 74 // ModR/M : MMRRRMMM | |
| 75 // M(Mod & r/m): 00 & 101 = disp32 | |
|
huangs
2016/06/27 20:25:14
Think it's better to be explicit:
// MM = 00 & MM
etiennep
2016/06/28 17:38:27
Done.
| |
| 76 // R(REG): selects reg operand from [eax|ecx|...|edi] | |
| 61 rel32 = p + 2; | 77 rel32 = p + 2; |
| 62 is_rip_relative = true; | 78 is_rip_relative = true; |
| 63 } | 79 } |
| 64 } | 80 } |
| 65 // TODO(etiennep): Many rip mov/lea variants are not detected. Experiment, | |
| 66 // fix and combine logic. | |
| 67 if (p + 7 <= end_pointer) { | 81 if (p + 7 <= end_pointer) { |
|
huangs
2016/06/27 20:25:14
// TODO(huangs): Maybe skip checking prefixes, and
etiennep
2016/06/28 17:38:27
Done.
| |
| 68 if ((p[0] & 0xFB) == 0x48 && // Dst reg : 48/4C [rax-rdi]/[r8-r15] | 82 if (((p[0] & 0xF2) == 0x40 || p[0] == 0x66) && |
| 69 p[1] == 0x8D && // LEA | 83 (p[1] == 0x89 || p[1] == 0x8B || p[1] == 0x8D) && |
| 70 (p[2] & 0xC7) == 0x05) { // Dst reg : [05,0D,...3D] = | 84 (p[2] & 0xC7) == 0x05) { |
| 71 // [rax,rbx,...,rdi]/[r8,r9,...,r15] | 85 // 7-byte instructions: |
| 72 // LEA dst, QWORD [rip + rel32] | 86 // [REX.W prefix] [1-byte opcode] [ModR/M] [disp32] |
| 73 rel32 = p + 3; | 87 // REX Prefix : 0100WR0B |
| 74 is_rip_relative = true; | 88 // W: 1 = 64 Bit Operand Size |
| 75 } else if ((p[0] & 0xFB) == 0x48 && // Dst reg : 48/4C [rax-rdi]/[r8-r15] | 89 // R: 0 = REG selects from [rax|rcx|...|rdi]. |
| 76 p[1] == 0x8B && // MOV | 90 // 1 = REG selects from [r9|r10|...|r15]. |
| 77 (p[2] & 0xC7) == 0x05) { // Dst reg : [05,0D,...3D] = | 91 // B: ModR/M r/m field extension (not used). |
| 78 // [rax,rbx,...,rdi]/[r8,r9,...,r15] | 92 // Opcode |
| 79 // MOV dst, QWORD PTR[rip + rel32] | 93 // 89: mov QWORD PTR [rip+disp32],reg |
| 94 // 8B: mov reg,QWORD PTR [rip+disp32] | |
| 95 // 8D: lea reg,[rip+disp32] | |
| 96 // ModR/M : MMRRRMMM | |
| 97 // M(Mod & r/m): 00 & 101 = disp32 | |
|
huangs
2016/06/27 20:25:14
// MM = 00 & MMM = 101 => rip+disp32
// RRR sele
etiennep
2016/06/28 17:38:27
Done.
| |
| 98 // R(REG): selects reg operand | |
| 99 // | |
| 100 // 0x66 [1-byte opcode] [ModR/M] [disp32] | |
| 101 // Prefix | |
| 102 // 0x66: Operand size override | |
| 103 // Opcode | |
| 104 // 89: mov WORD PTR [rip+disp32],reg | |
| 105 // 8B: mov reg,WORD PTR [rip+disp32] | |
| 106 // 8D: lea reg,[rip+disp32] | |
| 107 // ModR/M : MMRRRMMM | |
| 108 // M(Mod & r/m): 00 & 101 = disp32 | |
|
huangs
2016/06/27 20:25:14
// MM = 00 & MMM = 101 => rip+disp32
// RRR sele
etiennep
2016/06/28 17:38:27
Done.
| |
| 109 // R(REG): selects reg operand from [ax|cx|...|di] | |
| 80 rel32 = p + 3; | 110 rel32 = p + 3; |
| 81 is_rip_relative = true; | 111 is_rip_relative = true; |
| 82 } | 112 } |
| 83 } | 113 } |
| 84 | 114 |
| 85 if (rel32) { | 115 if (rel32) { |
| 86 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); | 116 RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); |
| 87 | 117 |
| 88 // Is there an abs32 reloc overlapping the candidate? | 118 // Is there an abs32 reloc overlapping the candidate? |
| 89 while (abs32_pos != abs32_locations.end() && *abs32_pos < rel32_rva - 3) | 119 while (abs32_pos != abs32_locations.end() && *abs32_pos < rel32_rva - 3) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 112 #endif | 142 #endif |
| 113 p = rel32 + 4; | 143 p = rel32 + 4; |
| 114 continue; | 144 continue; |
| 115 } | 145 } |
| 116 } | 146 } |
| 117 p += 1; | 147 p += 1; |
| 118 } | 148 } |
| 119 } | 149 } |
| 120 | 150 |
| 121 } // namespace courgette | 151 } // namespace courgette |
| OLD | NEW |