Coverage Report

Created: 2022-01-22 13:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- x86AssemblyInspectionEngine.cpp -----------------------------------===//
2
//
3
// 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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "x86AssemblyInspectionEngine.h"
10
11
#include <memory>
12
13
#include "llvm-c/Disassembler.h"
14
15
#include "lldb/Core/Address.h"
16
#include "lldb/Symbol/UnwindPlan.h"
17
#include "lldb/Target/RegisterContext.h"
18
#include "lldb/Target/UnwindAssembly.h"
19
20
using namespace lldb_private;
21
using namespace lldb;
22
23
x86AssemblyInspectionEngine::x86AssemblyInspectionEngine(const ArchSpec &arch)
24
    : m_cur_insn(nullptr), m_machine_ip_regnum(LLDB_INVALID_REGNUM),
25
      m_machine_sp_regnum(LLDB_INVALID_REGNUM),
26
      m_machine_fp_regnum(LLDB_INVALID_REGNUM),
27
      m_lldb_ip_regnum(LLDB_INVALID_REGNUM),
28
      m_lldb_sp_regnum(LLDB_INVALID_REGNUM),
29
      m_lldb_fp_regnum(LLDB_INVALID_REGNUM),
30
31
      m_reg_map(), m_arch(arch), m_cpu(k_cpu_unspecified), m_wordsize(-1),
32
21.0k
      m_register_map_initialized(false), m_disasm_context() {
33
21.0k
  m_disasm_context =
34
21.0k
      ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr,
35
21.0k
                         /*TagType=*/1, nullptr, nullptr);
36
21.0k
}
37
38
21.0k
x86AssemblyInspectionEngine::~x86AssemblyInspectionEngine() {
39
21.0k
  ::LLVMDisasmDispose(m_disasm_context);
40
21.0k
}
41
42
10.8k
void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
43
10.8k
  m_cpu = k_cpu_unspecified;
44
10.8k
  m_wordsize = -1;
45
10.8k
  m_register_map_initialized = false;
46
47
10.8k
  const llvm::Triple::ArchType cpu = m_arch.GetMachine();
48
10.8k
  if (cpu == llvm::Triple::x86)
49
3
    m_cpu = k_i386;
50
10.8k
  else if (cpu == llvm::Triple::x86_64)
51
10.8k
    m_cpu = k_x86_64;
52
53
10.8k
  if (m_cpu == k_cpu_unspecified)
54
0
    return;
55
56
10.8k
  if (reg_ctx.get() == nullptr)
57
0
    return;
58
59
10.8k
  if (m_cpu == k_i386) {
60
3
    m_machine_ip_regnum = k_machine_eip;
61
3
    m_machine_sp_regnum = k_machine_esp;
62
3
    m_machine_fp_regnum = k_machine_ebp;
63
3
    m_machine_alt_fp_regnum = k_machine_ebx;
64
3
    m_wordsize = 4;
65
66
3
    struct lldb_reg_info reginfo;
67
3
    reginfo.name = "eax";
68
3
    m_reg_map[k_machine_eax] = reginfo;
69
3
    reginfo.name = "edx";
70
3
    m_reg_map[k_machine_edx] = reginfo;
71
3
    reginfo.name = "esp";
72
3
    m_reg_map[k_machine_esp] = reginfo;
73
3
    reginfo.name = "esi";
74
3
    m_reg_map[k_machine_esi] = reginfo;
75
3
    reginfo.name = "eip";
76
3
    m_reg_map[k_machine_eip] = reginfo;
77
3
    reginfo.name = "ecx";
78
3
    m_reg_map[k_machine_ecx] = reginfo;
79
3
    reginfo.name = "ebx";
80
3
    m_reg_map[k_machine_ebx] = reginfo;
81
3
    reginfo.name = "ebp";
82
3
    m_reg_map[k_machine_ebp] = reginfo;
83
3
    reginfo.name = "edi";
84
3
    m_reg_map[k_machine_edi] = reginfo;
85
10.8k
  } else {
86
10.8k
    m_machine_ip_regnum = k_machine_rip;
87
10.8k
    m_machine_sp_regnum = k_machine_rsp;
88
10.8k
    m_machine_fp_regnum = k_machine_rbp;
89
10.8k
    m_machine_alt_fp_regnum = k_machine_rbx;
90
10.8k
    m_wordsize = 8;
91
92
10.8k
    struct lldb_reg_info reginfo;
93
10.8k
    reginfo.name = "rax";
94
10.8k
    m_reg_map[k_machine_rax] = reginfo;
95
10.8k
    reginfo.name = "rdx";
96
10.8k
    m_reg_map[k_machine_rdx] = reginfo;
97
10.8k
    reginfo.name = "rsp";
98
10.8k
    m_reg_map[k_machine_rsp] = reginfo;
99
10.8k
    reginfo.name = "rsi";
100
10.8k
    m_reg_map[k_machine_rsi] = reginfo;
101
10.8k
    reginfo.name = "r8";
102
10.8k
    m_reg_map[k_machine_r8] = reginfo;
103
10.8k
    reginfo.name = "r10";
104
10.8k
    m_reg_map[k_machine_r10] = reginfo;
105
10.8k
    reginfo.name = "r12";
106
10.8k
    m_reg_map[k_machine_r12] = reginfo;
107
10.8k
    reginfo.name = "r14";
108
10.8k
    m_reg_map[k_machine_r14] = reginfo;
109
10.8k
    reginfo.name = "rip";
110
10.8k
    m_reg_map[k_machine_rip] = reginfo;
111
10.8k
    reginfo.name = "rcx";
112
10.8k
    m_reg_map[k_machine_rcx] = reginfo;
113
10.8k
    reginfo.name = "rbx";
114
10.8k
    m_reg_map[k_machine_rbx] = reginfo;
115
10.8k
    reginfo.name = "rbp";
116
10.8k
    m_reg_map[k_machine_rbp] = reginfo;
117
10.8k
    reginfo.name = "rdi";
118
10.8k
    m_reg_map[k_machine_rdi] = reginfo;
119
10.8k
    reginfo.name = "r9";
120
10.8k
    m_reg_map[k_machine_r9] = reginfo;
121
10.8k
    reginfo.name = "r11";
122
10.8k
    m_reg_map[k_machine_r11] = reginfo;
123
10.8k
    reginfo.name = "r13";
124
10.8k
    m_reg_map[k_machine_r13] = reginfo;
125
10.8k
    reginfo.name = "r15";
126
10.8k
    m_reg_map[k_machine_r15] = reginfo;
127
10.8k
  }
128
129
10.8k
  for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin();
130
196k
       it != m_reg_map.end(); 
++it185k
) {
131
185k
    const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName(it->second.name);
132
185k
    if (ri)
133
185k
      it->second.lldb_regnum = ri->kinds[eRegisterKindLLDB];
134
185k
  }
135
136
10.8k
  uint32_t lldb_regno;
137
10.8k
  if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno))
138
10.8k
    m_lldb_sp_regnum = lldb_regno;
139
10.8k
  if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
140
10.8k
    m_lldb_fp_regnum = lldb_regno;
141
10.8k
  if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
142
10.8k
    m_lldb_alt_fp_regnum = lldb_regno;
143
10.8k
  if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
144
10.8k
    m_lldb_ip_regnum = lldb_regno;
145
146
10.8k
  m_register_map_initialized = true;
