Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: courgette/rel32_finder_x64.cc

Issue 2072093003: Courgette: Extend pointer detection in x64. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Document instructions format and update unittests Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698