blob: eb1989895af6d353f003539495dd9c63983107f1 [file] [log] [blame]
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001//===-- x86AssemblyInspectionEngine.cpp -------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "x86AssemblyInspectionEngine.h"
11
12#include "llvm-c/Disassembler.h"
13
14#include "lldb/Core/Address.h"
15#include "lldb/Symbol/UnwindPlan.h"
16#include "lldb/Target/RegisterContext.h"
17#include "lldb/Target/UnwindAssembly.h"
18
19using namespace lldb_private;
20using namespace lldb;
21
22x86AssemblyInspectionEngine::x86AssemblyInspectionEngine(const ArchSpec &arch)
23 : m_cur_insn(nullptr), m_machine_ip_regnum(LLDB_INVALID_REGNUM),
24 m_machine_sp_regnum(LLDB_INVALID_REGNUM),
25 m_machine_fp_regnum(LLDB_INVALID_REGNUM),
26 m_lldb_ip_regnum(LLDB_INVALID_REGNUM),
27 m_lldb_sp_regnum(LLDB_INVALID_REGNUM),
28 m_lldb_fp_regnum(LLDB_INVALID_REGNUM),
29
30 m_reg_map(), m_arch(arch), m_cpu(k_cpu_unspecified), m_wordsize(-1),
31 m_register_map_initialized(false), m_disasm_context() {
Jason Molendac0657a62016-10-01 00:19:26 +000032 m_disasm_context =
33 ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr,
34 /*TagType=*/1, nullptr, nullptr);
Jason Molenda74b8fbc2016-09-29 01:00:16 +000035}
36
37x86AssemblyInspectionEngine::~x86AssemblyInspectionEngine() {
38 ::LLVMDisasmDispose(m_disasm_context);
39}
40
41void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
42 m_cpu = k_cpu_unspecified;
43 m_wordsize = -1;
44 m_register_map_initialized = false;
45
46 const llvm::Triple::ArchType cpu = m_arch.GetMachine();
47 if (cpu == llvm::Triple::x86)
48 m_cpu = k_i386;
49 else if (cpu == llvm::Triple::x86_64)
50 m_cpu = k_x86_64;
51
52 if (m_cpu == k_cpu_unspecified)
53 return;
54
55 if (reg_ctx.get() == nullptr)
56 return;
57
58 if (m_cpu == k_i386) {
59 m_machine_ip_regnum = k_machine_eip;
60 m_machine_sp_regnum = k_machine_esp;
61 m_machine_fp_regnum = k_machine_ebp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000062 m_machine_alt_fp_regnum = k_machine_ebx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +000063 m_wordsize = 4;
64
65 struct lldb_reg_info reginfo;
66 reginfo.name = "eax";
67 m_reg_map[k_machine_eax] = reginfo;
68 reginfo.name = "edx";
69 m_reg_map[k_machine_edx] = reginfo;
70 reginfo.name = "esp";
71 m_reg_map[k_machine_esp] = reginfo;
72 reginfo.name = "esi";
73 m_reg_map[k_machine_esi] = reginfo;
74 reginfo.name = "eip";
75 m_reg_map[k_machine_eip] = reginfo;
76 reginfo.name = "ecx";
77 m_reg_map[k_machine_ecx] = reginfo;
78 reginfo.name = "ebx";
79 m_reg_map[k_machine_ebx] = reginfo;
80 reginfo.name = "ebp";
81 m_reg_map[k_machine_ebp] = reginfo;
82 reginfo.name = "edi";
83 m_reg_map[k_machine_edi] = reginfo;
84 } else {
85 m_machine_ip_regnum = k_machine_rip;
86 m_machine_sp_regnum = k_machine_rsp;
87 m_machine_fp_regnum = k_machine_rbp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000088 m_machine_alt_fp_regnum = k_machine_rbx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +000089 m_wordsize = 8;
90
91 struct lldb_reg_info reginfo;
92 reginfo.name = "rax";
93 m_reg_map[k_machine_rax] = reginfo;
94 reginfo.name = "rdx";
95 m_reg_map[k_machine_rdx] = reginfo;
96 reginfo.name = "rsp";
97 m_reg_map[k_machine_rsp] = reginfo;
98 reginfo.name = "rsi";
99 m_reg_map[k_machine_rsi] = reginfo;
100 reginfo.name = "r8";
101 m_reg_map[k_machine_r8] = reginfo;
102 reginfo.name = "r10";
103 m_reg_map[k_machine_r10] = reginfo;
104 reginfo.name = "r12";
105 m_reg_map[k_machine_r12] = reginfo;
106 reginfo.name = "r14";
107 m_reg_map[k_machine_r14] = reginfo;
108 reginfo.name = "rip";
109 m_reg_map[k_machine_rip] = reginfo;
110 reginfo.name = "rcx";
111 m_reg_map[k_machine_rcx] = reginfo;
112 reginfo.name = "rbx";
113 m_reg_map[k_machine_rbx] = reginfo;
114 reginfo.name = "rbp";
115 m_reg_map[k_machine_rbp] = reginfo;
116 reginfo.name = "rdi";
117 m_reg_map[k_machine_rdi] = reginfo;
118 reginfo.name = "r9";
119 m_reg_map[k_machine_r9] = reginfo;
120 reginfo.name = "r11";
121 m_reg_map[k_machine_r11] = reginfo;
122 reginfo.name = "r13";
123 m_reg_map[k_machine_r13] = reginfo;
124 reginfo.name = "r15";
125 m_reg_map[k_machine_r15] = reginfo;
126 }
127
128 for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin();
129 it != m_reg_map.end(); ++it) {
130 const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName(it->second.name);
131 if (ri)
132 it->second.lldb_regnum = ri->kinds[eRegisterKindLLDB];
133 }
134
135 uint32_t lldb_regno;
136 if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno))
137 m_lldb_sp_regnum = lldb_regno;
138 if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
139 m_lldb_fp_regnum = lldb_regno;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000140 if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
141 m_lldb_alt_fp_regnum = lldb_regno;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000142 if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
143 m_lldb_ip_regnum = lldb_regno;
144
145 m_register_map_initialized = true;
146}
147
148void x86AssemblyInspectionEngine::Initialize(
149 std::vector<lldb_reg_info> &reg_info) {
150 m_cpu = k_cpu_unspecified;
151 m_wordsize = -1;
152 m_register_map_initialized = false;
153
154 const llvm::Triple::ArchType cpu = m_arch.GetMachine();
155 if (cpu == llvm::Triple::x86)
156 m_cpu = k_i386;
157 else if (cpu == llvm::Triple::x86_64)
158 m_cpu = k_x86_64;
159
160 if (m_cpu == k_cpu_unspecified)
161 return;
162
163 if (m_cpu == k_i386) {
164 m_machine_ip_regnum = k_machine_eip;
165 m_machine_sp_regnum = k_machine_esp;
166 m_machine_fp_regnum = k_machine_ebp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000167 m_machine_alt_fp_regnum = k_machine_ebx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000168 m_wordsize = 4;
169
170 struct lldb_reg_info reginfo;
171 reginfo.name = "eax";
172 m_reg_map[k_machine_eax] = reginfo;
173 reginfo.name = "edx";
174 m_reg_map[k_machine_edx] = reginfo;
175 reginfo.name = "esp";
176 m_reg_map[k_machine_esp] = reginfo;
177 reginfo.name = "esi";
178 m_reg_map[k_machine_esi] = reginfo;
179 reginfo.name = "eip";
180 m_reg_map[k_machine_eip] = reginfo;
181 reginfo.name = "ecx";
182 m_reg_map[k_machine_ecx] = reginfo;
183 reginfo.name = "ebx";
184 m_reg_map[k_machine_ebx] = reginfo;
185 reginfo.name = "ebp";
186 m_reg_map[k_machine_ebp] = reginfo;
187 reginfo.name = "edi";
188 m_reg_map[k_machine_edi] = reginfo;
189 } else {
190 m_machine_ip_regnum = k_machine_rip;
191 m_machine_sp_regnum = k_machine_rsp;
192 m_machine_fp_regnum = k_machine_rbp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000193 m_machine_alt_fp_regnum = k_machine_rbx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000194 m_wordsize = 8;
195
196 struct lldb_reg_info reginfo;
197 reginfo.name = "rax";
198 m_reg_map[k_machine_rax] = reginfo;
199 reginfo.name = "rdx";
200 m_reg_map[k_machine_rdx] = reginfo;
201 reginfo.name = "rsp";
202 m_reg_map[k_machine_rsp] = reginfo;
203 reginfo.name = "rsi";
204 m_reg_map[k_machine_rsi] = reginfo;
205 reginfo.name = "r8";
206 m_reg_map[k_machine_r8] = reginfo;
207 reginfo.name = "r10";
208 m_reg_map[k_machine_r10] = reginfo;
209 reginfo.name = "r12";
210 m_reg_map[k_machine_r12] = reginfo;
211 reginfo.name = "r14";
212 m_reg_map[k_machine_r14] = reginfo;
213 reginfo.name = "rip";
214 m_reg_map[k_machine_rip] = reginfo;
215 reginfo.name = "rcx";
216 m_reg_map[k_machine_rcx] = reginfo;
217 reginfo.name = "rbx";
218 m_reg_map[k_machine_rbx] = reginfo;
219 reginfo.name = "rbp";
220 m_reg_map[k_machine_rbp] = reginfo;
221 reginfo.name = "rdi";
222 m_reg_map[k_machine_rdi] = reginfo;
223 reginfo.name = "r9";
224 m_reg_map[k_machine_r9] = reginfo;
225 reginfo.name = "r11";
226 m_reg_map[k_machine_r11] = reginfo;
227 reginfo.name = "r13";
228 m_reg_map[k_machine_r13] = reginfo;
229 reginfo.name = "r15";
230 m_reg_map[k_machine_r15] = reginfo;
231 }
232
233 for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin();
234 it != m_reg_map.end(); ++it) {
235 for (size_t i = 0; i < reg_info.size(); ++i) {
236 if (::strcmp(reg_info[i].name, it->second.name) == 0) {
237 it->second.lldb_regnum = reg_info[i].lldb_regnum;
238 break;
239 }
240 }
241 }
242
243 uint32_t lldb_regno;
244 if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno))
245 m_lldb_sp_regnum = lldb_regno;
246 if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
247 m_lldb_fp_regnum = lldb_regno;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000248 if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
249 m_lldb_alt_fp_regnum = lldb_regno;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000250 if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
251 m_lldb_ip_regnum = lldb_regno;
252
253 m_register_map_initialized = true;
254}
255
256// This function expects an x86 native register number (i.e. the bits stripped
Adrian Prantl05097242018-04-30 16:49:04 +0000257// out of the actual instruction), not an lldb register number.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000258//
259// FIXME: This is ABI dependent, it shouldn't be hardcoded here.
260
261bool x86AssemblyInspectionEngine::nonvolatile_reg_p(int machine_regno) {
262 if (m_cpu == k_i386) {
263 switch (machine_regno) {
264 case k_machine_ebx:
265 case k_machine_ebp: // not actually a nonvolatile but often treated as such
266 // by convention
267 case k_machine_esi:
268 case k_machine_edi:
269 case k_machine_esp:
270 return true;
271 default:
272 return false;
273 }
274 }
275 if (m_cpu == k_x86_64) {
276 switch (machine_regno) {
277 case k_machine_rbx:
278 case k_machine_rsp:
279 case k_machine_rbp: // not actually a nonvolatile but often treated as such
280 // by convention
281 case k_machine_r12:
282 case k_machine_r13:
283 case k_machine_r14:
284 case k_machine_r15:
285 return true;
286 default:
287 return false;
288 }
289 }
290 return false;
291}
292
293// Macro to detect if this is a REX mode prefix byte.
294#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
295
296// The high bit which should be added to the source register number (the "R"
297// bit)
298#define REX_W_SRCREG(opcode) (((opcode)&0x4) >> 2)
299
300// The high bit which should be added to the destination register number (the
301// "B" bit)
302#define REX_W_DSTREG(opcode) ((opcode)&0x1)
303
304// pushq %rbp [0x55]
305bool x86AssemblyInspectionEngine::push_rbp_pattern_p() {
306 uint8_t *p = m_cur_insn;
307 if (*p == 0x55)
308 return true;
309 return false;
310}
311
312// pushq $0 ; the first instruction in start() [0x6a 0x00]
313bool x86AssemblyInspectionEngine::push_0_pattern_p() {
314 uint8_t *p = m_cur_insn;
315 if (*p == 0x6a && *(p + 1) == 0x0)
316 return true;
317 return false;
318}
319
320// pushq $0
321// pushl $0
322bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
323 uint8_t *p = m_cur_insn;
324 if (*p == 0x68 || *p == 0x6a)
325 return true;
326 return false;
327}
328
Jason Molendac0657a62016-10-01 00:19:26 +0000329// pushl imm8(%esp)
330//
Adrian Prantl05097242018-04-30 16:49:04 +0000331// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' (same byte pattern for 'pushq
332// 0x20(%rsp)' in an x86_64 program)
Jason Molendac0657a62016-10-01 00:19:26 +0000333//
Adrian Prantl05097242018-04-30 16:49:04 +0000334// 0xff (with opcode bits '6' in next byte, PUSH r/m32) 0x74 (ModR/M byte with
335// three bits used to specify the opcode)
Jason Molendac0657a62016-10-01 00:19:26 +0000336// mod == b01, opcode == b110, R/M == b100
337// "+disp8"
Adrian Prantl05097242018-04-30 16:49:04 +0000338// 0x24 (SIB byte - scaled index = 0, r32 == esp) 0x20 imm8 value
Jason Molendac0657a62016-10-01 00:19:26 +0000339
340bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
341 if (*m_cur_insn == 0xff) {
342 // Get the 3 opcode bits from the ModR/M byte
343 uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
344 if (opcode == 6) {
345 // I'm only looking for 0xff /6 here - I
Adrian Prantl05097242018-04-30 16:49:04 +0000346 // don't really care what value is being pushed, just that we're pushing
347 // a 32/64 bit value on to the stack is enough.
Jason Molendac0657a62016-10-01 00:19:26 +0000348 return true;
349 }
350 }
351 return false;
352}
353
Jason Molenda2630acc2016-10-04 05:10:06 +0000354// instructions only valid in 32-bit mode:
355// 0x0e - push cs
356// 0x16 - push ss
357// 0x1e - push ds
358// 0x06 - push es
359bool x86AssemblyInspectionEngine::push_misc_reg_p() {
360 uint8_t p = *m_cur_insn;
361 if (m_wordsize == 4) {
362 if (p == 0x0e || p == 0x16 || p == 0x1e || p == 0x06)
363 return true;
364 }
365 return false;
366}
367
Jason Molendac0657a62016-10-01 00:19:26 +0000368// pushq %rbx
369// pushl %ebx
370bool x86AssemblyInspectionEngine::push_reg_p(int &regno) {
371 uint8_t *p = m_cur_insn;
372 int regno_prefix_bit = 0;
373 // If we have a rex prefix byte, check to see if a B bit is set
374 if (m_wordsize == 8 && *p == 0x41) {
375 regno_prefix_bit = 1 << 3;
376 p++;
377 }
378 if (*p >= 0x50 && *p <= 0x57) {
379 regno = (*p - 0x50) | regno_prefix_bit;
380 return true;
381 }
382 return false;
383}
384
Adrian Prantl05097242018-04-30 16:49:04 +0000385// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] movl %esp, %ebp [0x8b
386// 0xec] or [0x89 0xe5]
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000387bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
388 uint8_t *p = m_cur_insn;
389 if (m_wordsize == 8 && *p == 0x48)
390 p++;
391 if (*(p) == 0x8b && *(p + 1) == 0xec)
392 return true;
393 if (*(p) == 0x89 && *(p + 1) == 0xe5)
394 return true;
395 return false;
396}
397
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000398// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
399// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
400bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
401 uint8_t *p = m_cur_insn;
402 if (m_wordsize == 8 && *p == 0x48)
403 p++;
404 if (*(p) == 0x8b && *(p + 1) == 0xdc)
405 return true;
406 if (*(p) == 0x89 && *(p + 1) == 0xe3)
407 return true;
408 return false;
409}
410
411// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
412// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
413bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
414 uint8_t *p = m_cur_insn;
415 if (m_wordsize == 8 && *p == 0x48)
416 p++;
417 if (*(p) == 0x8b && *(p + 1) == 0xe5)
418 return true;
419 if (*(p) == 0x89 && *(p + 1) == 0xec)
420 return true;
421 return false;
422}
423
424// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
425// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
426bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
427 uint8_t *p = m_cur_insn;
428 if (m_wordsize == 8 && *p == 0x48)
429 p++;
430 if (*(p) == 0x8b && *(p + 1) == 0xe3)
431 return true;
432 if (*(p) == 0x89 && *(p + 1) == 0xdc)
433 return true;
434 return false;
435}
436
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000437// subq $0x20, %rsp
438bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
439 uint8_t *p = m_cur_insn;
440 if (m_wordsize == 8 && *p == 0x48)
441 p++;
442 // 8-bit immediate operand
443 if (*p == 0x83 && *(p + 1) == 0xec) {
444 amount = (int8_t) * (p + 2);
445 return true;
446 }
447 // 32-bit immediate operand
448 if (*p == 0x81 && *(p + 1) == 0xec) {
449 amount = (int32_t)extract_4(p + 2);
450 return true;
451 }
452 return false;
453}
454
455// addq $0x20, %rsp
456bool x86AssemblyInspectionEngine::add_rsp_pattern_p(int &amount) {
457 uint8_t *p = m_cur_insn;
458 if (m_wordsize == 8 && *p == 0x48)
459 p++;
460 // 8-bit immediate operand
461 if (*p == 0x83 && *(p + 1) == 0xc4) {
462 amount = (int8_t) * (p + 2);
463 return true;
464 }
465 // 32-bit immediate operand
466 if (*p == 0x81 && *(p + 1) == 0xc4) {
467 amount = (int32_t)extract_4(p + 2);
468 return true;
469 }
470 return false;
471}
472
473// lea esp, [esp - 0x28]
474// lea esp, [esp + 0x28]
475bool x86AssemblyInspectionEngine::lea_rsp_pattern_p(int &amount) {
476 uint8_t *p = m_cur_insn;
477 if (m_wordsize == 8 && *p == 0x48)
478 p++;
479
480 // Check opcode
481 if (*p != 0x8d)
482 return false;
483
484 // 8 bit displacement
485 if (*(p + 1) == 0x64 && (*(p + 2) & 0x3f) == 0x24) {
486 amount = (int8_t) * (p + 3);
487 return true;
488 }
489
490 // 32 bit displacement
491 if (*(p + 1) == 0xa4 && (*(p + 2) & 0x3f) == 0x24) {
492 amount = (int32_t)extract_4(p + 3);
493 return true;
494 }
495
496 return false;
497}
498
Pavel Labath89963462017-06-29 12:40:13 +0000499// lea -0x28(%ebp), %esp
500// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
501bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) {
502 uint8_t *p = m_cur_insn;
503 if (m_wordsize == 8 && *p == 0x48)
504 p++;
505
506 // Check opcode
507 if (*p != 0x8d)
508 return false;
509 ++p;
510
511 // 8 bit displacement
512 if (*p == 0x65) {
513 amount = (int8_t)p[1];
514 return true;
515 }
516
517 // 32 bit displacement
518 if (*p == 0xa5) {
519 amount = (int32_t)extract_4(p + 1);
520 return true;
521 }
522
523 return false;
524}
525
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000526// lea -0x28(%ebx), %esp
527// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
528bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
529 uint8_t *p = m_cur_insn;
530 if (m_wordsize == 8 && *p == 0x48)
531 p++;
532
533 // Check opcode
534 if (*p != 0x8d)
535 return false;
536 ++p;
537
538 // 8 bit displacement
539 if (*p == 0x63) {
540 amount = (int8_t)p[1];
541 return true;
542 }
543
544 // 32 bit displacement
545 if (*p == 0xa3) {
546 amount = (int32_t)extract_4(p + 1);
547 return true;
548 }
549
550 return false;
551}
552
553// and -0xfffffff0, %esp
554// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
555bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
556 uint8_t *p = m_cur_insn;
557 if (m_wordsize == 8 && *p == 0x48)
558 p++;
559
560 if (*p != 0x81 && *p != 0x83)
561 return false;
562
563 return *++p == 0xe4;
564}
565
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000566// popq %rbx
567// popl %ebx
568bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
569 uint8_t *p = m_cur_insn;
570 int regno_prefix_bit = 0;
571 // If we have a rex prefix byte, check to see if a B bit is set
572 if (m_wordsize == 8 && *p == 0x41) {
573 regno_prefix_bit = 1 << 3;
574 p++;
575 }
576 if (*p >= 0x58 && *p <= 0x5f) {
577 regno = (*p - 0x58) | regno_prefix_bit;
578 return true;
579 }
580 return false;
581}
582
583// popq %rbp [0x5d]
584// popl %ebp [0x5d]
585bool x86AssemblyInspectionEngine::pop_rbp_pattern_p() {
586 uint8_t *p = m_cur_insn;
587 return (*p == 0x5d);
588}
589
Jason Molenda2630acc2016-10-04 05:10:06 +0000590// instructions valid only in 32-bit mode:
591// 0x1f - pop ds
592// 0x07 - pop es
593// 0x17 - pop ss
594bool x86AssemblyInspectionEngine::pop_misc_reg_p() {
595 uint8_t p = *m_cur_insn;
596 if (m_wordsize == 4) {
597 if (p == 0x1f || p == 0x07 || p == 0x17)
598 return true;
599 }
600 return false;
601}
602
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000603// leave [0xc9]
604bool x86AssemblyInspectionEngine::leave_pattern_p() {
605 uint8_t *p = m_cur_insn;
606 return (*p == 0xc9);
607}
608
609// call $0 [0xe8 0x0 0x0 0x0 0x0]
610bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() {
611 uint8_t *p = m_cur_insn;
612 return (*p == 0xe8) && (*(p + 1) == 0x0) && (*(p + 2) == 0x0) &&
613 (*(p + 3) == 0x0) && (*(p + 4) == 0x0);
614}
615
Adrian Prantl05097242018-04-30 16:49:04 +0000616// Look for an instruction sequence storing a nonvolatile register on to the
617// stack frame.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000618
619// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
620// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
621
Adrian Prantl05097242018-04-30 16:49:04 +0000622// The offset value returned in rbp_offset will be positive -- but it must be
623// subtraced from the frame base register to get the actual location. The
624// positive value returned for the offset is a convention used elsewhere for
625// CFA offsets et al.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000626
627bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
628 int &regno, int &rbp_offset) {
629 uint8_t *p = m_cur_insn;
630 int src_reg_prefix_bit = 0;
631 int target_reg_prefix_bit = 0;
632
633 if (m_wordsize == 8 && REX_W_PREFIX_P(*p)) {
634 src_reg_prefix_bit = REX_W_SRCREG(*p) << 3;
635 target_reg_prefix_bit = REX_W_DSTREG(*p) << 3;
636 if (target_reg_prefix_bit == 1) {
Adrian Prantl05097242018-04-30 16:49:04 +0000637 // rbp/ebp don't need a prefix bit - we know this isn't the reg we care
638 // about.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000639 return false;
640 }
641 p++;
642 }
643
644 if (*p == 0x89) {
645 /* Mask off the 3-5 bits which indicate the destination register
646 if this is a ModR/M byte. */
647 int opcode_destreg_masked_out = *(p + 1) & (~0x38);
648
649 /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
650 and three bits between them, e.g. 01nnn101
651 We're looking for a destination of ebp-disp8 or ebp-disp32. */
652 int immsize;
653 if (opcode_destreg_masked_out == 0x45)
654 immsize = 2;
655 else if (opcode_destreg_masked_out == 0x85)
656 immsize = 4;
657 else
658 return false;
659
660 int offset = 0;
661 if (immsize == 2)
662 offset = (int8_t) * (p + 2);
663 if (immsize == 4)
664 offset = (uint32_t)extract_4(p + 2);
665 if (offset > 0)
666 return false;
667
668 regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
669 rbp_offset = offset > 0 ? offset : -offset;
670 return true;
671 }
672 return false;
673}
674
675// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
676bool x86AssemblyInspectionEngine::ret_pattern_p() {
677 uint8_t *p = m_cur_insn;
678 if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
679 return true;
680 return false;
681}
682
683uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) {
684 uint32_t v = 0;
685 for (int i = 3; i >= 0; i--)
686 v = (v << 8) | b[i];
687 return v;
688}
689
690bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p,
Jason Molendaf6208042017-07-08 00:12:15 +0000691 int &length,
692 uint32_t buffer_remaining_bytes) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000693
Jason Molendaf6208042017-07-08 00:12:15 +0000694 uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize());
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000695 llvm::SmallVector<uint8_t, 32> opcode_data;
696 opcode_data.resize(max_op_byte_size);
697
698 char out_string[512];
699 const size_t inst_size =
700 ::LLVMDisasmInstruction(m_disasm_context, insn_p, max_op_byte_size, 0,
701 out_string, sizeof(out_string));
702
703 length = inst_size;
704 return true;
705}
706
707bool x86AssemblyInspectionEngine::machine_regno_to_lldb_regno(
708 int machine_regno, uint32_t &lldb_regno) {
709 MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.find(machine_regno);
710 if (it != m_reg_map.end()) {
711 lldb_regno = it->second.lldb_regnum;
712 return true;
713 }
714 return false;
715 return false;
716}
717
718bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
719 uint8_t *data, size_t size, AddressRange &func_range,
720 UnwindPlan &unwind_plan) {
721 unwind_plan.Clear();
722
723 if (data == nullptr || size == 0)
724 return false;
725
726 if (m_register_map_initialized == false)
727 return false;
728
729 addr_t current_func_text_offset = 0;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000730 int current_sp_bytes_offset_from_fa = 0;
731 bool is_aligned = false;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000732 UnwindPlan::Row::RegisterLocation initial_regloc;
733 UnwindPlan::RowSP row(new UnwindPlan::Row);
734
735 unwind_plan.SetPlanValidAddressRange(func_range);
736 unwind_plan.SetRegisterKind(eRegisterKindLLDB);
737
738 // At the start of the function, find the CFA by adding wordsize to the SP
739 // register
740 row->SetOffset(current_func_text_offset);
741 row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize);
742
743 // caller's stack pointer value before the call insn is the CFA address
744 initial_regloc.SetIsCFAPlusOffset(0);
745 row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
746
747 // saved instruction pointer can be found at CFA - wordsize.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000748 current_sp_bytes_offset_from_fa = m_wordsize;
749 initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000750 row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
751
752 unwind_plan.AppendRow(row);
753
754 // Allocate a new Row, populate it with the existing Row contents.
755 UnwindPlan::Row *newrow = new UnwindPlan::Row;
756 *newrow = *row.get();
757 row.reset(newrow);
758
Adrian Prantl05097242018-04-30 16:49:04 +0000759 // Track which registers have been saved so far in the prologue. If we see
760 // another push of that register, it's not part of the prologue. The register
761 // numbers used here are the machine register #'s (i386_register_numbers,
762 // x86_64_register_numbers).
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000763 std::vector<bool> saved_registers(32, false);
764
765 // Once the prologue has completed we'll save a copy of the unwind
Adrian Prantl05097242018-04-30 16:49:04 +0000766 // instructions If there is an epilogue in the middle of the function, after
767 // that epilogue we'll reinstate the unwind setup -- we assume that some code
768 // path jumps over the mid-function epilogue
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000769
770 UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
771 int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
772 // epilogue started executed
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000773 bool prologue_completed_is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000774 std::vector<bool> prologue_completed_saved_registers;
775
776 while (current_func_text_offset < size) {
777 int stack_offset, insn_len;
778 int machine_regno; // register numbers masked directly out of instructions
779 uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB
780 // numbering scheme
781
782 bool in_epilogue = false; // we're in the middle of an epilogue sequence
783 bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
784
785 m_cur_insn = data + current_func_text_offset;
Jason Molendaf6208042017-07-08 00:12:15 +0000786 if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset)
787 || insn_len == 0
788 || insn_len > kMaxInstructionByteSize) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000789 // An unrecognized/junk instruction
790 break;
791 }
792
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000793 auto &cfa_value = row->GetCFAValue();
794 auto &afa_value = row->GetAFAValue();
795 auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
796
797 if (mov_rsp_rbp_pattern_p()) {
798 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
799 fa_value_ptr->SetIsRegisterPlusOffset(
800 m_lldb_fp_regnum, fa_value_ptr->GetOffset());
801 row_updated = true;
802 }
803 }
804
805 else if (mov_rsp_rbx_pattern_p()) {
806 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
807 fa_value_ptr->SetIsRegisterPlusOffset(
808 m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
809 row_updated = true;
810 }
811 }
812
813 else if (and_rsp_pattern_p()) {
814 current_sp_bytes_offset_from_fa = 0;
815 afa_value.SetIsRegisterPlusOffset(
816 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
817 fa_value_ptr = &afa_value;
818 is_aligned = true;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000819 row_updated = true;
820 }
821
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000822 else if (mov_rbp_rsp_pattern_p()) {
823 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
824 {
825 is_aligned = false;
826 fa_value_ptr = &cfa_value;
827 afa_value.SetUnspecified();
828 row_updated = true;
829 }
830 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
831 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
832 }
833
834 else if (mov_rbx_rsp_pattern_p()) {
835 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
836 {
837 is_aligned = false;
838 fa_value_ptr = &cfa_value;
839 afa_value.SetUnspecified();
840 row_updated = true;
841 }
842 if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
843 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000844 }
845
846 // This is the start() function (or a pthread equivalent), it starts with a
Adrian Prantl05097242018-04-30 16:49:04 +0000847 // pushl $0x0 which puts the saved pc value of 0 on the stack. In this
848 // case we want to pretend we didn't see a stack movement at all --
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000849 // normally the saved pc value is already on the stack by the time the
850 // function starts executing.
851 else if (push_0_pattern_p()) {
852 }
853
854 else if (push_reg_p(machine_regno)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000855 current_sp_bytes_offset_from_fa += m_wordsize;
856 // the PUSH instruction has moved the stack pointer - if the FA is set
Adrian Prantl05097242018-04-30 16:49:04 +0000857 // in terms of the stack pointer, we need to add a new row of
858 // instructions.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000859 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
860 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000861 row_updated = true;
862 }
863 // record where non-volatile (callee-saved, spilled) registers are saved
864 // on the stack
865 if (nonvolatile_reg_p(machine_regno) &&
866 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
867 saved_registers[machine_regno] == false) {
868 UnwindPlan::Row::RegisterLocation regloc;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000869 if (is_aligned)
870 regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
871 else
872 regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000873 row->SetRegisterInfo(lldb_regno, regloc);
874 saved_registers[machine_regno] = true;
875 row_updated = true;
876 }
877 }
878
879 else if (pop_reg_p(machine_regno)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000880 current_sp_bytes_offset_from_fa -= m_wordsize;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000881
882 if (nonvolatile_reg_p(machine_regno) &&
883 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
884 saved_registers[machine_regno] == true) {
885 saved_registers[machine_regno] = false;
886 row->RemoveRegisterInfo(lldb_regno);
887
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000888 if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
889 fa_value_ptr->SetIsRegisterPlusOffset(
890 m_lldb_sp_regnum, fa_value_ptr->GetOffset());
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000891 }
892
893 in_epilogue = true;
894 row_updated = true;
895 }
896
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000897 // the POP instruction has moved the stack pointer - if the FA is set in
Adrian Prantl05097242018-04-30 16:49:04 +0000898 // terms of the stack pointer, we need to add a new row of instructions.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000899 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
900 fa_value_ptr->SetIsRegisterPlusOffset(
901 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000902 row_updated = true;
903 }
904 }
905
Jason Molenda2630acc2016-10-04 05:10:06 +0000906 else if (pop_misc_reg_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000907 current_sp_bytes_offset_from_fa -= m_wordsize;
908 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
909 fa_value_ptr->SetIsRegisterPlusOffset(
910 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
Jason Molenda2630acc2016-10-04 05:10:06 +0000911 row_updated = true;
912 }
913 }
914
Adrian Prantl05097242018-04-30 16:49:04 +0000915 // The LEAVE instruction moves the value from rbp into rsp and pops a value
916 // off the stack into rbp (restoring the caller's rbp value). It is the
917 // opposite of ENTER, or 'push rbp, mov rsp rbp'.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000918 else if (leave_pattern_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000919 if (saved_registers[m_machine_fp_regnum]) {
920 saved_registers[m_machine_fp_regnum] = false;
921 row->RemoveRegisterInfo(m_lldb_fp_regnum);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000922
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000923 row_updated = true;
924 }
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000925
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000926 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
927 {
928 is_aligned = false;
929 fa_value_ptr = &cfa_value;
930 afa_value.SetUnspecified();
931 row_updated = true;
932 }
933
934 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
935 {
936 fa_value_ptr->SetIsRegisterPlusOffset(
937 m_lldb_sp_regnum, fa_value_ptr->GetOffset());
938
939 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
940 }
941
942 current_sp_bytes_offset_from_fa -= m_wordsize;
943
944 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
945 fa_value_ptr->SetIsRegisterPlusOffset(
946 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
947 row_updated = true;
948 }
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000949
950 in_epilogue = true;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000951 }
952
953 else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
954 nonvolatile_reg_p(machine_regno) &&
955 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
956 saved_registers[machine_regno] == false) {
957 saved_registers[machine_regno] = true;
958
959 UnwindPlan::Row::RegisterLocation regloc;
960
Adrian Prantl05097242018-04-30 16:49:04 +0000961 // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000962 // want to express this as the offset from the FA. If the frame base is
963 // rbp (like the above instruction), the FA offset for rbp is probably
964 // 16. So we want to say that the value is stored at the FA address -
Adrian Prantl05097242018-04-30 16:49:04 +0000965 // 96.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000966 if (is_aligned)
967 regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
968 else
969 regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000970
971 row->SetRegisterInfo(lldb_regno, regloc);
972
973 row_updated = true;
974 }
975
976 else if (sub_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000977 current_sp_bytes_offset_from_fa += stack_offset;
978 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
979 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000980 row_updated = true;
981 }
982 }
983
984 else if (add_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000985 current_sp_bytes_offset_from_fa -= stack_offset;
986 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
987 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000988 row_updated = true;
989 }
990 in_epilogue = true;
991 }
992
Jason Molenda2630acc2016-10-04 05:10:06 +0000993 else if (push_extended_pattern_p() || push_imm_pattern_p() ||
994 push_misc_reg_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000995 current_sp_bytes_offset_from_fa += m_wordsize;
996 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
997 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molendac0657a62016-10-01 00:19:26 +0000998 row_updated = true;
999 }
1000 }
1001
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001002 else if (lea_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001003 current_sp_bytes_offset_from_fa -= stack_offset;
1004 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1005 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001006 row_updated = true;
1007 }
1008 if (stack_offset > 0)
1009 in_epilogue = true;
1010 }
1011
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001012 else if (lea_rbp_rsp_pattern_p(stack_offset)) {
1013 if (is_aligned &&
1014 cfa_value.GetRegisterNumber() == m_lldb_fp_regnum) {
1015 is_aligned = false;
1016 fa_value_ptr = &cfa_value;
1017 afa_value.SetUnspecified();
1018 row_updated = true;
1019 }
1020 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
1021 current_sp_bytes_offset_from_fa =
1022 fa_value_ptr->GetOffset() - stack_offset;
1023 }
1024 }
1025
1026 else if (lea_rbx_rsp_pattern_p(stack_offset)) {
1027 if (is_aligned &&
1028 cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1029 is_aligned = false;
1030 fa_value_ptr = &cfa_value;
1031 afa_value.SetUnspecified();
1032 row_updated = true;
1033 }
1034 if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1035 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
1036 }
Pavel Labath89963462017-06-29 12:40:13 +00001037 }
1038
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001039 else if (ret_pattern_p() && prologue_completed_row.get()) {
Adrian Prantl05097242018-04-30 16:49:04 +00001040 // Reinstate the saved prologue setup for any instructions that come
1041 // after the ret instruction
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001042
1043 UnwindPlan::Row *newrow = new UnwindPlan::Row;
1044 *newrow = *prologue_completed_row.get();
1045 row.reset(newrow);
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001046 current_sp_bytes_offset_from_fa =
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001047 prologue_completed_sp_bytes_offset_from_cfa;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001048 is_aligned = prologue_completed_is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001049
1050 saved_registers.clear();
1051 saved_registers.resize(prologue_completed_saved_registers.size(), false);
1052 for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) {
1053 saved_registers[i] = prologue_completed_saved_registers[i];
1054 }
1055
1056 in_epilogue = true;
1057 row_updated = true;
1058 }
1059
1060 // call next instruction
1061 // call 0
1062 // => pop %ebx
1063 // This is used in i386 programs to get the PIC base address for finding
1064 // global data
1065 else if (call_next_insn_pattern_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001066 current_sp_bytes_offset_from_fa += m_wordsize;
1067 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1068 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001069 row_updated = true;
1070 }
1071 }
1072
1073 if (row_updated) {
1074 if (current_func_text_offset + insn_len < size) {
1075 row->SetOffset(current_func_text_offset + insn_len);
1076 unwind_plan.AppendRow(row);
1077 // Allocate a new Row, populate it with the existing Row contents.
1078 newrow = new UnwindPlan::Row;
1079 *newrow = *row.get();
1080 row.reset(newrow);
1081 }
1082 }
1083
1084 if (in_epilogue == false && row_updated) {
1085 // If we're not in an epilogue sequence, save the updated Row
1086 UnwindPlan::Row *newrow = new UnwindPlan::Row;
1087 *newrow = *row.get();
1088 prologue_completed_row.reset(newrow);
1089
1090 prologue_completed_saved_registers.clear();
1091 prologue_completed_saved_registers.resize(saved_registers.size(), false);
1092 for (size_t i = 0; i < saved_registers.size(); ++i) {
1093 prologue_completed_saved_registers[i] = saved_registers[i];
1094 }
1095 }
1096
1097 // We may change the sp value without adding a new Row necessarily -- keep
1098 // track of it either way.
1099 if (in_epilogue == false) {
1100 prologue_completed_sp_bytes_offset_from_cfa =
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001101 current_sp_bytes_offset_from_fa;
1102 prologue_completed_is_aligned = is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001103 }
1104
1105 m_cur_insn = m_cur_insn + insn_len;
1106 current_func_text_offset += insn_len;
1107 }
1108
1109 unwind_plan.SetSourceName("assembly insn profiling");
1110 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1111 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1112
1113 return true;
1114}
1115
1116bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
1117 uint8_t *data, size_t size, AddressRange &func_range,
1118 UnwindPlan &unwind_plan, RegisterContextSP &reg_ctx) {
1119 Address addr_start = func_range.GetBaseAddress();
1120 if (!addr_start.IsValid())
1121 return false;
1122
Adrian Prantl05097242018-04-30 16:49:04 +00001123 // We either need a live RegisterContext, or we need the UnwindPlan to
1124 // already be in the lldb register numbering scheme.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001125 if (reg_ctx.get() == nullptr &&
1126 unwind_plan.GetRegisterKind() != eRegisterKindLLDB)
1127 return false;
1128
1129 // Is original unwind_plan valid?
Adrian Prantl05097242018-04-30 16:49:04 +00001130 // unwind_plan should have at least one row which is ABI-default (CFA
1131 // register is sp), and another row in mid-function.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001132 if (unwind_plan.GetRowCount() < 2)
1133 return false;
1134
1135 UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex(0);
1136 if (first_row->GetOffset() != 0)
1137 return false;
1138 uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber();
1139 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1140 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1141 unwind_plan.GetRegisterKind(),
1142 first_row->GetCFAValue().GetRegisterNumber());
1143 }
1144 if (cfa_reg != m_lldb_sp_regnum ||
1145 first_row->GetCFAValue().GetOffset() != m_wordsize)
1146 return false;
1147
1148 UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset(-1);
1149
1150 size_t offset = 0;
1151 int row_id = 1;
1152 bool unwind_plan_updated = false;
1153 UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
1154 m_cur_insn = data + offset;
1155
Adrian Prantl05097242018-04-30 16:49:04 +00001156 // After a mid-function epilogue we will need to re-insert the original
1157 // unwind rules so unwinds work for the remainder of the function. These
1158 // aren't common with clang/gcc on x86 but it is possible.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001159 bool reinstate_unwind_state = false;
1160
1161 while (offset < size) {
1162 m_cur_insn = data + offset;
1163 int insn_len;
Jason Molendaf6208042017-07-08 00:12:15 +00001164 if (!instruction_length(m_cur_insn, insn_len, size - offset)
1165 || insn_len == 0
1166 || insn_len > kMaxInstructionByteSize) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001167 // An unrecognized/junk instruction.
1168 break;
1169 }
1170
1171 // Advance offsets.
1172 offset += insn_len;
1173 m_cur_insn = data + offset;
1174
Adrian Prantl05097242018-04-30 16:49:04 +00001175 // offset is pointing beyond the bounds of the function; stop looping.
Jason Molendab8ebcb52017-03-02 05:08:10 +00001176 if (offset >= size)
1177 continue;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001178
Jason Molendab8ebcb52017-03-02 05:08:10 +00001179 if (reinstate_unwind_state) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001180 UnwindPlan::RowSP new_row(new UnwindPlan::Row());
1181 *new_row = *original_last_row;
1182 new_row->SetOffset(offset);
1183 unwind_plan.AppendRow(new_row);
1184 row.reset(new UnwindPlan::Row());
1185 *row = *new_row;
1186 reinstate_unwind_state = false;
1187 unwind_plan_updated = true;
1188 continue;
1189 }
1190
1191 // If we already have one row for this instruction, we can continue.
1192 while (row_id < unwind_plan.GetRowCount() &&
1193 unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) {
1194 row_id++;
1195 }
1196 UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex(row_id - 1);
1197 if (original_row->GetOffset() == offset) {
1198 *row = *original_row;
1199 continue;
1200 }
1201
1202 if (row_id == 0) {
Adrian Prantl05097242018-04-30 16:49:04 +00001203 // If we are here, compiler didn't generate CFI for prologue. This won't
1204 // happen to GCC or clang. In this case, bail out directly.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001205 return false;
1206 }
1207
1208 // Inspect the instruction to check if we need a new row for it.
1209 cfa_reg = row->GetCFAValue().GetRegisterNumber();
1210 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1211 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1212 unwind_plan.GetRegisterKind(),
1213 row->GetCFAValue().GetRegisterNumber());
1214 }
1215 if (cfa_reg == m_lldb_sp_regnum) {
1216 // CFA register is sp.
1217
1218 // call next instruction
1219 // call 0
1220 // => pop %ebx
1221 if (call_next_insn_pattern_p()) {
1222 row->SetOffset(offset);
1223 row->GetCFAValue().IncOffset(m_wordsize);
1224
1225 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1226 unwind_plan.InsertRow(new_row);
1227 unwind_plan_updated = true;
1228 continue;
1229 }
1230
1231 // push/pop register
1232 int regno;
1233 if (push_reg_p(regno)) {
1234 row->SetOffset(offset);
1235 row->GetCFAValue().IncOffset(m_wordsize);
1236
1237 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1238 unwind_plan.InsertRow(new_row);
1239 unwind_plan_updated = true;
1240 continue;
1241 }
1242 if (pop_reg_p(regno)) {
1243 // Technically, this might be a nonvolatile register recover in
Adrian Prantl05097242018-04-30 16:49:04 +00001244 // epilogue. We should reset RegisterInfo for the register. But in
1245 // practice, previous rule for the register is still valid... So we
1246 // ignore this case.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001247
1248 row->SetOffset(offset);
1249 row->GetCFAValue().IncOffset(-m_wordsize);
1250
1251 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1252 unwind_plan.InsertRow(new_row);
1253 unwind_plan_updated = true;
1254 continue;
1255 }
1256
Jason Molenda2630acc2016-10-04 05:10:06 +00001257 if (pop_misc_reg_p()) {
1258 row->SetOffset(offset);
1259 row->GetCFAValue().IncOffset(-m_wordsize);
1260
1261 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1262 unwind_plan.InsertRow(new_row);
1263 unwind_plan_updated = true;
1264 continue;
1265 }
1266
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001267 // push imm
1268 if (push_imm_pattern_p()) {
1269 row->SetOffset(offset);
1270 row->GetCFAValue().IncOffset(m_wordsize);
1271 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1272 unwind_plan.InsertRow(new_row);
1273 unwind_plan_updated = true;
1274 continue;
1275 }
1276
Jason Molendac0657a62016-10-01 00:19:26 +00001277 // push extended
Jason Molenda2630acc2016-10-04 05:10:06 +00001278 if (push_extended_pattern_p() || push_misc_reg_p()) {
Jason Molendac0657a62016-10-01 00:19:26 +00001279 row->SetOffset(offset);
1280 row->GetCFAValue().IncOffset(m_wordsize);
1281 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1282 unwind_plan.InsertRow(new_row);
1283 unwind_plan_updated = true;
1284 continue;
1285 }
1286
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001287 // add/sub %rsp/%esp
1288 int amount;
1289 if (add_rsp_pattern_p(amount)) {
1290 row->SetOffset(offset);
1291 row->GetCFAValue().IncOffset(-amount);
1292
1293 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1294 unwind_plan.InsertRow(new_row);
1295 unwind_plan_updated = true;
1296 continue;
1297 }
1298 if (sub_rsp_pattern_p(amount)) {
1299 row->SetOffset(offset);
1300 row->GetCFAValue().IncOffset(amount);
1301
1302 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1303 unwind_plan.InsertRow(new_row);
1304 unwind_plan_updated = true;
1305 continue;
1306 }
1307
1308 // lea %rsp, [%rsp + $offset]
1309 if (lea_rsp_pattern_p(amount)) {
1310 row->SetOffset(offset);
1311 row->GetCFAValue().IncOffset(-amount);
1312
1313 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1314 unwind_plan.InsertRow(new_row);
1315 unwind_plan_updated = true;
1316 continue;
1317 }
1318
1319 if (ret_pattern_p()) {
1320 reinstate_unwind_state = true;
1321 continue;
1322 }
1323 } else if (cfa_reg == m_lldb_fp_regnum) {
1324 // CFA register is fp.
1325
1326 // The only case we care about is epilogue:
1327 // [0x5d] pop %rbp/%ebp
1328 // => [0xc3] ret
1329 if (pop_rbp_pattern_p() || leave_pattern_p()) {
Jason Molendac0657a62016-10-01 00:19:26 +00001330 offset += 1;
1331 row->SetOffset(offset);
1332 row->GetCFAValue().SetIsRegisterPlusOffset(
1333 first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001334
Jason Molendac0657a62016-10-01 00:19:26 +00001335 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1336 unwind_plan.InsertRow(new_row);
1337 unwind_plan_updated = true;
1338 reinstate_unwind_state = true;
1339 continue;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001340 }
1341 } else {
1342 // CFA register is not sp or fp.
1343
1344 // This must be hand-written assembly.
1345 // Just trust eh_frame and assume we have finished.
1346 break;
1347 }
1348 }
1349
1350 unwind_plan.SetPlanValidAddressRange(func_range);
1351 if (unwind_plan_updated) {
1352 std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString());
1353 unwind_plan_source += " plus augmentation from assembly parsing";
1354 unwind_plan.SetSourceName(unwind_plan_source.c_str());
1355 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1356 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1357 }
1358 return true;
1359}
1360
1361bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
1362 uint8_t *data, size_t size, size_t &offset) {
1363 offset = 0;
1364
1365 if (m_register_map_initialized == false)
1366 return false;
1367
1368 while (offset < size) {
1369 int regno;
1370 int insn_len;
1371 int scratch;
1372
1373 m_cur_insn = data + offset;
Jason Molendaf6208042017-07-08 00:12:15 +00001374 if (!instruction_length(m_cur_insn, insn_len, size - offset)
1375 || insn_len > kMaxInstructionByteSize
1376 || insn_len == 0) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001377 // An error parsing the instruction, i.e. probably data/garbage - stop
1378 // scanning
1379 break;
1380 }
1381
1382 if (push_rbp_pattern_p() || mov_rsp_rbp_pattern_p() ||
1383 sub_rsp_pattern_p(scratch) || push_reg_p(regno) ||
1384 mov_reg_to_local_stack_frame_p(regno, scratch) ||
1385 (lea_rsp_pattern_p(scratch) && offset == 0)) {
1386 offset += insn_len;
1387 continue;
1388 }
1389 //
1390 // Unknown non-prologue instruction - stop scanning
1391 break;
1392 }
1393
1394 return true;
1395}