147
10.8k
}
148
149
void x86AssemblyInspectionEngine::Initialize(
150
62
    std::vector<lldb_reg_info> &reg_info) {
151
62
  m_cpu = k_cpu_unspecified;
152
62
  m_wordsize = -1;
153
62
  m_register_map_initialized = false;
154
155
62
  const llvm::Triple::ArchType cpu = m_arch.GetMachine();
156
62
  if (cpu == llvm::Triple::x86)
157
30
    m_cpu = k_i386;
158
32
  else if (cpu == llvm::Triple::x86_64)
159
32
    m_cpu = k_x86_64;
160
161
62
  if (m_cpu == k_cpu_unspecified)
162
0
    return;
163
164
62
  if (m_cpu == k_i386) {
165
30
    m_machine_ip_regnum = k_machine_eip;
166
30
    m_machine_sp_regnum = k_machine_esp;
167
30
    m_machine_fp_regnum = k_machine_ebp;
168
30
    m_machine_alt_fp_regnum = k_machine_ebx;
169
30
    m_wordsize = 4;
170
171
30
    struct lldb_reg_info reginfo;
172
30
    reginfo.name = "eax";
173
30
    m_reg_map[k_machine_eax] = reginfo;
174
30
    reginfo.name = "edx";
175
30
    m_reg_map[k_machine_edx] = reginfo;
176
30
    reginfo.name = "esp";
177
30
    m_reg_map[k_machine_esp] = reginfo;
178
30
    reginfo.name = "esi";
179
30
    m_reg_map[k_machine_esi] = reginfo;
180
30
    reginfo.name = "eip";
181
30
    m_reg_map[k_machine_eip] = reginfo;
182
30
    reginfo.name = "ecx";
183
30
    m_reg_map[k_machine_ecx] = reginfo;
184
30
    reginfo.name = "ebx";
185
30
    m_reg_map[k_machine_ebx] = reginfo;
186
30
    reginfo.name = "ebp";
187
30
    m_reg_map[k_machine_ebp] = reginfo;
188
30
    reginfo.name = "edi";
189
30
    m_reg_map[k_machine_edi] = reginfo;
190
32
  } else {
191
32
    m_machine_ip_regnum = k_machine_rip;
192
32
    m_machine_sp_regnum = k_machine_rsp;
193
32
    m_machine_fp_regnum = k_machine_rbp;
194
32
    m_machine_alt_fp_regnum = k_machine_rbx;
195
32
    m_wordsize = 8;
196
197
32
    struct lldb_reg_info reginfo;
198
32
    reginfo.name = "rax";
199
32
    m_reg_map[k_machine_rax] = reginfo;
200
32
    reginfo.name = "rdx";
201
32
    m_reg_map[k_machine_rdx] = reginfo;
202
32
    reginfo.name = "rsp";
203
32
    m_reg_map[k_machine_rsp] = reginfo;
204
32
    reginfo.name = "rsi";
205
32
    m_reg_map[k_machine_rsi] = reginfo;
206
32
    reginfo.name = "r8";
207
32
    m_reg_map[k_machine_r8] = reginfo;
208
32
    reginfo.name = "r10";
209
32
    m_reg_map[k_machine_r10] = reginfo;
210
32
    reginfo.name = "r12";
211
32
    m_reg_map[k_machine_r12] = reginfo;
212
32
    reginfo.name = "r14";
213
32
    m_reg_map[k_machine_r14] = reginfo;
214
32
    reginfo.name = "rip";
215
32
    m_reg_map[k_machine_rip] = reginfo;
216
32
    reginfo.name = "rcx";
217
32
    m_reg_map[k_machine_rcx] = reginfo;
218
32
    reginfo.name = "rbx";
219
32
    m_reg_map[k_machine_rbx] = reginfo;
220
32
    reginfo.name = "rbp";
221
32
    m_reg_map[k_machine_rbp] = reginfo;
222
32
    reginfo.name = "rdi";
223
32
    m_reg_map[k_machine_rdi] = reginfo;
224
32
    reginfo.name = "r9";
225
32
    m_reg_map[k_machine_r9] = reginfo;
226
32
    reginfo.name = "r11";
227
32
    m_reg_map[k_machine_r11] = reginfo;
228
32
    reginfo.name = "r13";
229
32
    m_reg_map[k_machine_r13] = reginfo;
230
32
    reginfo.name = "r15";
231
32
    m_reg_map[k_machine_r15] = reginfo;
232
32
  }
233
234
62
  for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin();
235
876
       it != m_reg_map.end(); 
++it814
) {
236
6.24k
    for (size_t i = 0; i < reg_info.size(); 
++i5.43k
) {
237
6.24k
      if (::strcmp(reg_info[i].name, it->second.name) == 0) {
238
814
        it->second.lldb_regnum = reg_info[i].lldb_regnum;
239
814
        break;
240
814
      }
241
6.24k
    }
242
814
  }
243
244
62
  uint32_t lldb_regno;
245
62
  if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno))
246
62
    m_lldb_sp_regnum = lldb_regno;
247
62
  if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
248
62
    m_lldb_fp_regnum = lldb_regno;
249
62
  if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
250
62
    m_lldb_alt_fp_regnum = lldb_regno;
251
62
  if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
252
62
    m_lldb_ip_regnum = lldb_regno;
253
254
62
  m_register_map_initialized = true;
255
62
}
256
257
// This function expects an x86 native register number (i.e. the bits stripped
258
// out of the actual instruction), not an lldb register number.
259
//
260
// FIXME: This is ABI dependent, it shouldn't be hardcoded here.
261
262
52.8k
bool x86AssemblyInspectionEngine::nonvolatile_reg_p(int machine_regno) {
263
52.8k
  if (m_cpu == k_i386) {
264
51
    switch (machine_regno) {
265
10
    case k_machine_ebx:
266
33
    case k_machine_ebp: // not actually a nonvolatile but often treated as such
267
                        // by convention
268
39
    case k_machine_esi:
269
45
    case k_machine_edi:
270
45
    case k_machine_esp:
271
45
      return true;
272
6
    default:
273
6
      return false;
274
51
    }
275
51
  }
276
52.8k
  if (m_cpu == k_x86_64) {
277
52.8k
    switch (machine_regno) {
278
195
    case k_machine_rbx:
279
196
    case k_machine_rsp:
280
11.6k
    case k_machine_rbp: // not actually a nonvolatile but often treated as such
281
                        // by convention
282
11.7k
    case k_machine_r12:
283
11.8k
    case k_machine_r13:
284
11.9k
    case k_machine_r14:
285
11.9k
    case k_machine_r15:
286
11.9k
      return true;
287
40.8k
    default:
288
40.8k
      return false;
289
52.8k
    }
290
52.8k
  }
291
0
  return false;
292
52.8k
}
293
294
// Macro to detect if this is a REX mode prefix byte.
295
378k
#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
296
297
// The high bit which should be added to the source register number (the "R"
298
// bit)
299
195k
#define REX_W_SRCREG(opcode) (((opcode)&0x4) >> 2)
300
301
// The high bit which should be added to the destination register number (the
302
// "B" bit)
303
195k
#define REX_W_DSTREG(opcode) ((opcode)&0x1)
304
305
// pushq %rbp [0x55]
306
0
bool x86AssemblyInspectionEngine::push_rbp_pattern_p() {
307
0
  uint8_t *p = m_cur_insn;
308
0
  return *p == 0x55;
309
0
}
310
311
// pushq $0 ; the first instruction in start() [0x6a 0x00]
312
397k
bool x86AssemblyInspectionEngine::push_0_pattern_p() {
313
397k
  uint8_t *p = m_cur_insn;
314
397k
  return *p == 0x6a && 
*(p + 1) == 0x02.50k
;
315
397k
}
316
317
// pushq $0
318
// pushl $0
319
366k
bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
320
366k
  uint8_t *p = m_cur_insn;
321
366k
  return *p == 0x68 || 
*p == 0x6a366k
;
322
366k
}
323
324
// pushl imm8(%esp)
325
//
326
// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' (same byte pattern for 'pushq
327
// 0x20(%rsp)' in an x86_64 program)
328
//
329
// 0xff (with opcode bits '6' in next byte, PUSH r/m32) 0x74 (ModR/M byte with
330
// three bits used to specify the opcode)
331
//      mod == b01, opcode == b110, R/M == b100
332
//      "+disp8"
333
// 0x24 (SIB byte - scaled index = 0, r32 == esp) 0x20 imm8 value
334
335
366k
bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
336
366k
  if (*m_cur_insn == 0xff) {
337
    // Get the 3 opcode bits from the ModR/M byte
338
18.8k
    uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
339
18.8k
    if (opcode == 6) {
340
      // I'm only looking for 0xff /6 here - I
341
      // don't really care what value is being pushed, just that we're pushing
342
      // a 32/64 bit value on to the stack is enough.
343
8
      return true;
344
8
    }
345
18.8k
  }
346
366k
  return false;
347
366k
}
348
349
// instructions only valid in 32-bit mode:
350
// 0x0e - push cs
351
// 0x16 - push ss
352
// 0x1e - push ds
353
// 0x06 - push es
354
366k
bool x86AssemblyInspectionEngine::push_misc_reg_p() {
355
366k
  uint8_t p = *m_cur_insn;
356
366k
  if (m_wordsize == 4) {
357
80
    if (p == 0x0e || 
p == 0x1679
||
p == 0x1e78
||
p == 0x0677
)
358
4
      return true;
359
80
  }
360
366k
  return false;
361
366k
}
362
363
// pushq %rbx
364
// pushl %ebx
365
395k
bool x86AssemblyInspectionEngine::push_reg_p(int &regno) {
366
395k
  uint8_t *p = m_cur_insn;
367
395k
  int regno_prefix_bit = 0;
368
  // If we have a rex prefix byte, check to see if a B bit is set
369
395k
  if (m_wordsize == 8 && 
(*p & 0xfe) == 0x40395k
) {
370
1.55k
    regno_prefix_bit = (*p & 1) << 3;
371
1.55k
    p++;
372
1.55k
  }
373
395k
  if (*p >= 0x50 && 
*p <= 0x57175k
) {
374
8.48k
    regno = (*p - 0x50) | regno_prefix_bit;
375
8.48k
    return true;
376
8.48k
  }
377
386k
  return false;
378
395k
}
379
380
// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] movl %esp, %ebp [0x8b
381
// 0xec] or [0x89 0xe5]
382
410k
bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
383
410k
  uint8_t *p = m_cur_insn;
