blob: 8037095a825b192e97208964ff5155de7a255563 [file] [log] [blame]
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001//===-- x86AssemblyInspectionEngine.cpp -------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jason Molenda74b8fbc2016-09-29 01:00:16 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "x86AssemblyInspectionEngine.h"
10
11#include "llvm-c/Disassembler.h"
12
13#include "lldb/Core/Address.h"
14#include "lldb/Symbol/UnwindPlan.h"
15#include "lldb/Target/RegisterContext.h"
16#include "lldb/Target/UnwindAssembly.h"
17
18using namespace lldb_private;
19using namespace lldb;
20
21x86AssemblyInspectionEngine::x86AssemblyInspectionEngine(const ArchSpec &arch)
22 : m_cur_insn(nullptr), m_machine_ip_regnum(LLDB_INVALID_REGNUM),
23 m_machine_sp_regnum(LLDB_INVALID_REGNUM),
24 m_machine_fp_regnum(LLDB_INVALID_REGNUM),
25 m_lldb_ip_regnum(LLDB_INVALID_REGNUM),
26 m_lldb_sp_regnum(LLDB_INVALID_REGNUM),
27 m_lldb_fp_regnum(LLDB_INVALID_REGNUM),
28
29 m_reg_map(), m_arch(arch), m_cpu(k_cpu_unspecified), m_wordsize(-1),
30 m_register_map_initialized(false), m_disasm_context() {
Jason Molendac0657a62016-10-01 00:19:26 +000031 m_disasm_context =
32 ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr,
33 /*TagType=*/1, nullptr, nullptr);
Jason Molenda74b8fbc2016-09-29 01:00:16 +000034}
35
36x86AssemblyInspectionEngine::~x86AssemblyInspectionEngine() {
37 ::LLVMDisasmDispose(m_disasm_context);
38}
39
40void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
41 m_cpu = k_cpu_unspecified;
42 m_wordsize = -1;
43 m_register_map_initialized = false;
44
45 const llvm::Triple::ArchType cpu = m_arch.GetMachine();
46 if (cpu == llvm::Triple::x86)
47 m_cpu = k_i386;
48 else if (cpu == llvm::Triple::x86_64)
49 m_cpu = k_x86_64;
50
51 if (m_cpu == k_cpu_unspecified)
52 return;
53
54 if (reg_ctx.get() == nullptr)
55 return;
56
57 if (m_cpu == k_i386) {
58 m_machine_ip_regnum = k_machine_eip;
59 m_machine_sp_regnum = k_machine_esp;
60 m_machine_fp_regnum = k_machine_ebp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000061 m_machine_alt_fp_regnum = k_machine_ebx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +000062 m_wordsize = 4;
63
64 struct lldb_reg_info reginfo;
65 reginfo.name = "eax";
66 m_reg_map[k_machine_eax] = reginfo;
67 reginfo.name = "edx";
68 m_reg_map[k_machine_edx] = reginfo;
69 reginfo.name = "esp";
70 m_reg_map[k_machine_esp] = reginfo;
71 reginfo.name = "esi";
72 m_reg_map[k_machine_esi] = reginfo;
73 reginfo.name = "eip";
74 m_reg_map[k_machine_eip] = reginfo;
75 reginfo.name = "ecx";
76 m_reg_map[k_machine_ecx] = reginfo;
77 reginfo.name = "ebx";
78 m_reg_map[k_machine_ebx] = reginfo;
79 reginfo.name = "ebp";
80 m_reg_map[k_machine_ebp] = reginfo;
81 reginfo.name = "edi";
82 m_reg_map[k_machine_edi] = reginfo;
83 } else {
84 m_machine_ip_regnum = k_machine_rip;
85 m_machine_sp_regnum = k_machine_rsp;
86 m_machine_fp_regnum = k_machine_rbp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000087 m_machine_alt_fp_regnum = k_machine_rbx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +000088 m_wordsize = 8;
89
90 struct lldb_reg_info reginfo;
91 reginfo.name = "rax";
92 m_reg_map[k_machine_rax] = reginfo;
93 reginfo.name = "rdx";
94 m_reg_map[k_machine_rdx] = reginfo;
95 reginfo.name = "rsp";
96 m_reg_map[k_machine_rsp] = reginfo;
97 reginfo.name = "rsi";
98 m_reg_map[k_machine_rsi] = reginfo;
99 reginfo.name = "r8";
100 m_reg_map[k_machine_r8] = reginfo;
101 reginfo.name = "r10";
102 m_reg_map[k_machine_r10] = reginfo;
103 reginfo.name = "r12";
104 m_reg_map[k_machine_r12] = reginfo;
105 reginfo.name = "r14";
106 m_reg_map[k_machine_r14] = reginfo;
107 reginfo.name = "rip";
108 m_reg_map[k_machine_rip] = reginfo;
109 reginfo.name = "rcx";
110 m_reg_map[k_machine_rcx] = reginfo;
111 reginfo.name = "rbx";
112 m_reg_map[k_machine_rbx] = reginfo;
113 reginfo.name = "rbp";
114 m_reg_map[k_machine_rbp] = reginfo;
115 reginfo.name = "rdi";
116 m_reg_map[k_machine_rdi] = reginfo;
117 reginfo.name = "r9";
118 m_reg_map[k_machine_r9] = reginfo;
119 reginfo.name = "r11";
120 m_reg_map[k_machine_r11] = reginfo;
121 reginfo.name = "r13";
122 m_reg_map[k_machine_r13] = reginfo;
123 reginfo.name = "r15";
124 m_reg_map[k_machine_r15] = reginfo;
125 }
126
127 for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin();
128 it != m_reg_map.end(); ++it) {
129 const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName(it->second.name);
130 if (ri)
131 it->second.lldb_regnum = ri->kinds[eRegisterKindLLDB];
132 }
133
134 uint32_t lldb_regno;
135 if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno))
136 m_lldb_sp_regnum = lldb_regno;
137 if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
138 m_lldb_fp_regnum = lldb_regno;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000139 if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
140 m_lldb_alt_fp_regnum = lldb_regno;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000141 if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
142 m_lldb_ip_regnum = lldb_regno;
143
144 m_register_map_initialized = true;
145}
146
147void x86AssemblyInspectionEngine::Initialize(
148 std::vector<lldb_reg_info> &reg_info) {
149 m_cpu = k_cpu_unspecified;
150 m_wordsize = -1;
151 m_register_map_initialized = false;
152
153 const llvm::Triple::ArchType cpu = m_arch.GetMachine();
154 if (cpu == llvm::Triple::x86)
155 m_cpu = k_i386;
156 else if (cpu == llvm::Triple::x86_64)
157 m_cpu = k_x86_64;
158
159 if (m_cpu == k_cpu_unspecified)
160 return;
161
162 if (m_cpu == k_i386) {
163 m_machine_ip_regnum = k_machine_eip;
164 m_machine_sp_regnum = k_machine_esp;
165 m_machine_fp_regnum = k_machine_ebp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000166 m_machine_alt_fp_regnum = k_machine_ebx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000167 m_wordsize = 4;
168
169 struct lldb_reg_info reginfo;
170 reginfo.name = "eax";
171 m_reg_map[k_machine_eax] = reginfo;
172 reginfo.name = "edx";
173 m_reg_map[k_machine_edx] = reginfo;
174 reginfo.name = "esp";
175 m_reg_map[k_machine_esp] = reginfo;
176 reginfo.name = "esi";
177 m_reg_map[k_machine_esi] = reginfo;
178 reginfo.name = "eip";
179 m_reg_map[k_machine_eip] = reginfo;
180 reginfo.name = "ecx";
181 m_reg_map[k_machine_ecx] = reginfo;
182 reginfo.name = "ebx";
183 m_reg_map[k_machine_ebx] = reginfo;
184 reginfo.name = "ebp";
185 m_reg_map[k_machine_ebp] = reginfo;
186 reginfo.name = "edi";
187 m_reg_map[k_machine_edi] = reginfo;
188 } else {
189 m_machine_ip_regnum = k_machine_rip;
190 m_machine_sp_regnum = k_machine_rsp;
191 m_machine_fp_regnum = k_machine_rbp;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000192 m_machine_alt_fp_regnum = k_machine_rbx;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000193 m_wordsize = 8;
194
195 struct lldb_reg_info reginfo;
196 reginfo.name = "rax";
197 m_reg_map[k_machine_rax] = reginfo;
198 reginfo.name = "rdx";
199 m_reg_map[k_machine_rdx] = reginfo;
200 reginfo.name = "rsp";
201 m_reg_map[k_machine_rsp] = reginfo;
202 reginfo.name = "rsi";
203 m_reg_map[k_machine_rsi] = reginfo;
204 reginfo.name = "r8";
205 m_reg_map[k_machine_r8] = reginfo;
206 reginfo.name = "r10";
207 m_reg_map[k_machine_r10] = reginfo;
208 reginfo.name = "r12";
209 m_reg_map[k_machine_r12] = reginfo;
210 reginfo.name = "r14";
211 m_reg_map[k_machine_r14] = reginfo;
212 reginfo.name = "rip";
213 m_reg_map[k_machine_rip] = reginfo;
214 reginfo.name = "rcx";
215 m_reg_map[k_machine_rcx] = reginfo;
216 reginfo.name = "rbx";
217 m_reg_map[k_machine_rbx] = reginfo;
218 reginfo.name = "rbp";
219 m_reg_map[k_machine_rbp] = reginfo;
220 reginfo.name = "rdi";
221 m_reg_map[k_machine_rdi] = reginfo;
222 reginfo.name = "r9";
223 m_reg_map[k_machine_r9] = reginfo;
224 reginfo.name = "r11";
225 m_reg_map[k_machine_r11] = reginfo;
226 reginfo.name = "r13";
227 m_reg_map[k_machine_r13] = reginfo;
228 reginfo.name = "r15";
229 m_reg_map[k_machine_r15] = reginfo;
230 }
231
232 for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin();
233 it != m_reg_map.end(); ++it) {
234 for (size_t i = 0; i < reg_info.size(); ++i) {
235 if (::strcmp(reg_info[i].name, it->second.name) == 0) {
236 it->second.lldb_regnum = reg_info[i].lldb_regnum;
237 break;
238 }
239 }
240 }
241
242 uint32_t lldb_regno;
243 if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno))
244 m_lldb_sp_regnum = lldb_regno;
245 if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
246 m_lldb_fp_regnum = lldb_regno;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000247 if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
248 m_lldb_alt_fp_regnum = lldb_regno;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000249 if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
250 m_lldb_ip_regnum = lldb_regno;
251
252 m_register_map_initialized = true;
253}
254
255// This function expects an x86 native register number (i.e. the bits stripped
Adrian Prantl05097242018-04-30 16:49:04 +0000256// out of the actual instruction), not an lldb register number.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000257//
258// FIXME: This is ABI dependent, it shouldn't be hardcoded here.
259
260bool x86AssemblyInspectionEngine::nonvolatile_reg_p(int machine_regno) {
261 if (m_cpu == k_i386) {
262 switch (machine_regno) {
263 case k_machine_ebx:
264 case k_machine_ebp: // not actually a nonvolatile but often treated as such
265 // by convention
266 case k_machine_esi:
267 case k_machine_edi:
268 case k_machine_esp:
269 return true;
270 default:
271 return false;
272 }
273 }
274 if (m_cpu == k_x86_64) {
275 switch (machine_regno) {
276 case k_machine_rbx:
277 case k_machine_rsp:
278 case k_machine_rbp: // not actually a nonvolatile but often treated as such
279 // by convention
280 case k_machine_r12:
281 case k_machine_r13:
282 case k_machine_r14:
283 case k_machine_r15:
284 return true;
285 default:
286 return false;
287 }
288 }
289 return false;
290}
291
292// Macro to detect if this is a REX mode prefix byte.
293#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
294
295// The high bit which should be added to the source register number (the "R"
296// bit)
297#define REX_W_SRCREG(opcode) (((opcode)&0x4) >> 2)
298
299// The high bit which should be added to the destination register number (the
300// "B" bit)
301#define REX_W_DSTREG(opcode) ((opcode)&0x1)
302
303// pushq %rbp [0x55]
304bool x86AssemblyInspectionEngine::push_rbp_pattern_p() {
305 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000306 return *p == 0x55;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000307}
308
309// pushq $0 ; the first instruction in start() [0x6a 0x00]
310bool x86AssemblyInspectionEngine::push_0_pattern_p() {
311 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000312 return *p == 0x6a && *(p + 1) == 0x0;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000313}
314
315// pushq $0
316// pushl $0
317bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
318 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000319 return *p == 0x68 || *p == 0x6a;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000320}
321
Jason Molendac0657a62016-10-01 00:19:26 +0000322// pushl imm8(%esp)
323//
Adrian Prantl05097242018-04-30 16:49:04 +0000324// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' (same byte pattern for 'pushq
325// 0x20(%rsp)' in an x86_64 program)
Jason Molendac0657a62016-10-01 00:19:26 +0000326//
Adrian Prantl05097242018-04-30 16:49:04 +0000327// 0xff (with opcode bits '6' in next byte, PUSH r/m32) 0x74 (ModR/M byte with
328// three bits used to specify the opcode)
Jason Molendac0657a62016-10-01 00:19:26 +0000329// mod == b01, opcode == b110, R/M == b100
330// "+disp8"
Adrian Prantl05097242018-04-30 16:49:04 +0000331// 0x24 (SIB byte - scaled index = 0, r32 == esp) 0x20 imm8 value
Jason Molendac0657a62016-10-01 00:19:26 +0000332
333bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
334 if (*m_cur_insn == 0xff) {
335 // Get the 3 opcode bits from the ModR/M byte
336 uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
337 if (opcode == 6) {
338 // I'm only looking for 0xff /6 here - I
Adrian Prantl05097242018-04-30 16:49:04 +0000339 // don't really care what value is being pushed, just that we're pushing
340 // a 32/64 bit value on to the stack is enough.
Jason Molendac0657a62016-10-01 00:19:26 +0000341 return true;
342 }
343 }
344 return false;
345}
346
Jason Molenda2630acc2016-10-04 05:10:06 +0000347// instructions only valid in 32-bit mode:
348// 0x0e - push cs
349// 0x16 - push ss
350// 0x1e - push ds
351// 0x06 - push es
352bool x86AssemblyInspectionEngine::push_misc_reg_p() {
353 uint8_t p = *m_cur_insn;
354 if (m_wordsize == 4) {
355 if (p == 0x0e || p == 0x16 || p == 0x1e || p == 0x06)
356 return true;
357 }
358 return false;
359}
360
Jason Molendac0657a62016-10-01 00:19:26 +0000361// pushq %rbx
362// pushl %ebx
363bool x86AssemblyInspectionEngine::push_reg_p(int &regno) {
364 uint8_t *p = m_cur_insn;
365 int regno_prefix_bit = 0;
366 // If we have a rex prefix byte, check to see if a B bit is set
367 if (m_wordsize == 8 && *p == 0x41) {
368 regno_prefix_bit = 1 << 3;
369 p++;
370 }
371 if (*p >= 0x50 && *p <= 0x57) {
372 regno = (*p - 0x50) | regno_prefix_bit;
373 return true;
374 }
375 return false;
376}
377
Adrian Prantl05097242018-04-30 16:49:04 +0000378// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] movl %esp, %ebp [0x8b
379// 0xec] or [0x89 0xe5]
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000380bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
381 uint8_t *p = m_cur_insn;
382 if (m_wordsize == 8 && *p == 0x48)
383 p++;
384 if (*(p) == 0x8b && *(p + 1) == 0xec)
385 return true;
386 if (*(p) == 0x89 && *(p + 1) == 0xe5)
387 return true;
388 return false;
389}
390
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000391// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
392// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
393bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
394 uint8_t *p = m_cur_insn;
395 if (m_wordsize == 8 && *p == 0x48)
396 p++;
397 if (*(p) == 0x8b && *(p + 1) == 0xdc)
398 return true;
399 if (*(p) == 0x89 && *(p + 1) == 0xe3)
400 return true;
401 return false;
402}
403
404// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
405// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
406bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
407 uint8_t *p = m_cur_insn;
408 if (m_wordsize == 8 && *p == 0x48)
409 p++;
410 if (*(p) == 0x8b && *(p + 1) == 0xe5)
411 return true;
412 if (*(p) == 0x89 && *(p + 1) == 0xec)
413 return true;
414 return false;
415}
416
417// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
418// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
419bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
420 uint8_t *p = m_cur_insn;
421 if (m_wordsize == 8 && *p == 0x48)
422 p++;
423 if (*(p) == 0x8b && *(p + 1) == 0xe3)
424 return true;
425 if (*(p) == 0x89 && *(p + 1) == 0xdc)
426 return true;
427 return false;
428}
429
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000430// subq $0x20, %rsp
431bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
432 uint8_t *p = m_cur_insn;
433 if (m_wordsize == 8 && *p == 0x48)
434 p++;
435 // 8-bit immediate operand
436 if (*p == 0x83 && *(p + 1) == 0xec) {
437 amount = (int8_t) * (p + 2);
438 return true;
439 }
440 // 32-bit immediate operand
441 if (*p == 0x81 && *(p + 1) == 0xec) {
442 amount = (int32_t)extract_4(p + 2);
443 return true;
444 }
445 return false;
446}
447
448// addq $0x20, %rsp
449bool x86AssemblyInspectionEngine::add_rsp_pattern_p(int &amount) {
450 uint8_t *p = m_cur_insn;
451 if (m_wordsize == 8 && *p == 0x48)
452 p++;
453 // 8-bit immediate operand
454 if (*p == 0x83 && *(p + 1) == 0xc4) {
455 amount = (int8_t) * (p + 2);
456 return true;
457 }
458 // 32-bit immediate operand
459 if (*p == 0x81 && *(p + 1) == 0xc4) {
460 amount = (int32_t)extract_4(p + 2);
461 return true;
462 }
463 return false;
464}
465
466// lea esp, [esp - 0x28]
467// lea esp, [esp + 0x28]
468bool x86AssemblyInspectionEngine::lea_rsp_pattern_p(int &amount) {
469 uint8_t *p = m_cur_insn;
470 if (m_wordsize == 8 && *p == 0x48)
471 p++;
472
473 // Check opcode
474 if (*p != 0x8d)
475 return false;
476
477 // 8 bit displacement
478 if (*(p + 1) == 0x64 && (*(p + 2) & 0x3f) == 0x24) {
479 amount = (int8_t) * (p + 3);
480 return true;
481 }
482
483 // 32 bit displacement
484 if (*(p + 1) == 0xa4 && (*(p + 2) & 0x3f) == 0x24) {
485 amount = (int32_t)extract_4(p + 3);
486 return true;
487 }
488
489 return false;
490}
491
Pavel Labath89963462017-06-29 12:40:13 +0000492// lea -0x28(%ebp), %esp
493// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
494bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) {
495 uint8_t *p = m_cur_insn;
496 if (m_wordsize == 8 && *p == 0x48)
497 p++;
498
499 // Check opcode
500 if (*p != 0x8d)
501 return false;
502 ++p;
503
504 // 8 bit displacement
505 if (*p == 0x65) {
506 amount = (int8_t)p[1];
507 return true;
508 }
509
510 // 32 bit displacement
511 if (*p == 0xa5) {
512 amount = (int32_t)extract_4(p + 1);
513 return true;
514 }
515
516 return false;
517}
518
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000519// lea -0x28(%ebx), %esp
520// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
521bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
522 uint8_t *p = m_cur_insn;
523 if (m_wordsize == 8 && *p == 0x48)
524 p++;
525
526 // Check opcode
527 if (*p != 0x8d)
528 return false;
529 ++p;
530
531 // 8 bit displacement
532 if (*p == 0x63) {
533 amount = (int8_t)p[1];
534 return true;
535 }
536
537 // 32 bit displacement
538 if (*p == 0xa3) {
539 amount = (int32_t)extract_4(p + 1);
540 return true;
541 }
542
543 return false;
544}
545
546// and -0xfffffff0, %esp
547// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
548bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
549 uint8_t *p = m_cur_insn;
550 if (m_wordsize == 8 && *p == 0x48)
551 p++;
552
553 if (*p != 0x81 && *p != 0x83)
554 return false;
555
556 return *++p == 0xe4;
557}
558
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000559// popq %rbx
560// popl %ebx
561bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
562 uint8_t *p = m_cur_insn;
563 int regno_prefix_bit = 0;
564 // If we have a rex prefix byte, check to see if a B bit is set
565 if (m_wordsize == 8 && *p == 0x41) {
566 regno_prefix_bit = 1 << 3;
567 p++;
568 }
569 if (*p >= 0x58 && *p <= 0x5f) {
570 regno = (*p - 0x58) | regno_prefix_bit;
571 return true;
572 }
573 return false;
574}
575
576// popq %rbp [0x5d]
577// popl %ebp [0x5d]
578bool x86AssemblyInspectionEngine::pop_rbp_pattern_p() {
579 uint8_t *p = m_cur_insn;
580 return (*p == 0x5d);
581}
582
Jason Molenda2630acc2016-10-04 05:10:06 +0000583// instructions valid only in 32-bit mode:
584// 0x1f - pop ds
585// 0x07 - pop es
586// 0x17 - pop ss
587bool x86AssemblyInspectionEngine::pop_misc_reg_p() {
588 uint8_t p = *m_cur_insn;
589 if (m_wordsize == 4) {
590 if (p == 0x1f || p == 0x07 || p == 0x17)
591 return true;
592 }
593 return false;
594}
595
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000596// leave [0xc9]
597bool x86AssemblyInspectionEngine::leave_pattern_p() {
598 uint8_t *p = m_cur_insn;
599 return (*p == 0xc9);
600}
601
602// call $0 [0xe8 0x0 0x0 0x0 0x0]
603bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() {
604 uint8_t *p = m_cur_insn;
605 return (*p == 0xe8) && (*(p + 1) == 0x0) && (*(p + 2) == 0x0) &&
606 (*(p + 3) == 0x0) && (*(p + 4) == 0x0);
607}
608
Adrian Prantl05097242018-04-30 16:49:04 +0000609// Look for an instruction sequence storing a nonvolatile register on to the
610// stack frame.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000611
612// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
613// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
614
Adrian Prantl05097242018-04-30 16:49:04 +0000615// The offset value returned in rbp_offset will be positive -- but it must be
616// subtraced from the frame base register to get the actual location. The
617// positive value returned for the offset is a convention used elsewhere for
618// CFA offsets et al.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000619
620bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
621 int &regno, int &rbp_offset) {
622 uint8_t *p = m_cur_insn;
623 int src_reg_prefix_bit = 0;
624 int target_reg_prefix_bit = 0;
625
626 if (m_wordsize == 8 && REX_W_PREFIX_P(*p)) {
627 src_reg_prefix_bit = REX_W_SRCREG(*p) << 3;
628 target_reg_prefix_bit = REX_W_DSTREG(*p) << 3;
629 if (target_reg_prefix_bit == 1) {
Adrian Prantl05097242018-04-30 16:49:04 +0000630 // rbp/ebp don't need a prefix bit - we know this isn't the reg we care
631 // about.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000632 return false;
633 }
634 p++;
635 }
636
637 if (*p == 0x89) {
638 /* Mask off the 3-5 bits which indicate the destination register
639 if this is a ModR/M byte. */
640 int opcode_destreg_masked_out = *(p + 1) & (~0x38);
641
642 /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
643 and three bits between them, e.g. 01nnn101
644 We're looking for a destination of ebp-disp8 or ebp-disp32. */
645 int immsize;
646 if (opcode_destreg_masked_out == 0x45)
647 immsize = 2;
648 else if (opcode_destreg_masked_out == 0x85)
649 immsize = 4;
650 else
651 return false;
652
653 int offset = 0;
654 if (immsize == 2)
655 offset = (int8_t) * (p + 2);
656 if (immsize == 4)
657 offset = (uint32_t)extract_4(p + 2);
658 if (offset > 0)
659 return false;
660
661 regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
662 rbp_offset = offset > 0 ? offset : -offset;
663 return true;
664 }
665 return false;
666}
667
668// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
669bool x86AssemblyInspectionEngine::ret_pattern_p() {
670 uint8_t *p = m_cur_insn;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000671 return *p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000672}
673
674uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) {
675 uint32_t v = 0;
676 for (int i = 3; i >= 0; i--)
677 v = (v << 8) | b[i];
678 return v;
679}
680
681bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p,
Jason Molendaf6208042017-07-08 00:12:15 +0000682 int &length,
683 uint32_t buffer_remaining_bytes) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000684
Jason Molendaf6208042017-07-08 00:12:15 +0000685 uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize());
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000686 llvm::SmallVector<uint8_t, 32> opcode_data;
687 opcode_data.resize(max_op_byte_size);
688
689 char out_string[512];
690 const size_t inst_size =
691 ::LLVMDisasmInstruction(m_disasm_context, insn_p, max_op_byte_size, 0,
692 out_string, sizeof(out_string));
693
694 length = inst_size;
695 return true;
696}
697
698bool x86AssemblyInspectionEngine::machine_regno_to_lldb_regno(
699 int machine_regno, uint32_t &lldb_regno) {
700 MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.find(machine_regno);
701 if (it != m_reg_map.end()) {
702 lldb_regno = it->second.lldb_regnum;
703 return true;
704 }
705 return false;
706 return false;
707}
708
709bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
710 uint8_t *data, size_t size, AddressRange &func_range,
711 UnwindPlan &unwind_plan) {
712 unwind_plan.Clear();
713
714 if (data == nullptr || size == 0)
715 return false;
716
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000717 if (!m_register_map_initialized)
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000718 return false;
719
720 addr_t current_func_text_offset = 0;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000721 int current_sp_bytes_offset_from_fa = 0;
722 bool is_aligned = false;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000723 UnwindPlan::Row::RegisterLocation initial_regloc;
724 UnwindPlan::RowSP row(new UnwindPlan::Row);
725
726 unwind_plan.SetPlanValidAddressRange(func_range);
727 unwind_plan.SetRegisterKind(eRegisterKindLLDB);
728
729 // At the start of the function, find the CFA by adding wordsize to the SP
730 // register
731 row->SetOffset(current_func_text_offset);
732 row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize);
733
734 // caller's stack pointer value before the call insn is the CFA address
735 initial_regloc.SetIsCFAPlusOffset(0);
736 row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
737
738 // saved instruction pointer can be found at CFA - wordsize.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000739 current_sp_bytes_offset_from_fa = m_wordsize;
740 initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000741 row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
742
743 unwind_plan.AppendRow(row);
744
745 // Allocate a new Row, populate it with the existing Row contents.
746 UnwindPlan::Row *newrow = new UnwindPlan::Row;
747 *newrow = *row.get();
748 row.reset(newrow);
749
Adrian Prantl05097242018-04-30 16:49:04 +0000750 // Track which registers have been saved so far in the prologue. If we see
751 // another push of that register, it's not part of the prologue. The register
752 // numbers used here are the machine register #'s (i386_register_numbers,
753 // x86_64_register_numbers).
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000754 std::vector<bool> saved_registers(32, false);
755
756 // Once the prologue has completed we'll save a copy of the unwind
Adrian Prantl05097242018-04-30 16:49:04 +0000757 // instructions If there is an epilogue in the middle of the function, after
758 // that epilogue we'll reinstate the unwind setup -- we assume that some code
759 // path jumps over the mid-function epilogue
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000760
761 UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
762 int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
763 // epilogue started executed
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000764 bool prologue_completed_is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000765 std::vector<bool> prologue_completed_saved_registers;
766
767 while (current_func_text_offset < size) {
768 int stack_offset, insn_len;
769 int machine_regno; // register numbers masked directly out of instructions
770 uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB
771 // numbering scheme
772
773 bool in_epilogue = false; // we're in the middle of an epilogue sequence
774 bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
775
776 m_cur_insn = data + current_func_text_offset;
Jason Molendaf6208042017-07-08 00:12:15 +0000777 if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset)
778 || insn_len == 0
779 || insn_len > kMaxInstructionByteSize) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000780 // An unrecognized/junk instruction
781 break;
782 }
783
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000784 auto &cfa_value = row->GetCFAValue();
785 auto &afa_value = row->GetAFAValue();
786 auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
787
788 if (mov_rsp_rbp_pattern_p()) {
789 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
790 fa_value_ptr->SetIsRegisterPlusOffset(
791 m_lldb_fp_regnum, fa_value_ptr->GetOffset());
792 row_updated = true;
793 }
794 }
795
796 else if (mov_rsp_rbx_pattern_p()) {
797 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
798 fa_value_ptr->SetIsRegisterPlusOffset(
799 m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
800 row_updated = true;
801 }
802 }
803
804 else if (and_rsp_pattern_p()) {
805 current_sp_bytes_offset_from_fa = 0;
806 afa_value.SetIsRegisterPlusOffset(
807 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
808 fa_value_ptr = &afa_value;
809 is_aligned = true;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000810 row_updated = true;
811 }
812
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000813 else if (mov_rbp_rsp_pattern_p()) {
814 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
815 {
816 is_aligned = false;
817 fa_value_ptr = &cfa_value;
818 afa_value.SetUnspecified();
819 row_updated = true;
820 }
821 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
822 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
823 }
824
825 else if (mov_rbx_rsp_pattern_p()) {
826 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
827 {
828 is_aligned = false;
829 fa_value_ptr = &cfa_value;
830 afa_value.SetUnspecified();
831 row_updated = true;
832 }
833 if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
834 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000835 }
836
837 // This is the start() function (or a pthread equivalent), it starts with a
Adrian Prantl05097242018-04-30 16:49:04 +0000838 // pushl $0x0 which puts the saved pc value of 0 on the stack. In this
839 // case we want to pretend we didn't see a stack movement at all --
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000840 // normally the saved pc value is already on the stack by the time the
841 // function starts executing.
842 else if (push_0_pattern_p()) {
843 }
844
845 else if (push_reg_p(machine_regno)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000846 current_sp_bytes_offset_from_fa += m_wordsize;
847 // the PUSH instruction has moved the stack pointer - if the FA is set
Adrian Prantl05097242018-04-30 16:49:04 +0000848 // in terms of the stack pointer, we need to add a new row of
849 // instructions.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000850 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
851 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000852 row_updated = true;
853 }
854 // record where non-volatile (callee-saved, spilled) registers are saved
855 // on the stack
856 if (nonvolatile_reg_p(machine_regno) &&
857 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000858 !saved_registers[machine_regno]) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000859 UnwindPlan::Row::RegisterLocation regloc;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000860 if (is_aligned)
861 regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
862 else
863 regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000864 row->SetRegisterInfo(lldb_regno, regloc);
865 saved_registers[machine_regno] = true;
866 row_updated = true;
867 }
868 }
869
870 else if (pop_reg_p(machine_regno)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000871 current_sp_bytes_offset_from_fa -= m_wordsize;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000872
873 if (nonvolatile_reg_p(machine_regno) &&
874 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000875 saved_registers[machine_regno]) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000876 saved_registers[machine_regno] = false;
877 row->RemoveRegisterInfo(lldb_regno);
878
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000879 if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
880 fa_value_ptr->SetIsRegisterPlusOffset(
881 m_lldb_sp_regnum, fa_value_ptr->GetOffset());
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000882 }
883
884 in_epilogue = true;
885 row_updated = true;
886 }
887
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000888 // the POP instruction has moved the stack pointer - if the FA is set in
Adrian Prantl05097242018-04-30 16:49:04 +0000889 // terms of the stack pointer, we need to add a new row of instructions.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000890 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
891 fa_value_ptr->SetIsRegisterPlusOffset(
892 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000893 row_updated = true;
894 }
895 }
896
Jason Molenda2630acc2016-10-04 05:10:06 +0000897 else if (pop_misc_reg_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000898 current_sp_bytes_offset_from_fa -= m_wordsize;
899 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 Molenda2630acc2016-10-04 05:10:06 +0000902 row_updated = true;
903 }
904 }
905
Adrian Prantl05097242018-04-30 16:49:04 +0000906 // The LEAVE instruction moves the value from rbp into rsp and pops a value
907 // off the stack into rbp (restoring the caller's rbp value). It is the
908 // opposite of ENTER, or 'push rbp, mov rsp rbp'.
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000909 else if (leave_pattern_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000910 if (saved_registers[m_machine_fp_regnum]) {
911 saved_registers[m_machine_fp_regnum] = false;
912 row->RemoveRegisterInfo(m_lldb_fp_regnum);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000913
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000914 row_updated = true;
915 }
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000916
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000917 if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
918 {
919 is_aligned = false;
920 fa_value_ptr = &cfa_value;
921 afa_value.SetUnspecified();
922 row_updated = true;
923 }
924
925 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
926 {
927 fa_value_ptr->SetIsRegisterPlusOffset(
928 m_lldb_sp_regnum, fa_value_ptr->GetOffset());
929
930 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
931 }
932
933 current_sp_bytes_offset_from_fa -= m_wordsize;
934
935 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
936 fa_value_ptr->SetIsRegisterPlusOffset(
937 m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
938 row_updated = true;
939 }
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000940
941 in_epilogue = true;
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000942 }
943
944 else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
945 nonvolatile_reg_p(machine_regno) &&
946 machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000947 !saved_registers[machine_regno]) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000948 saved_registers[machine_regno] = true;
949
950 UnwindPlan::Row::RegisterLocation regloc;
951
Adrian Prantl05097242018-04-30 16:49:04 +0000952 // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000953 // want to express this as the offset from the FA. If the frame base is
954 // rbp (like the above instruction), the FA offset for rbp is probably
955 // 16. So we want to say that the value is stored at the FA address -
Adrian Prantl05097242018-04-30 16:49:04 +0000956 // 96.
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000957 if (is_aligned)
958 regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
959 else
960 regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000961
962 row->SetRegisterInfo(lldb_regno, regloc);
963
964 row_updated = true;
965 }
966
967 else if (sub_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000968 current_sp_bytes_offset_from_fa += stack_offset;
969 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
970 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000971 row_updated = true;
972 }
973 }
974
975 else if (add_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000976 current_sp_bytes_offset_from_fa -= stack_offset;
977 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
978 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000979 row_updated = true;
980 }
981 in_epilogue = true;
982 }
983
Jason Molenda2630acc2016-10-04 05:10:06 +0000984 else if (push_extended_pattern_p() || push_imm_pattern_p() ||
985 push_misc_reg_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000986 current_sp_bytes_offset_from_fa += m_wordsize;
987 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
988 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molendac0657a62016-10-01 00:19:26 +0000989 row_updated = true;
990 }
991 }
992
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000993 else if (lea_rsp_pattern_p(stack_offset)) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000994 current_sp_bytes_offset_from_fa -= stack_offset;
995 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
996 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +0000997 row_updated = true;
998 }
999 if (stack_offset > 0)
1000 in_epilogue = true;
1001 }
1002
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001003 else if (lea_rbp_rsp_pattern_p(stack_offset)) {
1004 if (is_aligned &&
1005 cfa_value.GetRegisterNumber() == m_lldb_fp_regnum) {
1006 is_aligned = false;
1007 fa_value_ptr = &cfa_value;
1008 afa_value.SetUnspecified();
1009 row_updated = true;
1010 }
1011 if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
1012 current_sp_bytes_offset_from_fa =
1013 fa_value_ptr->GetOffset() - stack_offset;
1014 }
1015 }
1016
1017 else if (lea_rbx_rsp_pattern_p(stack_offset)) {
1018 if (is_aligned &&
1019 cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1020 is_aligned = false;
1021 fa_value_ptr = &cfa_value;
1022 afa_value.SetUnspecified();
1023 row_updated = true;
1024 }
1025 if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1026 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
1027 }
Pavel Labath89963462017-06-29 12:40:13 +00001028 }
1029
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001030 else if (ret_pattern_p() && prologue_completed_row.get()) {
Adrian Prantl05097242018-04-30 16:49:04 +00001031 // Reinstate the saved prologue setup for any instructions that come
1032 // after the ret instruction
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001033
1034 UnwindPlan::Row *newrow = new UnwindPlan::Row;
1035 *newrow = *prologue_completed_row.get();
1036 row.reset(newrow);
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001037 current_sp_bytes_offset_from_fa =
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001038 prologue_completed_sp_bytes_offset_from_cfa;
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001039 is_aligned = prologue_completed_is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001040
1041 saved_registers.clear();
1042 saved_registers.resize(prologue_completed_saved_registers.size(), false);
1043 for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) {
1044 saved_registers[i] = prologue_completed_saved_registers[i];
1045 }
1046
1047 in_epilogue = true;
1048 row_updated = true;
1049 }
1050
1051 // call next instruction
1052 // call 0
1053 // => pop %ebx
1054 // This is used in i386 programs to get the PIC base address for finding
1055 // global data
1056 else if (call_next_insn_pattern_p()) {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001057 current_sp_bytes_offset_from_fa += m_wordsize;
1058 if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1059 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001060 row_updated = true;
1061 }
1062 }
1063
1064 if (row_updated) {
1065 if (current_func_text_offset + insn_len < size) {
1066 row->SetOffset(current_func_text_offset + insn_len);
1067 unwind_plan.AppendRow(row);
1068 // Allocate a new Row, populate it with the existing Row contents.
1069 newrow = new UnwindPlan::Row;
1070 *newrow = *row.get();
1071 row.reset(newrow);
1072 }
1073 }
1074
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001075 if (!in_epilogue && row_updated) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001076 // If we're not in an epilogue sequence, save the updated Row
1077 UnwindPlan::Row *newrow = new UnwindPlan::Row;
1078 *newrow = *row.get();
1079 prologue_completed_row.reset(newrow);
1080
1081 prologue_completed_saved_registers.clear();
1082 prologue_completed_saved_registers.resize(saved_registers.size(), false);
1083 for (size_t i = 0; i < saved_registers.size(); ++i) {
1084 prologue_completed_saved_registers[i] = saved_registers[i];
1085 }
1086 }
1087
1088 // We may change the sp value without adding a new Row necessarily -- keep
1089 // track of it either way.
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001090 if (!in_epilogue) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001091 prologue_completed_sp_bytes_offset_from_cfa =
Aleksandr Urakov4538ed32018-10-30 10:07:08 +00001092 current_sp_bytes_offset_from_fa;
1093 prologue_completed_is_aligned = is_aligned;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001094 }
1095
1096 m_cur_insn = m_cur_insn + insn_len;
1097 current_func_text_offset += insn_len;
1098 }
1099
1100 unwind_plan.SetSourceName("assembly insn profiling");
1101 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1102 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1103
1104 return true;
1105}
1106
1107bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
1108 uint8_t *data, size_t size, AddressRange &func_range,
1109 UnwindPlan &unwind_plan, RegisterContextSP &reg_ctx) {
1110 Address addr_start = func_range.GetBaseAddress();
1111 if (!addr_start.IsValid())
1112 return false;
1113
Adrian Prantl05097242018-04-30 16:49:04 +00001114 // We either need a live RegisterContext, or we need the UnwindPlan to
1115 // already be in the lldb register numbering scheme.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001116 if (reg_ctx.get() == nullptr &&
1117 unwind_plan.GetRegisterKind() != eRegisterKindLLDB)
1118 return false;
1119
1120 // Is original unwind_plan valid?
Adrian Prantl05097242018-04-30 16:49:04 +00001121 // unwind_plan should have at least one row which is ABI-default (CFA
1122 // register is sp), and another row in mid-function.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001123 if (unwind_plan.GetRowCount() < 2)
1124 return false;
1125
1126 UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex(0);
1127 if (first_row->GetOffset() != 0)
1128 return false;
1129 uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber();
1130 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1131 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1132 unwind_plan.GetRegisterKind(),
1133 first_row->GetCFAValue().GetRegisterNumber());
1134 }
1135 if (cfa_reg != m_lldb_sp_regnum ||
1136 first_row->GetCFAValue().GetOffset() != m_wordsize)
1137 return false;
1138
1139 UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset(-1);
1140
1141 size_t offset = 0;
1142 int row_id = 1;
1143 bool unwind_plan_updated = false;
1144 UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
1145 m_cur_insn = data + offset;
1146
Adrian Prantl05097242018-04-30 16:49:04 +00001147 // After a mid-function epilogue we will need to re-insert the original
1148 // unwind rules so unwinds work for the remainder of the function. These
1149 // aren't common with clang/gcc on x86 but it is possible.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001150 bool reinstate_unwind_state = false;
1151
1152 while (offset < size) {
1153 m_cur_insn = data + offset;
1154 int insn_len;
Jason Molendaf6208042017-07-08 00:12:15 +00001155 if (!instruction_length(m_cur_insn, insn_len, size - offset)
1156 || insn_len == 0
1157 || insn_len > kMaxInstructionByteSize) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001158 // An unrecognized/junk instruction.
1159 break;
1160 }
1161
1162 // Advance offsets.
1163 offset += insn_len;
1164 m_cur_insn = data + offset;
1165
Adrian Prantl05097242018-04-30 16:49:04 +00001166 // offset is pointing beyond the bounds of the function; stop looping.
Jason Molendab8ebcb52017-03-02 05:08:10 +00001167 if (offset >= size)
1168 continue;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001169
Jason Molendab8ebcb52017-03-02 05:08:10 +00001170 if (reinstate_unwind_state) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001171 UnwindPlan::RowSP new_row(new UnwindPlan::Row());
1172 *new_row = *original_last_row;
1173 new_row->SetOffset(offset);
1174 unwind_plan.AppendRow(new_row);
1175 row.reset(new UnwindPlan::Row());
1176 *row = *new_row;
1177 reinstate_unwind_state = false;
1178 unwind_plan_updated = true;
1179 continue;
1180 }
1181
1182 // If we already have one row for this instruction, we can continue.
1183 while (row_id < unwind_plan.GetRowCount() &&
1184 unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) {
1185 row_id++;
1186 }
1187 UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex(row_id - 1);
1188 if (original_row->GetOffset() == offset) {
1189 *row = *original_row;
1190 continue;
1191 }
1192
1193 if (row_id == 0) {
Adrian Prantl05097242018-04-30 16:49:04 +00001194 // If we are here, compiler didn't generate CFI for prologue. This won't
1195 // happen to GCC or clang. In this case, bail out directly.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001196 return false;
1197 }
1198
1199 // Inspect the instruction to check if we need a new row for it.
1200 cfa_reg = row->GetCFAValue().GetRegisterNumber();
1201 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1202 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1203 unwind_plan.GetRegisterKind(),
1204 row->GetCFAValue().GetRegisterNumber());
1205 }
1206 if (cfa_reg == m_lldb_sp_regnum) {
1207 // CFA register is sp.
1208
1209 // call next instruction
1210 // call 0
1211 // => pop %ebx
1212 if (call_next_insn_pattern_p()) {
1213 row->SetOffset(offset);
1214 row->GetCFAValue().IncOffset(m_wordsize);
1215
1216 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1217 unwind_plan.InsertRow(new_row);
1218 unwind_plan_updated = true;
1219 continue;
1220 }
1221
1222 // push/pop register
1223 int regno;
1224 if (push_reg_p(regno)) {
1225 row->SetOffset(offset);
1226 row->GetCFAValue().IncOffset(m_wordsize);
1227
1228 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1229 unwind_plan.InsertRow(new_row);
1230 unwind_plan_updated = true;
1231 continue;
1232 }
1233 if (pop_reg_p(regno)) {
1234 // Technically, this might be a nonvolatile register recover in
Adrian Prantl05097242018-04-30 16:49:04 +00001235 // epilogue. We should reset RegisterInfo for the register. But in
1236 // practice, previous rule for the register is still valid... So we
1237 // ignore this case.
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001238
1239 row->SetOffset(offset);
1240 row->GetCFAValue().IncOffset(-m_wordsize);
1241
1242 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1243 unwind_plan.InsertRow(new_row);
1244 unwind_plan_updated = true;
1245 continue;
1246 }
1247
Jason Molenda2630acc2016-10-04 05:10:06 +00001248 if (pop_misc_reg_p()) {
1249 row->SetOffset(offset);
1250 row->GetCFAValue().IncOffset(-m_wordsize);
1251
1252 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1253 unwind_plan.InsertRow(new_row);
1254 unwind_plan_updated = true;
1255 continue;
1256 }
1257
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001258 // push imm
1259 if (push_imm_pattern_p()) {
1260 row->SetOffset(offset);
1261 row->GetCFAValue().IncOffset(m_wordsize);
1262 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1263 unwind_plan.InsertRow(new_row);
1264 unwind_plan_updated = true;
1265 continue;
1266 }
1267
Jason Molendac0657a62016-10-01 00:19:26 +00001268 // push extended
Jason Molenda2630acc2016-10-04 05:10:06 +00001269 if (push_extended_pattern_p() || push_misc_reg_p()) {
Jason Molendac0657a62016-10-01 00:19:26 +00001270 row->SetOffset(offset);
1271 row->GetCFAValue().IncOffset(m_wordsize);
1272 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1273 unwind_plan.InsertRow(new_row);
1274 unwind_plan_updated = true;
1275 continue;
1276 }
1277
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001278 // add/sub %rsp/%esp
1279 int amount;
1280 if (add_rsp_pattern_p(amount)) {
1281 row->SetOffset(offset);
1282 row->GetCFAValue().IncOffset(-amount);
1283
1284 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1285 unwind_plan.InsertRow(new_row);
1286 unwind_plan_updated = true;
1287 continue;
1288 }
1289 if (sub_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
1299 // lea %rsp, [%rsp + $offset]
1300 if (lea_rsp_pattern_p(amount)) {
1301 row->SetOffset(offset);
1302 row->GetCFAValue().IncOffset(-amount);
1303
1304 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1305 unwind_plan.InsertRow(new_row);
1306 unwind_plan_updated = true;
1307 continue;
1308 }
1309
1310 if (ret_pattern_p()) {
1311 reinstate_unwind_state = true;
1312 continue;
1313 }
1314 } else if (cfa_reg == m_lldb_fp_regnum) {
1315 // CFA register is fp.
1316
1317 // The only case we care about is epilogue:
1318 // [0x5d] pop %rbp/%ebp
1319 // => [0xc3] ret
1320 if (pop_rbp_pattern_p() || leave_pattern_p()) {
Jason Molendac0657a62016-10-01 00:19:26 +00001321 offset += 1;
1322 row->SetOffset(offset);
1323 row->GetCFAValue().SetIsRegisterPlusOffset(
1324 first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001325
Jason Molendac0657a62016-10-01 00:19:26 +00001326 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1327 unwind_plan.InsertRow(new_row);
1328 unwind_plan_updated = true;
1329 reinstate_unwind_state = true;
1330 continue;
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001331 }
1332 } else {
1333 // CFA register is not sp or fp.
1334
1335 // This must be hand-written assembly.
1336 // Just trust eh_frame and assume we have finished.
1337 break;
1338 }
1339 }
1340
1341 unwind_plan.SetPlanValidAddressRange(func_range);
1342 if (unwind_plan_updated) {
1343 std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString());
1344 unwind_plan_source += " plus augmentation from assembly parsing";
1345 unwind_plan.SetSourceName(unwind_plan_source.c_str());
1346 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1347 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1348 }
1349 return true;
1350}
1351
1352bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
1353 uint8_t *data, size_t size, size_t &offset) {
1354 offset = 0;
1355
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001356 if (!m_register_map_initialized)
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001357 return false;
1358
1359 while (offset < size) {
1360 int regno;
1361 int insn_len;
1362 int scratch;
1363
1364 m_cur_insn = data + offset;
Jason Molendaf6208042017-07-08 00:12:15 +00001365 if (!instruction_length(m_cur_insn, insn_len, size - offset)
1366 || insn_len > kMaxInstructionByteSize
1367 || insn_len == 0) {
Jason Molenda74b8fbc2016-09-29 01:00:16 +00001368 // An error parsing the instruction, i.e. probably data/garbage - stop
1369 // scanning
1370 break;
1371 }
1372
1373 if (push_rbp_pattern_p() || mov_rsp_rbp_pattern_p() ||
1374 sub_rsp_pattern_p(scratch) || push_reg_p(regno) ||
1375 mov_reg_to_local_stack_frame_p(regno, scratch) ||
1376 (lea_rsp_pattern_p(scratch) && offset == 0)) {
1377 offset += insn_len;
1378 continue;
1379 }
1380 //
1381 // Unknown non-prologue instruction - stop scanning
1382 break;
1383 }
1384
1385 return true;
1386}