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 |