blob: f8e70204e50983c18841dfba30d12ee274174941 [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;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000307 return *p == 0x55;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000308}
309
310// pushq $0 ; the first instruction in start() [0x6a 0x00]
311bool x86AssemblyInspectionEngine::push_0_pattern_p() {
312 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000313 return *p == 0x6a && *(p + 1) == 0x0;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000314}
315
316// pushq $0
317// pushl $0
318bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
319 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000320 return *p == 0x68 || *p == 0x6a;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000321}
322
Jason Molendac0657a62016-10-01 00:19:26 +0000323// pushl imm8(%esp)
324//
Adrian Prantl05097242018-04-30 16:49:04 +0000325// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' (same byte pattern for 'pushq
326// 0x20(%rsp)' in an x86_64 program)
Jason Molendac0657a62016-10-01 00:19:26 +0000327//
Adrian Prantl05097242018-04-30 16:49:04 +0000328// 0xff (with opcode bits '6' in next byte, PUSH r/m32) 0x74 (ModR/M byte with
329// three bits used to specify the opcode)
Jason Molendac0657a62016-10-01 00:19:26 +0000330// mod == b01, opcode == b110, R/M == b100
331// "+disp8"
Adrian Prantl05097242018-04-30 16:49:04 +0000332// 0x24 (SIB byte - scaled index = 0, r32 == esp) 0x20 imm8 value
Jason Molendac0657a62016-10-01 00:19:26 +0000333
334bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
335 if (*m_cur_insn == 0xff) {
336 // Get the 3 opcode bits from the ModR/M byte
337 uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
338 if (opcode == 6) {
339 // I'm only looking for 0xff /6 here - I
Adrian Prantl05097242018-04-30 16:49:04 +0000340 // don't really care what value is being pushed, just that we're pushing
341 // a 32/64 bit value on to the stack is enough.
Jason Molendac0657a62016-10-01 00:19:26 +0000342 return true;
343 }
344 }
345 return false;
346}
347
Jason Molenda2630acc2016-10-04 05:10:06 +0000348// instructions only valid in 32-bit mode:
349// 0x0e - push cs
350// 0x16 - push ss
351// 0x1e - push ds
352// 0x06 - push es
353bool x86AssemblyInspectionEngine::push_misc_reg_p() {
354 uint8_t p = *m_cur_insn;
355 if (m_wordsize == 4) {
356 if (p == 0x0e || p == 0x16 || p == 0x1e || p == 0x06)
357 return true;
358 }
359 return false;
360}
361
Jason Molendac0657a62016-10-01 00:19:26 +0000362// pushq %rbx
363// pushl %ebx
364bool x86AssemblyInspectionEngine::push_reg_p(int &regno) {
365 uint8_t *p = m_cur_insn;
366 int regno_prefix_bit = 0;
367 // If we have a rex prefix byte, check to see if a B bit is set
368 if (m_wordsize == 8 && *p == 0x41) {
369 regno_prefix_bit = 1 << 3;
370 p++;
371 }
372 if (*p >= 0x50 && *p <= 0x57) {
373 regno = (*p - 0x50) | regno_prefix_bit;
374 return true;
375 }
376 return false;
377}
378
Adrian Prantl05097242018-04-30 16:49:04 +0000379// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] movl %esp, %ebp [0x8b
380// 0xec] or [0x89 0xe5]
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000381bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
382 uint8_t *p = m_cur_insn;
383 if (m_wordsize == 8 && *p == 0x48)
384 p++;
385 if (*(p) == 0x8b && *(p + 1) == 0xec)
386 return true;
387 if (*(p) == 0x89 && *(p + 1) == 0xe5)
388 return true;
389 return false;
390}
391
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000392// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
393// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
394bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
395 uint8_t *p = m_cur_insn;
396 if (m_wordsize == 8 && *p == 0x48)
397 p++;
398 if (*(p) == 0x8b && *(p + 1) == 0xdc)
399 return true;
400 if (*(p) == 0x89 && *(p + 1) == 0xe3)
401 return true;
402 return false;
403}
404
405// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
406// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
407bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
408 uint8_t *p = m_cur_insn;
409 if (m_wordsize == 8 && *p == 0x48)
410 p++;
411 if (*(p) == 0x8b && *(p + 1) == 0xe5)
412 return true;
413 if (*(p) == 0x89 && *(p + 1) == 0xec)
414 return true;
415 return false;
416}
417
418// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
419// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
420bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
421 uint8_t *p = m_cur_insn;
422 if (m_wordsize == 8 && *p == 0x48)
423 p++;
424 if (*(p) == 0x8b && *(p + 1) == 0xe3)
425 return true;
426 if (*(p) == 0x89 && *(p + 1) == 0xdc)
427 return true;
428 return false;
429}
430
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000431// subq $0x20, %rsp
432bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
433 uint8_t *p = m_cur_insn;
434 if (m_wordsize == 8 && *p == 0x48)
435 p++;
436 // 8-bit immediate operand
437 if (*p == 0x83 && *(p + 1) == 0xec) {
438 amount = (int8_t) * (p + 2);
439 return true;
440 }
441 // 32-bit immediate operand
442 if (*p == 0x81 && *(p + 1) == 0xec) {
443 amount = (int32_t)extract_4(p + 2);
444 return true;
445 }
446 return false;
447}
448
449// addq $0x20, %rsp
450bool x86AssemblyInspectionEngine::add_rsp_pattern_p(int &amount) {
451 uint8_t *p = m_cur_insn;
452 if (m_wordsize == 8 && *p == 0x48)
453 p++;
454 // 8-bit immediate operand
455 if (*p == 0x83 && *(p + 1) == 0xc4) {
456 amount = (int8_t) * (p + 2);
457 return true;
458 }
459 // 32-bit immediate operand
460 if (*p == 0x81 && *(p + 1) == 0xc4) {
461 amount = (int32_t)extract_4(p + 2);
462 return true;
463 }
464 return false;
465}
466
467// lea esp, [esp - 0x28]
468// lea esp, [esp + 0x28]
469bool x86AssemblyInspectionEngine::lea_rsp_pattern_p(int &amount) {
470 uint8_t *p = m_cur_insn;
471 if (m_wordsize == 8 && *p == 0x48)
472 p++;
473
474 // Check opcode
475 if (*p != 0x8d)
476 return false;
477
478 // 8 bit displacement
479 if (*(p + 1) == 0x64 && (*(p + 2) & 0x3f) == 0x24) {
480 amount = (int8_t) * (p + 3);
481 return true;
482 }
483
484 // 32 bit displacement
485 if (*(p + 1) == 0xa4 && (*(p + 2) & 0x3f) == 0x24) {
486 amount = (int32_t)extract_4(p + 3);
487 return true;
488 }
489
490 return false;
491}
492
Pavel Labath89963462017-06-29 12:40:13 +0000493// lea -0x28(%ebp), %esp
494// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
495bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) {
496 uint8_t *p = m_cur_insn;
497 if (m_wordsize == 8 && *p == 0x48)
498 p++;
499
500 // Check opcode
501 if (*p != 0x8d)
502 return false;
503 ++p;
504
505 // 8 bit displacement
506 if (*p == 0x65) {
507 amount = (int8_t)p[1];
508 return true;
509 }
510
511 // 32 bit displacement
512 if (*p == 0xa5) {
513 amount = (int32_t)extract_4(p + 1);
514 return true;
515 }
516
517 return false;
518}
519
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000520// lea -0x28(%ebx), %esp
521// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
522bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
523 uint8_t *p = m_cur_insn;
524 if (m_wordsize == 8 && *p == 0x48)
525 p++;
526
527 // Check opcode
528 if (*p != 0x8d)
529 return false;
530 ++p;
531
532 // 8 bit displacement
533 if (*p == 0x63) {
534 amount = (int8_t)p[1];
535 return true;
536 }
537
538 // 32 bit displacement
539 if (*p == 0xa3) {
540 amount = (int32_t)extract_4(p + 1);
541 return true;
542 }
543
544 return false;
545}
546
547// and -0xfffffff0, %esp
548// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
549bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
550 uint8_t *p = m_cur_insn;
551 if (m_wordsize == 8 && *p == 0x48)
552 p++;
553
554 if (*p != 0x81 && *p != 0x83)
555 return false;
556
557 return *++p == 0xe4;
558}
559
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000560// popq %rbx
561// popl %ebx
562bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
563 uint8_t *p = m_cur_insn;
564 int regno_prefix_bit = 0;
565 // If we have a rex prefix byte, check to see if a B bit is set
566 if (m_wordsize == 8 && *p == 0x41) {
567 regno_prefix_bit = 1 << 3;
568 p++;
569 }
570 if (*p >= 0x58 && *p <= 0x5f) {
571 regno = (*p - 0x58) | regno_prefix_bit;
572 return true;
573 }
574 return false;
575}
576
577// popq %rbp [0x5d]
578// popl %ebp [0x5d]
579bool x86AssemblyInspectionEngine::pop_rbp_pattern_p() {
580 uint8_t *p = m_cur_insn;
581 return (*p == 0x5d);
582}
583
Jason Molenda2630acc2016-10-04 05:10:06 +0000584// instructions valid only in 32-bit mode:
585// 0x1f - pop ds
586// 0x07 - pop es
587// 0x17 - pop ss
588bool x86AssemblyInspectionEngine::pop_misc_reg_p() {
589 uint8_t p = *m_cur_insn;
590 if (m_wordsize == 4) {
591 if (p == 0x1f || p == 0x07 || p == 0x17)
592 return true;
593 }
594 return false;
595}
596
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000597// leave [0xc9]
598bool x86AssemblyInspectionEngine::leave_pattern_p() {
599 uint8_t *p = m_cur_insn;
600 return (*p == 0xc9);
601}
602
603// call $0 [0xe8 0x0 0x0 0x0 0x0]
604bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() {
605 uint8_t *p = m_cur_insn;
606 return (*p == 0xe8) && (*(p + 1) == 0x0) && (*(p + 2) == 0x0) &&
607 (*(p + 3) == 0x0) && (*(p + 4) == 0x0);
608}
609
Adrian Prantl05097242018-04-30 16:49:04 +0000610// Look for an instruction sequence storing a nonvolatile register on to the
611// stack frame.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000612
613// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
614// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
615
Adrian Prantl05097242018-04-30 16:49:04 +0000616// The offset value returned in rbp_offset will be positive -- but it must be
617// subtraced from the frame base register to get the actual location. The
618// positive value returned for the offset is a convention used elsewhere for
619// CFA offsets et al.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000620
621bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
622 int &regno, int &rbp_offset) {
623 uint8_t *p = m_cur_insn;
624 int src_reg_prefix_bit = 0;
625 int target_reg_prefix_bit = 0;
626
627 if (m_wordsize == 8 && REX_W_PREFIX_P(*p)) {
628 src_reg_prefix_bit = REX_W_SRCREG(*p) << 3;
629 target_reg_prefix_bit = REX_W_DSTREG(*p) << 3;
630 if (target_reg_prefix_bit == 1) {
Adrian Prantl05097242018-04-30 16:49:04 +0000631 // rbp/ebp don't need a prefix bit - we know this isn't the reg we care
632 // about.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000633 return false;
634 }
635 p++;
636 }
637
638 if (*p == 0x89) {
639 /* Mask off the 3-5 bits which indicate the destination register
640 if this is a ModR/M byte. */
641 int opcode_destreg_masked_out = *(p + 1) & (~0x38);
642
643 /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
644 and three bits between them, e.g. 01nnn101
645 We're looking for a destination of ebp-disp8 or ebp-disp32. */
646 int immsize;
647 if (opcode_destreg_masked_out == 0x45)
648 immsize = 2;
649 else if (opcode_destreg_masked_out == 0x85)
650 immsize = 4;
651 else
652 return false;
653
654 int offset = 0;
655 if (immsize == 2)
656 offset = (int8_t) * (p + 2);
657 if (immsize == 4)
658 offset = (uint32_t)extract_4(p + 2);
659 if (offset > 0)
660 return false;
661
662 regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
663 rbp_offset = offset > 0 ? offset : -offset;
664 return true;
665 }
666 return false;
667}
668
669// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
670bool x86AssemblyInspectionEngine::ret_pattern_p() {
671 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000672 return *p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000673}
674
675uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) {
676 uint32_t v = 0;
677 for (int i = 3; i >= 0; i--)
678 v = (v << 8) | b[i];
679 return v;
680}
681
682bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p,
Jason Molendaf6208042017-07-08 00:12:15 +0000683 int &length,
684 uint32_t buffer_remaining_bytes) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000685
Jason Molendaf6208042017-07-08 00:12:15 +0000686 uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize());
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000687 llvm::SmallVector<uint8_t, 32> opcode_data;
688 opcode_data.resize(max_op_byte_size);
689
690 char out_string[512];
691 const size_t inst_size =
692 ::LLVMDisasmInstruction(m_disasm_context, insn_p, max_op_byte_size, 0,
693 out_string, sizeof(out_string));
694
695 length = inst_size;
696 return true;
697}
698
699bool x86AssemblyInspectionEngine::machine_regno_to_lldb_regno(
700 int machine_regno, uint32_t &lldb_regno) {
701 MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.find(machine_regno);
702 if (it != m_reg_map.end()) {
703 lldb_regno = it->second.lldb_regnum;
704 return true;
705 }
706 return false;
707 return false;
708}
709
710bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
711 uint8_t *data, size_t size, AddressRange &func_range,
712 UnwindPlan &unwind_plan) {
713 unwind_plan.Clear();
714
715 if (data == nullptr || size == 0)
716 return false;
717
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000718 if (!m_register_map_initialized)
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000719 return false;
720
721 addr_t current_func_text_offset = 0;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000722 int current_sp_bytes_offset_from_fa = 0;
723 bool is_aligned = false;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000724 UnwindPlan::Row::RegisterLocation initial_regloc;
725 UnwindPlan::RowSP row(new UnwindPlan::Row);
726
727 unwind_plan.SetPlanValidAddressRange(func_range);
728 unwind_plan.SetRegisterKind(eRegisterKindLLDB);
729
730 // At the start of the function, find the CFA by adding wordsize to the SP
731 // register
732 row->SetOffset(current_func_text_offset);
733 row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize);
734
735 // caller's stack pointer value before the call insn is the CFA address
736 initial_regloc.SetIsCFAPlusOffset(0);
737 row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
738
739 // saved instruction pointer can be found at CFA - wordsize.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000740 current_sp_bytes_offset_from_fa = m_wordsize;
741 initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000742 row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
743
744 unwind_plan.AppendRow(row);
745
746 // Allocate a new Row, populate it with the existing Row contents.
747 UnwindPlan::Row *newrow = new UnwindPlan::Row;
748 *newrow = *row.get();
749 row.reset(newrow);
750
Adrian Prantl05097242018-04-30 16:49:04 +0000751 // Track which registers have been saved so far in the prologue. If we see
752 // another push of that register, it's not part of the prologue. The register
753 // numbers used here are the machine register #'s (i386_register_numbers,
754 // x86_64_register_numbers).
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000755 std::vector<bool> saved_registers(32, false);
756
757 // Once the prologue has completed we'll save a copy of the unwind
Adrian Prantl05097242018-04-30 16:49:04 +0000758 // instructions If there is an epilogue in the middle of the function, after
759 // that epilogue we'll reinstate the unwind setup -- we assume that some code
760 // path jumps over the mid-function epilogue
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000761
762 UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
763 int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
764 // epilogue started executed
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000765 bool prologue_completed_is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000766 std::vector<bool> prologue_completed_saved_registers;
767
768 while (current_func_text_offset < size) {
769 int stack_offset, insn_len;
770 int machine_regno; // register numbers masked directly out of instructions
771 uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB
772 // numbering scheme
773
774 bool in_epilogue = false; // we're in the middle of an epilogue sequence
775 bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
776
777 m_cur_insn = data + current_func_text_offset;
Jason Molendaf6208042017-07-08 00:12:15 +0000778 if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset)
779 || insn_len == 0
780 || insn_len > kMaxInstructionByteSize) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000781 // An unrecognized/junk instruction
782 break;
783 }
784
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000785 auto &cfa_value = row->GetCFAValue();
786 auto &afa_value = row->GetAFAValue();
787 auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
788
789 if (mov_rsp_rbp_pattern_p()) {
790 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
791 fa_value_ptr->SetIsRegisterPlusOffset(
792 m_lldb_fp_regnum, fa_value_ptr->GetOffset());
793 row_updated = true;
794 }
795 }
796
797 else if (mov_rsp_rbx_pattern_p()) {
798 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
799 fa_value_ptr->SetIsRegisterPlusOffset(
800 m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
801 row_updated = true;
802 }
803 }
804
805 else if (and_rsp_pattern_p()) {
806 current_sp_bytes_offset_from_fa = 0;
807 afa_value.SetIsRegisterPlusOffset(
808 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
809 fa_value_ptr = &afa_value;
810 is_aligned = true;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000811 row_updated = true;
812 }
813
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000814 else if (mov_rbp_rsp_pattern_p()) {
815 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
816 {
817 is_aligned = false;
818 fa_value_ptr = &cfa_value;
819 afa_value.SetUnspecified();
820 row_updated = true;
821 }
822 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
823 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
824 }
825
826 else if (mov_rbx_rsp_pattern_p()) {
827 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
828 {
829 is_aligned = false;
830 fa_value_ptr = &cfa_value;
831 afa_value.SetUnspecified();
832 row_updated = true;
833 }
834 if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
835 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000836 }
837
838 // This is the start() function (or a pthread equivalent), it starts with a
Adrian Prantl05097242018-04-30 16:49:04 +0000839 // pushl $0x0 which puts the saved pc value of 0 on the stack. In this
840 // case we want to pretend we didn't see a stack movement at all --
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000841 // normally the saved pc value is already on the stack by the time the
842 // function starts executing.
843 else if (push_0_pattern_p()) {
844 }
845
846 else if (push_reg_p(machine_regno)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000847 current_sp_bytes_offset_from_fa += m_wordsize;
848 // the PUSH instruction has moved the stack pointer - if the FA is set
Adrian Prantl05097242018-04-30 16:49:04 +0000849 // in terms of the stack pointer, we need to add a new row of
850 // instructions.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000851 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
852 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000853 row_updated = true;
854 }
855 // record where non-volatile (callee-saved, spilled) registers are saved
856 // on the stack
857 if (nonvolatile_reg_p(machine_regno) &&
858 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000859 !saved_registers[machine_regno]) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000860 UnwindPlan::Row::RegisterLocation regloc;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000861 if (is_aligned)
862 regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
863 else
864 regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000865 row->SetRegisterInfo(lldb_regno, regloc);
866 saved_registers[machine_regno] = true;
867 row_updated = true;
868 }
869 }
870
871 else if (pop_reg_p(machine_regno)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000872 current_sp_bytes_offset_from_fa -= m_wordsize;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000873
874 if (nonvolatile_reg_p(machine_regno) &&
875 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000876 saved_registers[machine_regno]) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000877 saved_registers[machine_regno] = false;
878 row->RemoveRegisterInfo(lldb_regno);
879
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000880 if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
881 fa_value_ptr->SetIsRegisterPlusOffset(
882 m_lldb_sp_regnum, fa_value_ptr->GetOffset());
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000883 }
884
885 in_epilogue = true;
886 row_updated = true;
887 }
888
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000889 // the POP instruction has moved the stack pointer - if the FA is set in
Adrian Prantl05097242018-04-30 16:49:04 +0000890 // terms of the stack pointer, we need to add a new row of instructions.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000891 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
892 fa_value_ptr->SetIsRegisterPlusOffset(
893 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000894 row_updated = true;
895 }
896 }
897
Jason Molenda2630acc2016-10-04 05:10:06 +0000898 else if (pop_misc_reg_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000899 current_sp_bytes_offset_from_fa -= m_wordsize;
900 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
901 fa_value_ptr->SetIsRegisterPlusOffset(
902 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
Jason Molenda2630acc2016-10-04 05:10:06 +0000903 row_updated = true;
904 }
905 }
906
Adrian Prantl05097242018-04-30 16:49:04 +0000907 // The LEAVE instruction moves the value from rbp into rsp and pops a value
908 // off the stack into rbp (restoring the caller's rbp value). It is the
909 // opposite of ENTER, or 'push rbp, mov rsp rbp'.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000910 else if (leave_pattern_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000911 if (saved_registers[m_machine_fp_regnum]) {
912 saved_registers[m_machine_fp_regnum] = false;
913 row->RemoveRegisterInfo(m_lldb_fp_regnum);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000914
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000915 row_updated = true;
916 }
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000917
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000918 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
919 {
920 is_aligned = false;
921 fa_value_ptr = &cfa_value;
922 afa_value.SetUnspecified();
923 row_updated = true;
924 }
925
926 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
927 {
928 fa_value_ptr->SetIsRegisterPlusOffset(
929 m_lldb_sp_regnum, fa_value_ptr->GetOffset());
930
931 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
932 }
933
934 current_sp_bytes_offset_from_fa -= m_wordsize;
935
936 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
937 fa_value_ptr->SetIsRegisterPlusOffset(
938 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
939 row_updated = true;
940 }
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000941
942 in_epilogue = true;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000943 }
944
945 else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
946 nonvolatile_reg_p(machine_regno) &&
947 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000948 !saved_registers[machine_regno]) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000949 saved_registers[machine_regno] = true;
950
951 UnwindPlan::Row::RegisterLocation regloc;
952
Adrian Prantl05097242018-04-30 16:49:04 +0000953 // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000954 // want to express this as the offset from the FA. If the frame base is
955 // rbp (like the above instruction), the FA offset for rbp is probably
956 // 16. So we want to say that the value is stored at the FA address -
Adrian Prantl05097242018-04-30 16:49:04 +0000957 // 96.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000958 if (is_aligned)
959 regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
960 else
961 regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000962
963 row->SetRegisterInfo(lldb_regno, regloc);
964
965 row_updated = true;
966 }
967
968 else if (sub_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000969 current_sp_bytes_offset_from_fa += stack_offset;
970 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
971 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000972 row_updated = true;
973 }
974 }
975
976 else if (add_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 in_epilogue = true;
983 }
984
Jason Molenda2630acc2016-10-04 05:10:06 +0000985 else if (push_extended_pattern_p() || push_imm_pattern_p() ||
986 push_misc_reg_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000987 current_sp_bytes_offset_from_fa += m_wordsize;
988 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
989 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molendac0657a62016-10-01 00:19:26 +0000990 row_updated = true;
991 }
992 }
993
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000994 else if (lea_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000995 current_sp_bytes_offset_from_fa -= stack_offset;
996 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
997 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000998 row_updated = true;
999 }
1000 if (stack_offset > 0)
1001 in_epilogue = true;
1002 }
1003
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001004 else if (lea_rbp_rsp_pattern_p(stack_offset)) {
1005 if (is_aligned &&
1006 cfa_value.GetRegisterNumber() == m_lldb_fp_regnum) {
1007 is_aligned = false;
1008 fa_value_ptr = &cfa_value;
1009 afa_value.SetUnspecified();
1010 row_updated = true;
1011 }
1012 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
1013 current_sp_bytes_offset_from_fa =
1014 fa_value_ptr->GetOffset() - stack_offset;
1015 }
1016 }
1017
1018 else if (lea_rbx_rsp_pattern_p(stack_offset)) {
1019 if (is_aligned &&
1020 cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1021 is_aligned = false;
1022 fa_value_ptr = &cfa_value;
1023 afa_value.SetUnspecified();
1024 row_updated = true;
1025 }
1026 if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1027 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
1028 }
Pavel Labath89963462017-06-29 12:40:13 +00001029 }
1030
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001031 else if (ret_pattern_p() && prologue_completed_row.get()) {
Adrian Prantl05097242018-04-30 16:49:04 +00001032 // Reinstate the saved prologue setup for any instructions that come
1033 // after the ret instruction
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001034
1035 UnwindPlan::Row *newrow = new UnwindPlan::Row;
1036 *newrow = *prologue_completed_row.get();
1037 row.reset(newrow);
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001038 current_sp_bytes_offset_from_fa =
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001039 prologue_completed_sp_bytes_offset_from_cfa;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001040 is_aligned = prologue_completed_is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001041
1042 saved_registers.clear();
1043 saved_registers.resize(prologue_completed_saved_registers.size(), false);
1044 for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) {
1045 saved_registers[i] = prologue_completed_saved_registers[i];
1046 }
1047
1048 in_epilogue = true;
1049 row_updated = true;
1050 }
1051
1052 // call next instruction
1053 // call 0
1054 // => pop %ebx
1055 // This is used in i386 programs to get the PIC base address for finding
1056 // global data
1057 else if (call_next_insn_pattern_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001058 current_sp_bytes_offset_from_fa += m_wordsize;
1059 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1060 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001061 row_updated = true;
1062 }
1063 }
1064
1065 if (row_updated) {
1066 if (current_func_text_offset + insn_len < size) {
1067 row->SetOffset(current_func_text_offset + insn_len);
1068 unwind_plan.AppendRow(row);
1069 // Allocate a new Row, populate it with the existing Row contents.
1070 newrow = new UnwindPlan::Row;
1071 *newrow = *row.get();
1072 row.reset(newrow);
1073 }
1074 }
1075
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001076 if (!in_epilogue && row_updated) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001077 // If we're not in an epilogue sequence, save the updated Row
1078 UnwindPlan::Row *newrow = new UnwindPlan::Row;
1079 *newrow = *row.get();
1080 prologue_completed_row.reset(newrow);
1081
1082 prologue_completed_saved_registers.clear();
1083 prologue_completed_saved_registers.resize(saved_registers.size(), false);
1084 for (size_t i = 0; i < saved_registers.size(); ++i) {
1085 prologue_completed_saved_registers[i] = saved_registers[i];
1086 }
1087 }
1088
1089 // We may change the sp value without adding a new Row necessarily -- keep
1090 // track of it either way.
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001091 if (!in_epilogue) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001092 prologue_completed_sp_bytes_offset_from_cfa =
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001093 current_sp_bytes_offset_from_fa;
1094 prologue_completed_is_aligned = is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001095 }
1096
1097 m_cur_insn = m_cur_insn + insn_len;
1098 current_func_text_offset += insn_len;
1099 }
1100
1101 unwind_plan.SetSourceName("assembly insn profiling");
1102 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1103 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1104
1105 return true;
1106}
1107
1108bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
1109 uint8_t *data, size_t size, AddressRange &func_range,
1110 UnwindPlan &unwind_plan, RegisterContextSP &reg_ctx) {
1111 Address addr_start = func_range.GetBaseAddress();
1112 if (!addr_start.IsValid())
1113 return false;
1114
Adrian Prantl05097242018-04-30 16:49:04 +00001115 // We either need a live RegisterContext, or we need the UnwindPlan to
1116 // already be in the lldb register numbering scheme.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001117 if (reg_ctx.get() == nullptr &&
1118 unwind_plan.GetRegisterKind() != eRegisterKindLLDB)
1119 return false;
1120
1121 // Is original unwind_plan valid?
Adrian Prantl05097242018-04-30 16:49:04 +00001122 // unwind_plan should have at least one row which is ABI-default (CFA
1123 // register is sp), and another row in mid-function.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001124 if (unwind_plan.GetRowCount() < 2)
1125 return false;
1126
1127 UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex(0);
1128 if (first_row->GetOffset() != 0)
1129 return false;
1130 uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber();
1131 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1132 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1133 unwind_plan.GetRegisterKind(),
1134 first_row->GetCFAValue().GetRegisterNumber());
1135 }
1136 if (cfa_reg != m_lldb_sp_regnum ||
1137 first_row->GetCFAValue().GetOffset() != m_wordsize)
1138 return false;
1139
1140 UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset(-1);
1141
1142 size_t offset = 0;
1143 int row_id = 1;
1144 bool unwind_plan_updated = false;
1145 UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
1146 m_cur_insn = data + offset;
1147
Adrian Prantl05097242018-04-30 16:49:04 +00001148 // After a mid-function epilogue we will need to re-insert the original
1149 // unwind rules so unwinds work for the remainder of the function. These
1150 // aren't common with clang/gcc on x86 but it is possible.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001151 bool reinstate_unwind_state = false;
1152
1153 while (offset < size) {
1154 m_cur_insn = data + offset;
1155 int insn_len;
Jason Molendaf6208042017-07-08 00:12:15 +00001156 if (!instruction_length(m_cur_insn, insn_len, size - offset)
1157 || insn_len == 0
1158 || insn_len > kMaxInstructionByteSize) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001159 // An unrecognized/junk instruction.
1160 break;
1161 }
1162
1163 // Advance offsets.
1164 offset += insn_len;
1165 m_cur_insn = data + offset;
1166
Adrian Prantl05097242018-04-30 16:49:04 +00001167 // offset is pointing beyond the bounds of the function; stop looping.
Jason Molendab8ebcb52017-03-02 05:08:10 +00001168 if (offset >= size)
1169 continue;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001170
Jason Molendab8ebcb52017-03-02 05:08:10 +00001171 if (reinstate_unwind_state) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001172 UnwindPlan::RowSP new_row(new UnwindPlan::Row());
1173 *new_row = *original_last_row;
1174 new_row->SetOffset(offset);
1175 unwind_plan.AppendRow(new_row);
1176 row.reset(new UnwindPlan::Row());
1177 *row = *new_row;
1178 reinstate_unwind_state = false;
1179 unwind_plan_updated = true;
1180 continue;
1181 }
1182
1183 // If we already have one row for this instruction, we can continue.
1184 while (row_id < unwind_plan.GetRowCount() &&
1185 unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) {
1186 row_id++;
1187 }
1188 UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex(row_id - 1);
1189 if (original_row->GetOffset() == offset) {
1190 *row = *original_row;
1191 continue;
1192 }
1193
1194 if (row_id == 0) {
Adrian Prantl05097242018-04-30 16:49:04 +00001195 // If we are here, compiler didn't generate CFI for prologue. This won't
1196 // happen to GCC or clang. In this case, bail out directly.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001197 return false;
1198 }
1199
1200 // Inspect the instruction to check if we need a new row for it.
1201 cfa_reg = row->GetCFAValue().GetRegisterNumber();
1202 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1203 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1204 unwind_plan.GetRegisterKind(),
1205 row->GetCFAValue().GetRegisterNumber());
1206 }
1207 if (cfa_reg == m_lldb_sp_regnum) {
1208 // CFA register is sp.
1209
1210 // call next instruction
1211 // call 0
1212 // => pop %ebx
1213 if (call_next_insn_pattern_p()) {
1214 row->SetOffset(offset);
1215 row->GetCFAValue().IncOffset(m_wordsize);
1216
1217 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1218 unwind_plan.InsertRow(new_row);
1219 unwind_plan_updated = true;
1220 continue;
1221 }
1222
1223 // push/pop register
1224 int regno;
1225 if (push_reg_p(regno)) {
1226 row->SetOffset(offset);
1227 row->GetCFAValue().IncOffset(m_wordsize);
1228
1229 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1230 unwind_plan.InsertRow(new_row);
1231 unwind_plan_updated = true;
1232 continue;
1233 }
1234 if (pop_reg_p(regno)) {
1235 // Technically, this might be a nonvolatile register recover in
Adrian Prantl05097242018-04-30 16:49:04 +00001236 // epilogue. We should reset RegisterInfo for the register. But in
1237 // practice, previous rule for the register is still valid... So we
1238 // ignore this case.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001239
1240 row->SetOffset(offset);
1241 row->GetCFAValue().IncOffset(-m_wordsize);
1242
1243 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1244 unwind_plan.InsertRow(new_row);
1245 unwind_plan_updated = true;
1246 continue;
1247 }
1248
Jason Molenda2630acc2016-10-04 05:10:06 +00001249 if (pop_misc_reg_p()) {
1250 row->SetOffset(offset);
1251 row->GetCFAValue().IncOffset(-m_wordsize);
1252
1253 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1254 unwind_plan.InsertRow(new_row);
1255 unwind_plan_updated = true;
1256 continue;
1257 }
1258
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001259 // push imm
1260 if (push_imm_pattern_p()) {
1261 row->SetOffset(offset);
1262 row->GetCFAValue().IncOffset(m_wordsize);
1263 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1264 unwind_plan.InsertRow(new_row);
1265 unwind_plan_updated = true;
1266 continue;
1267 }
1268
Jason Molendac0657a62016-10-01 00:19:26 +00001269 // push extended
Jason Molenda2630acc2016-10-04 05:10:06 +00001270 if (push_extended_pattern_p() || push_misc_reg_p()) {
Jason Molendac0657a62016-10-01 00:19:26 +00001271 row->SetOffset(offset);
1272 row->GetCFAValue().IncOffset(m_wordsize);
1273 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1274 unwind_plan.InsertRow(new_row);
1275 unwind_plan_updated = true;
1276 continue;
1277 }
1278
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001279 // add/sub %rsp/%esp
1280 int amount;
1281 if (add_rsp_pattern_p(amount)) {
1282 row->SetOffset(offset);
1283 row->GetCFAValue().IncOffset(-amount);
1284
1285 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1286 unwind_plan.InsertRow(new_row);
1287 unwind_plan_updated = true;
1288 continue;
1289 }
1290 if (sub_rsp_pattern_p(amount)) {
1291 row->SetOffset(offset);
1292 row->GetCFAValue().IncOffset(amount);
1293
1294 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1295 unwind_plan.InsertRow(new_row);
1296 unwind_plan_updated = true;
1297 continue;
1298 }
1299
1300 // lea %rsp, [%rsp + $offset]
1301 if (lea_rsp_pattern_p(amount)) {
1302 row->SetOffset(offset);
1303 row->GetCFAValue().IncOffset(-amount);
1304
1305 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1306 unwind_plan.InsertRow(new_row);
1307 unwind_plan_updated = true;
1308 continue;
1309 }
1310
1311 if (ret_pattern_p()) {
1312 reinstate_unwind_state = true;
1313 continue;
1314 }
1315 } else if (cfa_reg == m_lldb_fp_regnum) {
1316 // CFA register is fp.
1317
1318 // The only case we care about is epilogue:
1319 // [0x5d] pop %rbp/%ebp
1320 // => [0xc3] ret
1321 if (pop_rbp_pattern_p() || leave_pattern_p()) {
Jason Molendac0657a62016-10-01 00:19:26 +00001322 offset += 1;
1323 row->SetOffset(offset);
1324 row->GetCFAValue().SetIsRegisterPlusOffset(
1325 first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001326
Jason Molendac0657a62016-10-01 00:19:26 +00001327 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1328 unwind_plan.InsertRow(new_row);
1329 unwind_plan_updated = true;
1330 reinstate_unwind_state = true;
1331 continue;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001332 }
1333 } else {
1334 // CFA register is not sp or fp.
1335
1336 // This must be hand-written assembly.
1337 // Just trust eh_frame and assume we have finished.
1338 break;
1339 }
1340 }
1341
1342 unwind_plan.SetPlanValidAddressRange(func_range);
1343 if (unwind_plan_updated) {
1344 std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString());
1345 unwind_plan_source += " plus augmentation from assembly parsing";
1346 unwind_plan.SetSourceName(unwind_plan_source.c_str());
1347 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1348 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1349 }
1350 return true;
1351}
1352
1353bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
1354 uint8_t *data, size_t size, size_t &offset) {
1355 offset = 0;
1356
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001357 if (!m_register_map_initialized)
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001358 return false;
1359
1360 while (offset < size) {
1361 int regno;
1362 int insn_len;
1363 int scratch;
1364
1365 m_cur_insn = data + offset;
Jason Molendaf6208042017-07-08 00:12:15 +00001366 if (!instruction_length(m_cur_insn, insn_len, size - offset)
1367 || insn_len > kMaxInstructionByteSize
1368 || insn_len == 0) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001369 // An error parsing the instruction, i.e. probably data/garbage - stop
1370 // scanning
1371 break;
1372 }
1373
1374 if (push_rbp_pattern_p() || mov_rsp_rbp_pattern_p() ||
1375 sub_rsp_pattern_p(scratch) || push_reg_p(regno) ||
1376 mov_reg_to_local_stack_frame_p(regno, scratch) ||
1377 (lea_rsp_pattern_p(scratch) && offset == 0)) {
1378 offset += insn_len;
1379 continue;
1380 }
1381 //
1382 // Unknown non-prologue instruction - stop scanning
1383 break;
1384 }
1385
1386 return true;
1387}