384
410k
  if (m_wordsize == 8 && 
*p == 0x48410k
)
385
197k
    p++;
386
410k
  if (*(p) == 0x8b && 
*(p + 1) == 0xec84.7k
)
387
3
    return true;
388
410k
  if (*(p) == 0x89 && 
*(p + 1) == 0xe569.3k
)
389
8.17k
    return true;
390
402k
  return false;
391
410k
}
392
393
// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
394
// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
395
402k
bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
396
402k
  uint8_t *p = m_cur_insn;
397
402k
  if (m_wordsize == 8 && 
*p == 0x48402k
)
398
189k
    p++;
399
402k
  if (*(p) == 0x8b && 
*(p + 1) == 0xdc84.7k
)
400
1
    return true;
401
402k
  if (*(p) == 0x89 && 
*(p + 1) == 0xe361.1k
)
402
0
    return true;
403
402k
  return false;
404
402k
}
405
406
// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
407
// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
408
400k
bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
409
400k
  uint8_t *p = m_cur_insn;
410
400k
  if (m_wordsize == 8 && 
*p == 0x48400k
)
411
187k
    p++;
412
400k
  if (*(p) == 0x8b && 
*(p + 1) == 0xe584.7k
)
413
1
    return true;
414
400k
  if (*(p) == 0x89 && 
*(p + 1) == 0xec61.1k
)
415
2.34k
    return true;
416
397k
  return false;
417
400k
}
418
419
// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
420
// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
421
397k
bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
422
397k
  uint8_t *p = m_cur_insn;
423
397k
  if (m_wordsize == 8 && 
*p == 0x48397k
)
424
184k
    p++;
425
397k
  if (*(p) == 0x8b && 
*(p + 1) == 0xe384.7k
)
426
1
    return true;
427
397k
  if (*(p) == 0x89 && 
*(p + 1) == 0xdc58.8k
)
428
0
    return true;
429
397k
  return false;
430
397k
}
431
432
// subq $0x20, %rsp
433
378k
bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
434
378k
  uint8_t *p = m_cur_insn;
435
378k
  if (m_wordsize == 8 && 
*p == 0x48378k
)
436
184k
    p++;
437
  // 8-bit immediate operand
438
378k
  if (*p == 0x83 && 
*(p + 1) == 0xec17.9k
) {
439
4.34k
    amount = (int8_t) * (p + 2);
440
4.34k
    return true;
441
4.34k
  }
442
  // 32-bit immediate operand
443
374k
  if (*p == 0x81 && 
*(p + 1) == 0xec1.15k
) {
444
506
    amount = (int32_t)extract_4(p + 2);
445
506
    return true;
446
506
  }
447
373k
  return false;
448
374k
}
449
450
// addq $0x20, %rsp
451
373k
bool x86AssemblyInspectionEngine::add_rsp_pattern_p(int &amount) {
452
373k
  uint8_t *p = m_cur_insn;
453
373k
  if (m_wordsize == 8 && 
*p == 0x48373k
)
454
179k
    p++;
455
  // 8-bit immediate operand
456
373k
  if (*p == 0x83 && 
*(p + 1) == 0xc413.6k
) {
457
6.51k
    amount = (int8_t) * (p + 2);
458
6.51k
    return true;
459
6.51k
  }
460
  // 32-bit immediate operand
461
367k
  if (*p == 0x81 && 
*(p + 1) == 0xc4650
) {
462
476
    amount = (int32_t)extract_4(p + 2);
463
476
    return true;
464
476
  }
465
366k
  return false;
466
367k
}
467
468
// lea esp, [esp - 0x28]
469
// lea esp, [esp + 0x28]
470
366k
bool x86AssemblyInspectionEngine::lea_rsp_pattern_p(int &amount) {
471
366k
  uint8_t *p = m_cur_insn;
472
366k
  if (m_wordsize == 8 && 
*p == 0x48366k
)
473
172k
    p++;
474
475
  // Check opcode
476
366k
  if (*p != 0x8d)
477
327k
    return false;
478
479
  // 8 bit displacement
480
38.8k
  if (*(p + 1) == 0x64 && 
(*(p + 2) & 0x3f) == 0x240
) {
481
0
    amount = (int8_t) * (p + 3);
482
0
    return true;
483
0
  }
484
485
  // 32 bit displacement
486
38.8k
  if (*(p + 1) == 0xa4 && 
(*(p + 2) & 0x3f) == 0x240
) {
487
0
    amount = (int32_t)extract_4(p + 3);
488
0
    return true;
489
0
  }
490
491
38.8k
  return false;
492
38.8k
}
493
494
// lea -0x28(%ebp), %esp
495
// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
496
366k
bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) {
497
366k
  uint8_t *p = m_cur_insn;
498
366k
  if (m_wordsize == 8 && 
*p == 0x48366k
)
499
172k
    p++;
500
501
  // Check opcode
502
366k
  if (*p != 0x8d)
503
327k
    return false;
504
38.8k
  ++p;
505
506
  // 8 bit displacement
507
38.8k
  if (*p == 0x65) {
508
5
    amount = (int8_t)p[1];
509
5
    return true;
510
5
  }
511
512
  // 32 bit displacement
513
38.8k
  if (*p == 0xa5) {
514
0
    amount = (int32_t)extract_4(p + 1);
515
0
    return true;
516
0
  }
517
518
38.8k
  return false;
519
38.8k
}
520
521
// lea -0x28(%ebx), %esp
522
// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
523
366k
bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
524
366k
  uint8_t *p = m_cur_insn;
525
366k
  if (m_wordsize == 8 && 
*p == 0x48366k
)
526
172k
    p++;
527
528
  // Check opcode
529
366k
  if (*p != 0x8d)
530
327k
    return false;
531
38.8k
  ++p;
532
533
  // 8 bit displacement
534
38.8k
  if (*p == 0x63) {
535
0
    amount = (int8_t)p[1];
536
0
    return true;
537
0
  }
538
539
  // 32 bit displacement
540
38.8k
  if (*p == 0xa3) {
541
0
    amount = (int32_t)extract_4(p + 1);
542
0
    return true;
543
0
  }
544
545
38.8k
  return false;
546
38.8k
}
547
548
// and -0xfffffff0, %esp
549
// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
550
402k
bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
551
402k
  uint8_t *p = m_cur_insn;
552
402k
  if (m_wordsize == 8 && 
*p == 0x48402k
)
553
189k
    p++;
554
555
402k
  if (*p != 0x81 && 
*p != 0x83401k
)
556
381k
    return false;
557
558
21.4k
  return *++p == 0xe4;
559
402k
}
560
561
// popq %rbx
562
// popl %ebx
563
386k
bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
564
386k
  uint8_t *p = m_cur_insn;
565
386k
  int regno_prefix_bit = 0;
566
  // If we have a rex prefix byte, check to see if a B bit is set
567
386k
  if (m_wordsize == 8 && 
(*p & 0xfe) == 0x40386k
) {
568
1.38k
    regno_prefix_bit = (*p & 1) << 3;
569
1.38k
    p++;
570
1.38k
  }
571
386k
  if (*p >= 0x58 && 
*p <= 0x5f166k
) {
572
8.18k
    regno = (*p - 0x58) | regno_prefix_bit;
573
8.18k
    return true;
574
8.18k
  }
575
378k
  return false;
576
386k
}
577
578
// popq %rbp [0x5d]
579
// popl %ebp [0x5d]
580
60
bool x86AssemblyInspectionEngine::pop_rbp_pattern_p() {
581
60
  uint8_t *p = m_cur_insn;
582
60
  return (*p == 0x5d);
583
60
}
584
585
// instructions valid only in 32-bit mode:
586
// 0x1f - pop ds
587
// 0x07 - pop es
588
// 0x17 - pop ss
589
378k
bool x86AssemblyInspectionEngine::pop_misc_reg_p() {
590
378k
  uint8_t p = *m_cur_insn;
591
378k
  if (m_wordsize == 4) {
592
115
    if (p == 0x1f || 
p == 0x07114
||
p == 0x17113
)
593
3
      return true;
594
115
  }
595
378k
  return false;
596
378k
}
597
598
// leave [0xc9]
599
378k
bool x86AssemblyInspectionEngine::leave_pattern_p() {
600
378k
  uint8_t *p = m_cur_insn;
601
378k
  return (*p == 0xc9);
602
378k
}
603
604
// call $0 [0xe8 0x0 0x0 0x0 0x0]
605
348k
bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() {
606
348k
  uint8_t *p = m_cur_insn;
607
348k
  return (*p == 0xe8) && 
(*(p + 1) == 0x0)33.3k
&&
(*(p + 2) == 0x0)83
&&
608
348k
         
(*(p + 3) == 0x0)4
&&
(*(p + 4) == 0x0)4
;
609
348k
}
610
611
// Look for an instruction sequence storing a nonvolatile register on to the
612
// stack frame.
613
614
//  movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
615
//  movl %eax, -0xc(%ebp)  [0x89 0x45 0xf4]
616
617
// The offset value returned in rbp_offset will be positive -- but it must be
618
// subtraced from the frame base register to get the actual location.  The
619
// positive value returned for the offset is a convention used elsewhere for
620
// CFA offsets et al.
621
622
bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
623
378k
    int &regno, int &rbp_offset) {
624
378k
  uint8_t *p = m_cur_insn;
625
378k
  int src_reg_prefix_bit = 0;
626
378k
  int target_reg_prefix_bit = 0;
627
628
378k
  if (m_wordsize == 8 && 
REX_W_PREFIX_P378k
(*p)) {
629
195k
    src_reg_prefix_bit = REX_W_SRCREG(*p) << 3;
630
195k
    target_reg_prefix_bit = REX_W_DSTREG(*p) << 3;
631
195k
    if (target_reg_prefix_bit == 1) {
632
      // rbp/ebp don't need a prefix bit - we know this isn't the reg we care
633
      // about.
634
0
      return false;
635
0
    }
636
195k
    p++;
637
195k
  }
638
639
378k
  if (*p == 0x89) {
640
    /* Mask off the 3-5 bits which indicate the destination register
641
       if this is a ModR/M byte.  */
642
60.2k
    int opcode_destreg_masked_out = *(p + 1) & (~0x38);
643
644
    /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
645
       and three bits between them, e.g. 01nnn101
646
       We're looking for a destination of ebp-disp8 or ebp-disp32.   */
647
60.2k
    int immsize;
648
60.2k
    if (opcode_destreg_masked_out == 0x45)
649
11.5k
      immsize = 2;
650
48.7k
    else if (opcode_destreg_masked_out == 0x85)
651
24.6k
      immsize = 4;
652
24.0k
    else
653
24.0k
      return false;
654
655
36.1k
    int offset = 0;
656
36.1k
    if (immsize == 2)
657
11.5k
      offset = (int8_t) * (p + 2);
658
36.1k
    if (immsize == 4)
659
24.6k
      offset = (uint32_t)extract_4(p + 2);
660
36.1k
    if (offset > 0)
661
0
      return false;
662
663
36.1k
    regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
664
36.1k
    rbp_offset = offset > 0 ? 
offset0
: -offset;
665
36.1k
    return true;
666
36.1k
  }
667
318k
  return false;
668
378k
}
669
670
// Returns true if this is a jmp instruction where we can't
671
// know the destination address statically. 
672
//
673
// ff e0                                   jmpq   *%rax
674
// ff e1                                   jmpq   *%rcx
675
// ff 60 28                                jmpq   *0x28(%rax)
676
// ff 60 60                                jmpq   *0x60(%rax)
677
306k
bool x86AssemblyInspectionEngine::jmp_to_reg_p() {
678
306k
  if (*m_cur_insn != 0xff)
679
287k
    return false;
680
681
  // The second byte is a ModR/M /4 byte, strip off the registers
682
18.8k
  uint8_t second_byte_sans_reg = *(m_cur_insn + 1) & ~7;
683
684
  // Don't handle 0x24 disp32, because the target address is
685
  // knowable statically - pc_rel_branch_or_jump_p() will
686
  // return the target address.
687
688
  // [reg]
689
18.8k
  if (second_byte_sans_reg == 0x20)
690
4
    return true;
691
692
  // [reg]+disp8
693
18.8k
  if (second_byte_sans_reg == 0x60)
694
0
    return true;
695
696
  // [reg]+disp32
697
18.8k
  if (second_byte_sans_reg == 0xa0)
698
0
    return true;
699
700
  // reg
701
18.8k
  if (second_byte_sans_reg == 0xe0)
702
4.65k
    return true;
703
704
  // disp32
705
  // jumps to an address stored in memory, the value can't be cached
706
  // in an unwind plan.
707
14.1k
  if (second_byte_sans_reg == 0x24)
708
0
    return true;
709
710
  // use SIB byte
711
  // ff 24 fe  jmpq   *(%rsi,%rdi,8)
712
14.1k
  if (second_byte_sans_reg == 0x24)
713
0
    return true;
714
715
14.1k
  return false;
716
14.1k
}
717
718
// Detect branches to fixed pc-relative offsets.
719
// Returns the offset from the address of the next instruction
720
// that may be branch/jumped to.
721
//
722
// Cannot determine the offset of a JMP that jumps to the address in
723
// a register ("jmpq *%rax") or offset from a register value 
724
// ("jmpq *0x28(%rax)"), this method will return false on those
725
// instructions.
726
//
727
// These instructions all end in either a relative 8/16/32 bit value
728
// depending on the instruction and the current execution mode of the
729
// inferior process.  Once we know the size of the opcode instruction, 
730
// we can use the total instruction length to determine the size of
731
// the relative offset without having to compute it correctly.
732
733
bool x86AssemblyInspectionEngine::pc_rel_branch_or_jump_p (
734
    const int instruction_length, int &offset)
735
332k
{
736
332k
  int opcode_size = 0;
737
738
332k
  uint8_t b1 = m_cur_insn[0];
739
740
332k
  switch (b1) {
741
56
    case 0x77: // JA/JNBE rel8
742
88
    case 0x73: // JAE/JNB/JNC rel8
743
142
    case 0x72: // JB/JC/JNAE rel8
744
154
    case 0x76: // JBE/JNA rel8
745
154
    case 0xe3: // JCXZ/JECXZ/JRCXZ rel8
746
600
    case 0x74: // JE/JZ rel8
747
600
    case 0x7f: // JG/JNLE rel8
748
600
    case 0x7d: // JGE/JNL rel8
749
600
    case 0x7c: // JL/JNGE rel8
750
614
    case 0x7e: // JNG/JLE rel8
751
614
    case 0x71: // JNO rel8
752
614
    case 0x7b: // JNP/JPO rel8
753
640
    case 0x79: // JNS rel8
754
10.3k
    case 0x75: // JNE/JNZ rel8
755
10.3k
    case 0x70: // JO rel8
756
10.3k
    case 0x7a: // JP/JPE rel8
757
10.3k
    case 0x78: // JS rel8
758
10.6k
    case 0xeb: // JMP rel8
759
30.2k
    case 0xe9: // JMP rel16/rel32
760
30.2k
      opcode_size = 1;
761
30.2k
      break;
762
302k
    default:
763
302k
      break;
764
332k
  }
765
332k
  if (b1 == 0x0f && 
opcode_size == 010.2k
) {
766
10.2k
    uint8_t b2 = m_cur_insn[1];
767
10.2k
    switch (b2) {
768
18
      case 0x87: // JA/JNBE rel16/rel32
769
30
      case 0x86: // JBE/JNA rel16/rel32
770
1.50k
      case 0x84: // JE/JZ rel16/rel32
771
1.56k
      case 0x8f: // JG/JNLE rel16/rel32
772
1.91k
      case 0x8d: // JNL/JGE rel16/rel32
773
2.25k
      case 0x8e: // JLE rel16/rel32
774
2.39k
      case 0x82: // JB/JC/JNAE rel16/rel32
775
2.44k
      case 0x83: // JAE/JNB/JNC rel16/rel32
776
4.38k
      case 0x85: // JNE/JNZ rel16/rel32
777
4.42k
      case 0x8c: // JL/JNGE rel16/rel32
778
4.42k
      case 0x81: // JNO rel16/rel32
779
4.42k
      case 0x8b: // JNP/JPO rel16/rel32
780
4.42k
      case 0x89: // JNS rel16/rel32
781
4.42k
      case 0x80: // JO rel16/rel32
782
4.42k
      case 0x8a: // JP rel16/rel32
783
4.42k
      case 0x88: // JS rel16/rel32
784
4.42k
        opcode_size = 2;
785
4.42k
        break;
786
5.78k
      default:
787
5.78k
        break;
788
10.2k
    }
789
10.2k
  }
790
791
332k
  if (opcode_size == 0)
792
297k
    return false;
793
794
34.6k
  offset = 0;
795
34.6k
  if (instruction_length - opcode_size == 1) {
796
10.6k
    int8_t rel8 = (int8_t) *(m_cur_insn + opcode_size);
797
10.6k
    offset = rel8;
798
24.0k
  } else if (instruction_length - opcode_size == 2) {
799
0
    int16_t rel16 = extract_2_signed (m_cur_insn + opcode_size);
800
0
    offset = rel16;
801
24.0k
  } else if (instruction_length - opcode_size == 4) {
802
24.0k
    int32_t rel32 = extract_4_signed (m_cur_insn + opcode_size);
803
24.0k
    offset = rel32;
804
24.0k
  } else {
805
0
    return false;
806
0
  }
807
34.6k
  return true;
808
34.6k
}
809
810
// Returns true if this instruction is a intra-function branch or jump -
811
// a branch/jump within the bounds of this same function.
812
// Cannot predict where a jump through a register value ("jmpq *%rax")
813
// will go, so it will return false on that instruction.
814
bool x86AssemblyInspectionEngine::local_branch_p (
815
    const addr_t current_func_text_offset,
816
    const AddressRange &func_range,
817
    const int instruction_length,
818
17.3k
    addr_t &target_insn_offset) {
819
17.3k
  int offset;
820
17.3k
  if (pc_rel_branch_or_jump_p (instruction_length, offset) && offset != 0) {
821
9.13k
    addr_t next_pc_value = current_func_text_offset + instruction_length;
822
9.13k
    if (offset < 0 && 
addr_t(-offset) > current_func_text_offset3.01k
) {
823
      // Branch target is before the start of this function
824
5
      return false;
825
5
    }
826
9.13k
    if (offset + next_pc_value > func_range.GetByteSize()) {
827
      // Branch targets outside this function's bounds
828
3
      return false;
829
3
    }
830
    // This instruction branches to target_insn_offset (byte offset into the function)
831
9.12k
    target_insn_offset = next_pc_value + offset;
832
9.12k
    return true;
833
9.13k
  }
834
8.19k
  return false;
835
17.3k
}
836
837
// Returns true if this instruction is a inter-function branch or jump - a
838
// branch/jump to another function.
839
// Cannot predict where a jump through a register value ("jmpq *%rax")
840
// will go, so it will return false on that instruction.
841
bool x86AssemblyInspectionEngine::non_local_branch_p (
842
    const addr_t current_func_text_offset,
843
    const AddressRange &func_range,
844
314k
    const int instruction_length) {
845
314k
  int offset;
846
314k
  addr_t target_insn_offset;
847
314k
  if (pc_rel_branch_or_jump_p (instruction_length, offset)) {
848
17.3k
    return !local_branch_p(current_func_text_offset,func_range,instruction_length,target_insn_offset);
849
17.3k
  }
850
297k
  return false;
851
314k
}
852
853
// ret [0xc3] or [0xcb] or [0xc2 imm16] or [0xca imm16]
854
339k
bool x86AssemblyInspectionEngine::ret_pattern_p() {
855
339k
  uint8_t *p = m_cur_insn;
856
339k
  return *p == 0xc3 || 
*p == 0xc2327k
||
*p == 0xca327k
||
*p == 0xcb327k
;
857
339k
}
858
859
0
uint16_t x86AssemblyInspectionEngine::extract_2(uint8_t *b) {
860
0
  uint16_t v = 0;
861
0
  for (int i = 1; i >= 0; i--)
862
0
    v = (v << 8) | b[i];
863
0
  return v;
864
0
}
865
866
0
int16_t x86AssemblyInspectionEngine::extract_2_signed(uint8_t *b) {
867
0
  int16_t v = 0;
868
0
  for (int i = 1; i >= 0; i--)
869
0
    v = (v << 8) | b[i];
870
0
  return v;
871
0
}
872
873
25.6k
uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) {
874
25.6k
  uint32_t v = 0;
875
128k
  for (int i = 3; i >= 0; 
i--102k
)
876
102k
    v = (v << 8) | b[i];
877
25.6k
  return v;
878
25.6k
}
879
880
24.0k
int32_t x86AssemblyInspectionEngine::extract_4_signed(uint8_t *b) {
881
24.0k
  int32_t v = 0;
882
120k
  for (int i = 3; i >= 0; 
i--96.2k
)
883
96.2k
    v = (v << 8) | b[i];
884
24.0k
  return v;
885
24.0k
}
886
887
888
bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p,
889
                                                     int &length, 
890
410k
                                                     uint32_t buffer_remaining_bytes) {
891
892
410k
  uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize());
893
410k
  llvm::SmallVector<uint8_t, 32> opcode_data;
894
410k
  opcode_data.resize(max_op_byte_size);
895
896
410k
  char out_string[512];
897
410k
  const size_t inst_size =
898
410k
      ::LLVMDisasmInstruction(m_disasm_context, insn_p, max_op_byte_size, 0,
899
410k
                              out_string, sizeof(out_string));
900
901
410k
  length = inst_size;
902
410k
  return true;
903
410k
}
904
905
bool x86AssemblyInspectionEngine::machine_regno_to_lldb_regno(
906
55.8k
    int machine_regno, uint32_t &lldb_regno) {
907
55.8k
  MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.find(machine_regno);
908
55.8k
  if (it != m_reg_map.end()) {
909
55.8k
    lldb_regno = it->second.lldb_regnum;
910
55.8k
    return true;
911
55.8k
  }
912
0
  return false;
913
55.8k
}
914
915
bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
916
    uint8_t *data, size_t size, AddressRange &func_range,
917
10.9k
    UnwindPlan &unwind_plan) {
918
10.9k
  unwind_plan.Clear();
919
920
10.9k
  if (data == nullptr || size == 0)
921
0
    return false;
922
923
10.9k
  if (!m_register_map_initialized)
924
0
    return false;
925
926
10.9k
  addr_t current_func_text_offset = 0;
927
10.9k
  int current_sp_bytes_offset_from_fa = 0;
928
10.9k
  bool is_aligned = false;
929
10.9k
  UnwindPlan::Row::RegisterLocation initial_regloc;
930
10.9k
  UnwindPlan::RowSP row(new UnwindPlan::Row);
931
932
10.9k
  unwind_plan.SetPlanValidAddressRange(func_range);
933
10.9k
  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
934
935
  // At the start of the function, find the CFA by adding wordsize to the SP
936
  // register
937
10.9k
  row->SetOffset(current_func_text_offset);
938
10.9k
  row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize);
939
940
  // caller's stack pointer value before the call insn is the CFA address
941
10.9k
  initial_regloc.SetIsCFAPlusOffset(0);
942
10.9k
  row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
943
944
  // saved instruction pointer can be found at CFA - wordsize.
945
10.9k
  current_sp_bytes_offset_from_fa = m_wordsize;
946
10.9k
  initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
947
10.9k
  row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
948
949
10.9k
  unwind_plan.AppendRow(row);
950
951
  // Allocate a new Row, populate it with the existing Row contents.
952
10.9k
  UnwindPlan::Row *newrow = new UnwindPlan::Row;
953
10.9k
  *newrow = *row.get();
954
10.9k
  row.reset(newrow);
955
956
  // Track which registers have been saved so far in the prologue. If we see
957
  // another push of that register, it's not part of the prologue. The register
958
  // numbers used here are the machine register #'s (i386_register_numbers,
959
  // x86_64_register_numbers).
960
10.9k
  std::vector<bool> saved_registers(32, false);
961
962
  // Once the prologue has completed we'll save a copy of the unwind
963
  // instructions If there is an epilogue in the middle of the function, after
964
  // that epilogue we'll reinstate the unwind setup -- we assume that some code
965
  // path jumps over the mid-function epilogue
966
967
10.9k
  UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
968
10.9k
  int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
969
                                                   // epilogue started executed
970
10.9k
  bool prologue_completed_is_aligned;
971
10.9k
  std::vector<bool> prologue_completed_saved_registers;
972
973
421k
  while (current_func_text_offset < size) {
974
410k
    int stack_offset, insn_len;
975
410k
    int machine_regno;   // register numbers masked directly out of instructions
976
410k
    uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB
977
                         // numbering scheme
978
979
410k
    bool in_epilogue = false; // we're in the middle of an epilogue sequence
980
410k
    bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
981
982
410k
    m_cur_insn = data + current_func_text_offset;
983
410k
    if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset)
984
410k
        || insn_len == 0 
985
410k
        || 
insn_len > kMaxInstructionByteSize410k
) {
986
      // An unrecognized/junk instruction
987
71
      break;
988
71
    }
989
990
410k
    auto &cfa_value = row->GetCFAValue();
991
410k
    auto &afa_value = row->GetAFAValue();
992
410k
    auto fa_value_ptr = is_aligned ? 
&afa_value23.4k
:
&cfa_value387k
;
993
994
410k
    if (mov_rsp_rbp_pattern_p()) {
995
8.17k
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
996
8.17k
        fa_value_ptr->SetIsRegisterPlusOffset(
997
8.17k
            m_lldb_fp_regnum, fa_value_ptr->GetOffset());
998
8.17k
        row_updated = true;
999
8.17k
      }
1000
8.17k
    }
1001
1002
402k
    else if (mov_rsp_rbx_pattern_p()) {
1003
1
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1004
1
        fa_value_ptr->SetIsRegisterPlusOffset(
1005
1
            m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
1006
1
        row_updated = true;
1007
1
      }
1008
1
    }
1009
1010
402k
    else if (and_rsp_pattern_p()) {
1011
2.33k
      current_sp_bytes_offset_from_fa = 0;
1012
2.33k
      afa_value.SetIsRegisterPlusOffset(
1013
2.33k
          m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
1014
2.33k
      fa_value_ptr = &afa_value;
1015
2.33k
      is_aligned = true;
1016
2.33k
      row_updated = true;
1017
2.33k
    }
1018
1019
400k
    else if (mov_rbp_rsp_pattern_p()) {
1020
2.34k
      if (is_aligned && 
cfa_value.GetRegisterNumber() == m_lldb_fp_regnum2.32k
)
1021
2.32k
      {
1022
2.32k
        is_aligned = false;
1023
2.32k
        fa_value_ptr = &cfa_value;
1024
2.32k
        afa_value.SetUnspecified();
1025
2.32k
        row_updated = true;
1026
2.32k
      }
1027
2.34k
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
1028
2.34k
        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1029
2.34k
    }
1030
1031
397k
    else if (mov_rbx_rsp_pattern_p()) {
1032
1
      if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
1033
1
      {
1034
1
        is_aligned = false;
1035
1
        fa_value_ptr = &cfa_value;
1036
1
        afa_value.SetUnspecified();
1037
1
        row_updated = true;
1038
1
      }
1039
1
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
1040
1
        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1041
1
    }
1042
1043
    // This is the start() function (or a pthread equivalent), it starts with a
1044
    // pushl $0x0 which puts the saved pc value of 0 on the stack.  In this
1045
    // case we want to pretend we didn't see a stack movement at all --
1046
    // normally the saved pc value is already on the stack by the time the
1047
    // function starts executing.
1048
397k
    else if (push_0_pattern_p()) {
1049
2.49k
    }
1050
1051
395k
    else if (push_reg_p(machine_regno)) {
1052
8.48k
      current_sp_bytes_offset_from_fa += m_wordsize;
1053
      // the PUSH instruction has moved the stack pointer - if the FA is set
1054
      // in terms of the stack pointer, we need to add a new row of
1055
      // instructions.
1056
8.48k
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1057
5.91k
        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1058
5.91k
        row_updated = true;
1059
5.91k
      }
1060
      // record where non-volatile (callee-saved, spilled) registers are saved
1061
      // on the stack
1062
8.48k
      if (nonvolatile_reg_p(machine_regno) &&
1063
8.48k
          
machine_regno_to_lldb_regno(machine_regno, lldb_regno)6.12k
&&
1064
8.48k
          
!saved_registers[machine_regno]6.12k
) {
1065
6.10k
        UnwindPlan::Row::RegisterLocation regloc;
1066
6.10k
        if (is_aligned)
1067
1
            regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
1068
6.10k
        else
1069
6.10k
            regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
1070
6.10k
        row->SetRegisterInfo(lldb_regno, regloc);
1071
6.10k
        saved_registers[machine_regno] = true;
1072
6.10k
        row_updated = true;
1073
6.10k
      }
1074
8.48k
    }
1075
1076
386k
    else if (pop_reg_p(machine_regno)) {
1077
8.18k
      current_sp_bytes_offset_from_fa -= m_wordsize;
1078
1079
8.18k
      if (nonvolatile_reg_p(machine_regno) &&
1080
8.18k
          
machine_regno_to_lldb_regno(machine_regno, lldb_regno)5.83k
&&
1081
8.18k
          
saved_registers[machine_regno]5.83k
) {
1082
5.83k
        saved_registers[machine_regno] = false;
1083
5.83k
        row->RemoveRegisterInfo(lldb_regno);
1084
1085
5.83k
        if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
1086
5.65k
          fa_value_ptr->SetIsRegisterPlusOffset(
1087
5.65k
              m_lldb_sp_regnum, fa_value_ptr->GetOffset());
1088
5.65k
        }
1089
1090
5.83k
        in_epilogue = true;
1091
5.83k
        row_updated = true;
1092
5.83k
      }
1093
1094
      // the POP instruction has moved the stack pointer - if the FA is set in
1095
      // terms of the stack pointer, we need to add a new row of instructions.
1096
8.18k
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1097
8.03k
        fa_value_ptr->SetIsRegisterPlusOffset(
1098
8.03k
            m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
1099
8.03k
        row_updated = true;
1100
8.03k
      }
1101
8.18k
    }
1102
1103
378k
    else if (pop_misc_reg_p()) {
1104
3
      current_sp_bytes_offset_from_fa -= m_wordsize;
1105
3
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1106
3
        fa_value_ptr->SetIsRegisterPlusOffset(
1107
3
            m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
1108
3
        row_updated = true;
1109
3
      }
1110
3
    }
1111
1112
    // The LEAVE instruction moves the value from rbp into rsp and pops a value
1113
    // off the stack into rbp (restoring the caller's rbp value). It is the
1114
    // opposite of ENTER, or 'push rbp, mov rsp rbp'.
1115
378k
    else if (leave_pattern_p()) {
1116
84
      if (saved_registers[m_machine_fp_regnum]) {
1117
84
        saved_registers[m_machine_fp_regnum] = false;
1118
84
        row->RemoveRegisterInfo(m_lldb_fp_regnum);
1119
1120
84
        row_updated = true;
1121
84
      }
1122
1123
84
      if (is_aligned && 
cfa_value.GetRegisterNumber() == m_lldb_fp_regnum0
)
1124
0
      {
1125
0
        is_aligned = false;
1126
0
        fa_value_ptr = &cfa_value;
1127
0
        afa_value.SetUnspecified();
1128
0
        row_updated = true;
1129
0
      }
1130
1131
84
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
1132
82
      {
1133
82
        fa_value_ptr->SetIsRegisterPlusOffset(
1134
82
            m_lldb_sp_regnum, fa_value_ptr->GetOffset());
1135
1136
82
        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1137
82
      }
1138
1139
84
      current_sp_bytes_offset_from_fa -= m_wordsize;
1140
1141
84
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1142
84
        fa_value_ptr->SetIsRegisterPlusOffset(
1143
84
            m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
1144
84
        row_updated = true;
1145
84
      }
1146
1147
84
      in_epilogue = true;
1148
84
    }
1149
1150
378k
    else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
1151
378k
             
nonvolatile_reg_p(machine_regno)36.1k
&&
1152
378k
             
machine_regno_to_lldb_regno(machine_regno, lldb_regno)64
&&
1153
378k
             
!saved_registers[machine_regno]64
) {
1154
17
      saved_registers[machine_regno] = true;
1155
1156
17
      UnwindPlan::Row::RegisterLocation regloc;
1157
1158
      // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
1159
      // want to express this as the offset from the FA.  If the frame base is
1160
      // rbp (like the above instruction), the FA offset for rbp is probably
1161
      // 16.  So we want to say that the value is stored at the FA address -
1162
      // 96.
1163
17
      if (is_aligned)
1164
1
          regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
1165
16
      else
1166
16
          regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
1167
1168
17
      row->SetRegisterInfo(lldb_regno, regloc);
1169
1170
17
      row_updated = true;
1171
17
    }
1172
1173
378k
    else if (sub_rsp_pattern_p(stack_offset)) {
1174
4.85k
      current_sp_bytes_offset_from_fa += stack_offset;
1175
4.85k
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1176
2.37k
        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1177
2.37k
        row_updated = true;
1178
2.37k
      }
1179
4.85k
    }
1180
1181
373k
    else if (add_rsp_pattern_p(stack_offset)) {
1182
6.99k
      current_sp_bytes_offset_from_fa -= stack_offset;
1183
6.99k
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1184
53
        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1185
53
        row_updated = true;
1186
53
      }
1187
6.99k
      in_epilogue = true;
1188
6.99k
    }
1189
1190
366k
    else if (push_extended_pattern_p() || 
push_imm_pattern_p()366k
||
1191
366k
             
push_misc_reg_p()366k
) {
1192
25
      current_sp_bytes_offset_from_fa += m_wordsize;
1193
25
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1194
18
        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1195
18
        row_updated = true;
1196
18
      }
1197
25
    }
1198
1199
366k
    else if (lea_rsp_pattern_p(stack_offset)) {
1200
0
      current_sp_bytes_offset_from_fa -= stack_offset;
1201
0
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1202
0
        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1203
0
        row_updated = true;
1204
0
      }
1205
0
      if (stack_offset > 0)
1206
0
        in_epilogue = true;
1207
0
    }
1208
1209
366k
    else if (lea_rbp_rsp_pattern_p(stack_offset)) {
1210
5
      if (is_aligned &&
1211
5
          
cfa_value.GetRegisterNumber() == m_lldb_fp_regnum4
) {
1212
4
        is_aligned = false;
1213
4
        fa_value_ptr = &cfa_value;
1214
4
        afa_value.SetUnspecified();
1215
4
        row_updated = true;
1216
4
      }
1217
5
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
1218
5
        current_sp_bytes_offset_from_fa =
1219
5
          fa_value_ptr->GetOffset() - stack_offset;
1220
5
      }
1221
5
    }
1222
1223
366k
    else if (lea_rbx_rsp_pattern_p(stack_offset)) {
1224
0
      if (is_aligned &&
1225
0
          cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1226
0
        is_aligned = false;
1227
0
        fa_value_ptr = &cfa_value;
1228
0
        afa_value.SetUnspecified();
1229
0
        row_updated = true;
1230
0
      }
1231
0
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
1232
0
        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
1233
0
      }
1234
0
    }
1235
1236
366k
    else if (prologue_completed_row.get() && 
1237
366k
             
(320k
ret_pattern_p()320k
||
1238
320k
              
non_local_branch_p (current_func_text_offset, func_range, insn_len)314k
||
1239
320k
              
jmp_to_reg_p()306k
)) {
1240
      // Check if the current instruction is the end of an epilogue sequence,
1241
      // and if so, re-instate the prologue-completed unwind state.
1242
1243
      // The current instruction is a branch/jump outside this function, 
1244
      // a ret, or a jump through a register value which we cannot 
1245
      // determine the effcts of.  Verify that the stack frame state 
1246
      // has been unwound to the same as it was at function entry to avoid 
1247
      // mis-identifying a JMP instruction as an epilogue.
1248
18.6k
      UnwindPlan::Row::RegisterLocation sp, pc;
1249
18.6k
      if (row->GetRegisterInfo(m_lldb_sp_regnum, sp) &&
1250
18.6k
          row->GetRegisterInfo(m_lldb_ip_regnum, pc)) {
1251
        // Any ret instruction variant is definitely indicative of an
1252
        // epilogue; for other insn patterns verify that we're back to
1253
        // the original unwind state.
1254
18.6k
        if (ret_pattern_p() ||
1255
18.6k
            
(12.8k
sp.IsCFAPlusOffset()12.8k
&&
sp.GetOffset() == 012.8k
&&
1256
18.6k
            
pc.IsAtCFAPlusOffset()12.8k
&&
pc.GetOffset() == -m_wordsize12.8k
)) {
1257
          // Reinstate the saved prologue setup for any instructions that come
1258
          // after the epilogue
1259
1260
18.6k
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
1261
18.6k
          *newrow = *prologue_completed_row.get();
1262
18.6k
          row.reset(newrow);
1263
18.6k
          current_sp_bytes_offset_from_fa =
1264
18.6k
              prologue_completed_sp_bytes_offset_from_cfa;
1265
18.6k
          is_aligned = prologue_completed_is_aligned;
1266
1267
18.6k
          saved_registers.clear();
1268
18.6k
          saved_registers.resize(prologue_completed_saved_registers.size(), false);
1269
614k
          for (size_t i = 0; i < prologue_completed_saved_registers.size(); 
++i595k
) {
1270
595k
            saved_registers[i] = prologue_completed_saved_registers[i];
1271
595k
          }
1272
1273
18.6k
          in_epilogue = true;
1274
18.6k
          row_updated = true;
1275
18.6k
        }
1276
18.6k
      }
1277
18.6k
    }
1278
1279
    // call next instruction
1280
    //     call 0
1281
    //  => pop  %ebx
1282
    // This is used in i386 programs to get the PIC base address for finding
1283
    // global data
1284
348k
    else if (call_next_insn_pattern_p()) {
1285
4
      current_sp_bytes_offset_from_fa += m_wordsize;
1286
4
      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
1287
3
        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1288
3
        row_updated = true;
1289
3
      }
1290
4
    }
1291
1292
410k
    if (row_updated) {
1293
48.3k
      if (current_func_text_offset + insn_len < size) {
1294
41.0k
        row->SetOffset(current_func_text_offset + insn_len);
1295
41.0k
        unwind_plan.AppendRow(row);
1296
        // Allocate a new Row, populate it with the existing Row contents.
1297
41.0k
        newrow = new UnwindPlan::Row;
1298
41.0k
        *newrow = *row.get();
1299
41.0k
        row.reset(newrow);
1300
41.0k
      }
1301
48.3k
    }
1302
1303
410k
    if (!in_epilogue && 
row_updated379k
) {
1304
      // If we're not in an epilogue sequence, save the updated Row
1305
23.7k
      UnwindPlan::Row *newrow = new UnwindPlan::Row;
1306
23.7k
      *newrow = *row.get();
1307
23.7k
      prologue_completed_row.reset(newrow);
1308
1309
23.7k
      prologue_completed_saved_registers.clear();
1310
23.7k
      prologue_completed_saved_registers.resize(saved_registers.size(), false);
1311
783k
      for (size_t i = 0; i < saved_registers.size(); 
++i759k
) {
1312
759k
        prologue_completed_saved_registers[i] = saved_registers[i];
1313
759k
      }
1314
23.7k
    }
1315
1316
    // We may change the sp value without adding a new Row necessarily -- keep
1317
    // track of it either way.
1318
410k
    if (!in_epilogue) {
1319
379k
      prologue_completed_sp_bytes_offset_from_cfa =
1320
379k
          current_sp_bytes_offset_from_fa;
1321
379k
      prologue_completed_is_aligned = is_aligned;
1322
379k
    }
1323
1324
410k
    m_cur_insn = m_cur_insn + insn_len;
1325
410k
    current_func_text_offset += insn_len;
1326
410k
  }
1327
1328
10.9k
  unwind_plan.SetSourceName("assembly insn profiling");
1329
10.9k
  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1330
10.9k
  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1331
10.9k
  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1332
1333
10.9k
  return true;
1334
10.9k
}
1335
1336
bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
1337
    uint8_t *data, size_t size, AddressRange &func_range,
1338
11
    UnwindPlan &unwind_plan, RegisterContextSP &reg_ctx) {
1339
11
  Address addr_start = func_range.GetBaseAddress();
1340
11
  if (!addr_start.IsValid())
1341
0
    return false;
1342
1343
  // We either need a live RegisterContext, or we need the UnwindPlan to
1344
  // already be in the lldb register numbering scheme.
1345
11
  if (reg_ctx.get() == nullptr &&
1346
11
      
unwind_plan.GetRegisterKind() != eRegisterKindLLDB3
)
1347
0
    return false;
1348
1349
  // Is original unwind_plan valid?
1350
  // unwind_plan should have at least one row which is ABI-default (CFA
1351
  // register is sp), and another row in mid-function.
1352
11
  if (unwind_plan.GetRowCount() < 2)
1353
3
    return false;
1354
1355
8
  UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex(0);
1356
8
  if (first_row->GetOffset() != 0)
1357
0
    return false;
1358
8
  uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber();
1359
8
  if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1360
5
    cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1361
5
        unwind_plan.GetRegisterKind(),
1362
5
        first_row->GetCFAValue().GetRegisterNumber());
1363
5
  }
1364
8
  if (cfa_reg != m_lldb_sp_regnum ||
1365
8
      first_row->GetCFAValue().GetOffset() != m_wordsize)
1366
0
    return false;
1367
1368
8
  UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset(-1);
1369
1370
8
  size_t offset = 0;
1371
8
  int row_id = 1;
1372
8
  bool unwind_plan_updated = false;
1373
8
  UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
1374
1375
  // After a mid-function epilogue we will need to re-insert the original
1376
  // unwind rules so unwinds work for the remainder of the function.  These
1377
  // aren't common with clang/gcc on x86 but it is possible.
1378
8
  bool reinstate_unwind_state = false;
1379
1380
98
  while (offset < size) {
1381
90
    m_cur_insn = data + offset;
1382
90
    int insn_len;
1383
90
    if (!instruction_length(m_cur_insn, insn_len, size - offset) ||
1384
90
        insn_len == 0 || insn_len > kMaxInstructionByteSize) {
1385
      // An unrecognized/junk instruction.
1386
0
      break;
1387
0
    }
1388
1389
    // Advance offsets.
1390
90
    offset += insn_len;
1391
1392
    // offset is pointing beyond the bounds of the function; stop looping.
1393
90
    if (offset >= size)
1394
8
      continue;
1395
1396
82
    if (reinstate_unwind_state) {
1397
0
      UnwindPlan::RowSP new_row(new UnwindPlan::Row());
1398
0
      *new_row = *original_last_row;
1399
0
      new_row->SetOffset(offset);
1400
0
      unwind_plan.AppendRow(new_row);
1401
0
      row = std::make_shared<UnwindPlan::Row>();
1402
0
      *row = *new_row;
1403
0
      reinstate_unwind_state = false;
1404
0
      unwind_plan_updated = true;
1405
0
      continue;
1406
0
    }
1407
1408
    // If we already have one row for this instruction, we can continue.
1409
101
    
while (82
row_id < unwind_plan.GetRowCount() &&
1410
101
           
unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset30
) {
1411
19
      row_id++;
1412
19
    }
1413
82
    UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex(row_id - 1);
1414
82
    if (original_row->GetOffset() == offset) {
1415
17
      *row = *original_row;
1416
17
      continue;
1417
17
    }
1418
1419
65
    if (row_id == 0) {
1420
      // If we are here, compiler didn't generate CFI for prologue. This won't
1421
      // happen to GCC or clang. In this case, bail out directly.
1422
0
      return false;
1423
0
    }
1424
1425
    // Inspect the instruction to check if we need a new row for it.
1426
65
    cfa_reg = row->GetCFAValue().GetRegisterNumber();
1427
65
    if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) {
1428
56
      cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1429
56
          unwind_plan.GetRegisterKind(),
1430
56
          row->GetCFAValue().GetRegisterNumber());
1431
56
    }
1432
65
    if (cfa_reg == m_lldb_sp_regnum) {
1433
      // CFA register is sp.
1434
1435
      // call next instruction
1436
      //     call 0
1437
      //  => pop  %ebx
1438
5
      if (call_next_insn_pattern_p()) {
1439
0
        row->SetOffset(offset);
1440
0
        row->GetCFAValue().IncOffset(m_wordsize);
1441
1442
0
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1443
0
        unwind_plan.InsertRow(new_row);
1444
0
        unwind_plan_updated = true;
1445
0
        continue;
1446
0
      }
1447
1448
      // push/pop register
1449
5
      int regno;
1450
5
      if (push_reg_p(regno)) {
1451
0
        row->SetOffset(offset);
1452
0
        row->GetCFAValue().IncOffset(m_wordsize);
1453
1454
0
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1455
0
        unwind_plan.InsertRow(new_row);
1456
0
        unwind_plan_updated = true;
1457
0
        continue;
1458
0
      }
1459
5
      if (pop_reg_p(regno)) {
1460
        // Technically, this might be a nonvolatile register recover in
1461
        // epilogue. We should reset RegisterInfo for the register. But in
1462
        // practice, previous rule for the register is still valid... So we
1463
        // ignore this case.
1464
1465
1
        row->SetOffset(offset);
1466
1
        row->GetCFAValue().IncOffset(-m_wordsize);
1467
1468
1
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1469
1
        unwind_plan.InsertRow(new_row);
1470
1
        unwind_plan_updated = true;
1471
1
        continue;
1472
1
      }
1473
1474
4
      if (pop_misc_reg_p()) {
1475
0
        row->SetOffset(offset);
1476
0
        row->GetCFAValue().IncOffset(-m_wordsize);
1477
1478
0
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1479
0
        unwind_plan.InsertRow(new_row);
1480
0
        unwind_plan_updated = true;
1481
0
        continue;
1482
0
      }
1483
1484
      // push imm
1485
4
      if (push_imm_pattern_p()) {
1486
0
        row->SetOffset(offset);
1487
0
        row->GetCFAValue().IncOffset(m_wordsize);
1488
0
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1489
0
        unwind_plan.InsertRow(new_row);
1490
0
        unwind_plan_updated = true;
1491
0
        continue;
1492
0
      }
1493
1494
      // push extended
1495
4
      if (push_extended_pattern_p() || push_misc_reg_p()) {
1496
0
        row->SetOffset(offset);
1497
0
        row->GetCFAValue().IncOffset(m_wordsize);
1498
0
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1499
0
        unwind_plan.InsertRow(new_row);
1500
0
        unwind_plan_updated = true;
1501
0
        continue;
1502
0
      }
1503
1504
      // add/sub %rsp/%esp
1505
4
      int amount;
1506
4
      if (add_rsp_pattern_p(amount)) {
1507
1
        row->SetOffset(offset);
1508
1
        row->GetCFAValue().IncOffset(-amount);
1509
1510
1
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1511
1
        unwind_plan.InsertRow(new_row);
1512
1
        unwind_plan_updated = true;
1513
1
        continue;
1514
1
      }
1515
3
      if (sub_rsp_pattern_p(amount)) {
1516
1
        row->SetOffset(offset);
1517
1
        row->GetCFAValue().IncOffset(amount);
1518
1519
1
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1520
1
        unwind_plan.InsertRow(new_row);
1521
1
        unwind_plan_updated = true;
1522
1
        continue;
1523
1
      }
1524
1525
      // lea %rsp, [%rsp + $offset]
1526
2
      if (lea_rsp_pattern_p(amount)) {
1527
0
        row->SetOffset(offset);
1528
0
        row->GetCFAValue().IncOffset(-amount);
1529
1530
0
        UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1531
0
        unwind_plan.InsertRow(new_row);
1532
0
        unwind_plan_updated = true;
1533
0
        continue;
1534
0
      }
1535
1536
2
      if (ret_pattern_p()) {
1537
0
        reinstate_unwind_state = true;
1538
0
        continue;
1539
0
      }
1540
60
    } else if (cfa_reg == m_lldb_fp_regnum) {
1541
      // CFA register is fp.
1542
1543
      // The only case we care about is epilogue:
1544
      //     [0x5d] pop %rbp/%ebp
1545
      //  => [0xc3] ret
1546
60
      if (pop_rbp_pattern_p() || 
leave_pattern_p()54
) {
1547
6
        m_cur_insn++;
1548
6
        if (ret_pattern_p()) {
1549
6
          row->SetOffset(offset);
1550
6
          row->GetCFAValue().SetIsRegisterPlusOffset(
1551
6
              first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
1552
1553
6
          UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
1554
6
          unwind_plan.InsertRow(new_row);
1555
6
          unwind_plan_updated = true;
1556
6
          reinstate_unwind_state = true;
1557
6
          continue;
1558
6
        }
1559
6
      }
1560
60
    } else {
1561
      // CFA register is not sp or fp.
1562
1563
      // This must be hand-written assembly.
1564
      // Just trust eh_frame and assume we have finished.
1565
0
      break;
1566
0
    }
1567
65
  }
1568
1569
8
  unwind_plan.SetPlanValidAddressRange(func_range);
1570
8
  if (unwind_plan_updated) {
1571
7
    std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString());
1572
7
    unwind_plan_source += " plus augmentation from assembly parsing";
1573
7
    unwind_plan.SetSourceName(unwind_plan_source.c_str());
1574
7
    unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1575
7
    unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1576
7
  }
1577
8
  return true;
1578
8
}
1579
1580
bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
1581
0
    uint8_t *data, size_t size, size_t &offset) {
1582
0
  offset = 0;
1583
1584
0
  if (!m_register_map_initialized)
1585
0
    return false;
1586
1587
0
  while (offset < size) {
1588
0
    int regno;
1589
0
    int insn_len;
1590
0
    int scratch;
1591
1592
0
    m_cur_insn = data + offset;
1593
0
    if (!instruction_length(m_cur_insn, insn_len, size - offset) 
1594
0
        || insn_len > kMaxInstructionByteSize 
1595
0
        || insn_len == 0) {
1596
      // An error parsing the instruction, i.e. probably data/garbage - stop
1597
      // scanning
1598
0
      break;
1599
0
    }
1600
1601
0
    if (push_rbp_pattern_p() || mov_rsp_rbp_pattern_p() ||
1602
0
        sub_rsp_pattern_p(scratch) || push_reg_p(regno) ||
1603
0
        mov_reg_to_local_stack_frame_p(regno, scratch) ||
1604
0
        (lea_rsp_pattern_p(scratch) && offset == 0)) {
1605
0
      offset += insn_len;
1606
0
      continue;
1607
0
    }
1608
    //
1609
    // Unknown non-prologue instruction - stop scanning
1610
0
    break;
1611
0
  }
1612
1613
0
  return true;
1614
0
}