1 //===-- Testx86AssemblyInspectionEngine.cpp ---------------------------*- C++
2 //-*-===//
3 
4 //
5 //                     The LLVM Compiler Infrastructure
6 //
7 // This file is distributed under the University of Illinois Open Source
8 // License. See LICENSE.TXT for details.
9 //
10 //===----------------------------------------------------------------------===//
11 
12 #include "gtest/gtest.h"
13 
14 #include <vector>
15 
16 #include "Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h"
17 #include "lldb/Core/Address.h"
18 #include "lldb/Core/AddressRange.h"
19 #include "lldb/Core/ArchSpec.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Utility/StreamString.h"
22 
23 #include "llvm/Support/TargetSelect.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 
28 class Testx86AssemblyInspectionEngine : public testing::Test {
29 public:
30   static void SetUpTestCase();
31 
32   //  static void TearDownTestCase() { }
33 
34   //  virtual void SetUp() override { }
35 
36   //  virtual void TearDown() override { }
37 
38 protected:
39 };
40 
41 void Testx86AssemblyInspectionEngine::SetUpTestCase() {
42   llvm::InitializeAllTargets();
43   llvm::InitializeAllAsmPrinters();
44   llvm::InitializeAllTargetMCs();
45   llvm::InitializeAllDisassemblers();
46 }
47 
48 // only defining the register names / numbers that the unwinder is actually
49 // using today
50 
51 // names should match the constants below.  These will be the eRegisterKindLLDB
52 // register numbers.
53 
54 const char *x86_64_reg_names[] = {"rax", "rbx", "rcx", "rdx", "rsp", "rbp",
55                                   "rsi", "rdi", "r8",  "r9",  "r10", "r11",
56                                   "r12", "r13", "r14", "r15", "rip"};
57 
58 enum x86_64_regs {
59   k_rax = 0,
60   k_rbx = 1,
61   k_rcx = 2,
62   k_rdx = 3,
63   k_rsp = 4,
64   k_rbp = 5,
65   k_rsi = 6,
66   k_rdi = 7,
67   k_r8 = 8,
68   k_r9 = 9,
69   k_r10 = 10,
70   k_r11 = 11,
71   k_r12 = 12,
72   k_r13 = 13,
73   k_r14 = 14,
74   k_r15 = 15,
75   k_rip = 16
76 };
77 
78 // names should match the constants below.  These will be the eRegisterKindLLDB
79 // register numbers.
80 
81 const char *i386_reg_names[] = {"eax", "ecx", "edx", "ebx", "esp",
82                                 "ebp", "esi", "edi", "eip"};
83 
84 enum i386_regs {
85   k_eax = 0,
86   k_ecx = 1,
87   k_edx = 2,
88   k_ebx = 3,
89   k_esp = 4,
90   k_ebp = 5,
91   k_esi = 6,
92   k_edi = 7,
93   k_eip = 8
94 };
95 
96 std::unique_ptr<x86AssemblyInspectionEngine> Getx86_64Inspector() {
97 
98   ArchSpec arch("x86_64-apple-macosx");
99   std::unique_ptr<x86AssemblyInspectionEngine> engine(
100       new x86AssemblyInspectionEngine(arch));
101 
102   std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;
103   int i = 0;
104   for (const auto &name : x86_64_reg_names) {
105     x86AssemblyInspectionEngine::lldb_reg_info ri;
106     ri.name = name;
107     ri.lldb_regnum = i++;
108     lldb_regnums.push_back(ri);
109   }
110 
111   engine->Initialize(lldb_regnums);
112   return engine;
113 }
114 
115 std::unique_ptr<x86AssemblyInspectionEngine> Geti386Inspector() {
116 
117   ArchSpec arch("i386-apple-macosx");
118   std::unique_ptr<x86AssemblyInspectionEngine> engine(
119       new x86AssemblyInspectionEngine(arch));
120 
121   std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;
122   int i = 0;
123   for (const auto &name : i386_reg_names) {
124     x86AssemblyInspectionEngine::lldb_reg_info ri;
125     ri.name = name;
126     ri.lldb_regnum = i++;
127     lldb_regnums.push_back(ri);
128   }
129 
130   engine->Initialize(lldb_regnums);
131   return engine;
132 }
133 
134 namespace lldb_private {
135 static std::ostream &operator<<(std::ostream &OS,
136                                 const UnwindPlan::Row::CFAValue &CFA) {
137   StreamString S;
138   CFA.Dump(S, nullptr, nullptr);
139   return OS << S.GetData();
140 }
141 } // namespace lldb_private
142 
143 TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) {
144   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
145 
146   // 'int main() { }' compiled for x86_64-apple-macosx with clang
147   uint8_t data[] = {
148       0x55,             // offset 0 -- pushq %rbp
149       0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp
150       0x31, 0xc0,       // offset 4 -- xorl %eax, %eax
151       0x5d,             // offset 6 -- popq %rbp
152       0xc3              // offset 7 -- retq
153   };
154 
155   AddressRange sample_range(0x1000, sizeof(data));
156 
157   UnwindPlan unwind_plan(eRegisterKindLLDB);
158   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
159       data, sizeof(data), sample_range, unwind_plan));
160 
161   // Expect four unwind rows:
162   // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
163   // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
164   // 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
165   // 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
166 
167   EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_rsp);
168   EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==
169               eLazyBoolYes);
170   EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);
171 
172   UnwindPlan::Row::RegisterLocation regloc;
173 
174   // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
175   UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(0);
176   EXPECT_EQ(0ull, row_sp->GetOffset());
177   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
178   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
179   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
180 
181   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
182   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
183   EXPECT_EQ(-8, regloc.GetOffset());
184 
185   // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
186   row_sp = unwind_plan.GetRowForFunctionOffset(1);
187   EXPECT_EQ(1ull, row_sp->GetOffset());
188   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
189   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
190   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
191 
192   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
193   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
194   EXPECT_EQ(-8, regloc.GetOffset());
195 
196   // 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
197   row_sp = unwind_plan.GetRowForFunctionOffset(4);
198   EXPECT_EQ(4ull, row_sp->GetOffset());
199   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp);
200   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
201   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
202 
203   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
204   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
205   EXPECT_EQ(-8, regloc.GetOffset());
206 
207   // 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
208   row_sp = unwind_plan.GetRowForFunctionOffset(7);
209   EXPECT_EQ(7ull, row_sp->GetOffset());
210   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
211   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
212   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
213 
214   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
215   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
216   EXPECT_EQ(-8, regloc.GetOffset());
217 }
218 
219 TEST_F(Testx86AssemblyInspectionEngine, TestSimple32bitFrameFunction) {
220   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
221 
222   // 'int main() { }' compiled for i386-apple-macosx with clang
223   uint8_t data[] = {
224       0x55,       // offset 0 -- pushl %ebp
225       0x89, 0xe5, // offset 1 -- movl %esp, %ebp
226       0x31, 0xc0, // offset 3 -- xorl %eax, %eax
227       0x5d,       // offset 5 -- popl %ebp
228       0xc3        // offset 6 -- retl
229   };
230 
231   AddressRange sample_range(0x1000, sizeof(data));
232 
233   UnwindPlan unwind_plan(eRegisterKindLLDB);
234   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
235       data, sizeof(data), sample_range, unwind_plan));
236 
237   // Expect four unwind rows:
238   // 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
239   // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
240   // 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
241   // 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
242 
243   EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_esp);
244   EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==
245               eLazyBoolYes);
246   EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);
247 
248   UnwindPlan::Row::RegisterLocation regloc;
249 
250   // offset 0 -- pushl %ebp
251   UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(0);
252   EXPECT_EQ(0ull, row_sp->GetOffset());
253   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
254   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
255   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
256 
257   EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
258   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
259   EXPECT_TRUE(regloc.GetOffset() == -4);
260 
261   // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
262   row_sp = unwind_plan.GetRowForFunctionOffset(1);
263   EXPECT_EQ(1ull, row_sp->GetOffset());
264   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
265   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
266   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
267 
268   EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
269   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
270   EXPECT_EQ(-4, regloc.GetOffset());
271 
272   // 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
273   row_sp = unwind_plan.GetRowForFunctionOffset(3);
274   EXPECT_EQ(3ull, row_sp->GetOffset());
275   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp);
276   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
277   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
278 
279   EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
280   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
281   EXPECT_EQ(-4, regloc.GetOffset());
282 
283   // 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
284   row_sp = unwind_plan.GetRowForFunctionOffset(6);
285   EXPECT_EQ(6ull, row_sp->GetOffset());
286   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
287   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
288   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
289 
290   EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
291   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
292   EXPECT_EQ(-4, regloc.GetOffset());
293 }
294 
295 TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessBigStackFrame) {
296   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
297 
298   // this source file:
299   //
300   // #include <stdio.h>
301   // int main (int argc, char **argv)
302   // {
303   //
304   //     const int arrsize = 60;
305   //     int buf[arrsize * arrsize];
306   //     int accum = argc;
307   //     for (int i = 0; i < arrsize; i++)
308   //         for (int j = 0; j < arrsize; j++)
309   //         {
310   //             if (i > 0 && j > 0)
311   //             {
312   //                 int n = buf[(i-1) * (j-1)] * 2;
313   //                 int m = buf[(i-1) * (j-1)] / 2;
314   //                 int j = buf[(i-1) * (j-1)] + 2;
315   //                 int k = buf[(i-1) * (j-1)] - 2;
316   //                 printf ("%d ", n + m + j + k);
317   //                 buf[(i-1) * (j-1)] += n - m + j - k;
318   //             }
319   //             buf[i*j] = accum++;
320   //         }
321   //
322   //     return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize *
323   //     arrsize) - 3]);
324   // }
325   //
326   // compiled 'clang -fomit-frame-pointer -Os' for x86_64-apple-macosx
327 
328   uint8_t data[] = {
329       0x55,       // offset 0  -- pushq %rbp
330       0x41, 0x57, // offset 1  -- pushq %r15
331       0x41, 0x56, // offset 3  -- pushq %r14
332       0x41, 0x55, // offset 5  -- pushq %r13
333       0x41, 0x54, // offset 7  -- pushq %r12
334       0x53,       // offset 9  -- pushq %rbx
335       0x48, 0x81, 0xec, 0x68, 0x38, 0x00,
336       0x00, // offset 10 -- subq $0x3868, %rsp
337 
338       // ....
339 
340       0x48, 0x81, 0xc4, 0x68, 0x38, 0x00,
341       0x00,                        // offset 17 -- addq $0x3868, %rsp
342       0x5b,                        // offset 24 -- popq %rbx
343       0x41, 0x5c,                  // offset 25 -- popq %r12
344       0x41, 0x5d,                  // offset 27 -- popq %r13
345       0x41, 0x5e,                  // offset 29 -- popq %r14
346       0x41, 0x5f,                  // offset 31 -- popq %r15
347       0x5d,                        // offset 33 -- popq %rbp
348       0xc3,                        // offset 34 -- retq
349       0xe8, 0x12, 0x34, 0x56, 0x78 // offset 35 -- callq whatever
350   };
351 
352   AddressRange sample_range(0x1000, sizeof(data));
353 
354   UnwindPlan unwind_plan(eRegisterKindLLDB);
355   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
356       data, sizeof(data), sample_range, unwind_plan));
357 
358   // Unwind rules should look like
359   // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
360   // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
361   // 3: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8]
362   // 5: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24]
363   // rip=[CFA-8
364   // 7: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32]
365   // r15=[CFA-24] rip=[CFA-8]
366   // 9: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40]
367   // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
368   // 10: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
369   // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
370   // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
371   // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
372 
373   // 24: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
374   // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
375   // 25: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40]
376   // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
377   // 27: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32]
378   // r15=[CFA-24] rip=[CFA-8]
379   // 29: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24]
380   // rip=[CFA-8]
381   // 31: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8]
382   // 33: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
383   // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
384 
385   UnwindPlan::Row::RegisterLocation regloc;
386 
387   // grab the Row for when the prologue has finished executing:
388   // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
389   // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
390 
391   UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(17);
392 
393   EXPECT_EQ(17ull, row_sp->GetOffset());
394   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
395   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
396   EXPECT_EQ(14496, row_sp->GetCFAValue().GetOffset());
397 
398   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
399   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
400   EXPECT_EQ(-8, regloc.GetOffset());
401 
402   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc));
403   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
404   EXPECT_EQ(-16, regloc.GetOffset());
405 
406   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc));
407   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
408   EXPECT_EQ(-24, regloc.GetOffset());
409 
410   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc));
411   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
412   EXPECT_EQ(-32, regloc.GetOffset());
413 
414   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc));
415   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
416   EXPECT_EQ(-40, regloc.GetOffset());
417 
418   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc));
419   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
420   EXPECT_EQ(-48, regloc.GetOffset());
421 
422   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc));
423   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
424   EXPECT_EQ(-56, regloc.GetOffset());
425 
426   // grab the Row for when the epilogue has finished executing:
427   // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
428 
429   row_sp = unwind_plan.GetRowForFunctionOffset(34);
430 
431   EXPECT_EQ(34ull, row_sp->GetOffset());
432   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
433   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
434   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
435 
436   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
437   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
438   EXPECT_EQ(-8, regloc.GetOffset());
439 
440   // these could be set to IsSame and be valid -- meaning that the
441   // register value is the same as the caller's -- but I'd rather
442   // they not be mentioned at all.
443 
444   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rax, regloc));
445   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbx, regloc));
446   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rcx, regloc));
447   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdx, regloc));
448   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
449   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rsi, regloc));
450   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdi, regloc));
451   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r8, regloc));
452   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r9, regloc));
453   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r10, regloc));
454   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r11, regloc));
455   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r12, regloc));
456   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc));
457   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc));
458   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc));
459 }
460 
461 TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessBigStackFrame) {
462   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
463 
464   // this source file:
465   //
466   // #include <stdio.h>
467   // int main (int argc, char **argv)
468   // {
469   //
470   //     const int arrsize = 60;
471   //     int buf[arrsize * arrsize];
472   //     int accum = argc;
473   //     for (int i = 0; i < arrsize; i++)
474   //         for (int j = 0; j < arrsize; j++)
475   //         {
476   //             if (i > 0 && j > 0)
477   //             {
478   //                 int n = buf[(i-1) * (j-1)] * 2;
479   //                 int m = buf[(i-1) * (j-1)] / 2;
480   //                 int j = buf[(i-1) * (j-1)] + 2;
481   //                 int k = buf[(i-1) * (j-1)] - 2;
482   //                 printf ("%d ", n + m + j + k);
483   //                 buf[(i-1) * (j-1)] += n - m + j - k;
484   //             }
485   //             buf[i*j] = accum++;
486   //         }
487   //
488   //     return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize *
489   //     arrsize) - 3]);
490   // }
491   //
492   // compiled 'clang -arch i386 -fomit-frame-pointer -Os' for i386-apple-macosx
493 
494   // simplified assembly version of the above function, which is used as the
495   // input
496   // data:
497   //
498   // 	.section	__TEXT,__text,regular,pure_instructions
499   // 	.macosx_version_min 10, 12
500   // 	.globl	_main
501   // 	.align	4, 0x90
502   // _main:                                  ## @main
503   // ## BB#0:
504   // 	pushl %ebp
505   // 	pushl %ebx
506   // 	pushl %edi
507   // 	pushl %esi
508   // L0$pb:
509   // 	subl $0x386c, %esp
510   //     calll L1
511   // L1:
512   //     popl %ecx
513   //     movl %ecx, 0x8(%esp)
514   //     subl $0x8, %esp
515   //     pushl %eax
516   //     pushl 0x20(%esp)
517   //     calll _puts
518   //     addl $0x10, %esp
519   //     incl %ebx
520   //     addl $0x386c, %esp
521   //     popl %esi
522   //     popl %edi
523   //     popl %ebx
524   //     popl %ebp
525   //     retl
526   //
527   // 	.section	__TEXT,__cstring,cstring_literals
528   // L_.str:                                 ## @.str
529   // 	.asciz	"HI"
530   //
531   //
532   // .subsections_via_symbols
533 
534   uint8_t data[] = {
535       0x55,
536       // offset 0 -- pushl %ebp
537 
538       0x53,
539       // offset 1 -- pushl %ebx
540 
541       0x57,
542       // offset 2 -- pushl %edi
543 
544       0x56,
545       // offset 3 -- pushl %esi
546 
547       0x81, 0xec, 0x6c, 0x38, 0x00, 0x00,
548       // offset 4 -- subl $0x386c, %esp
549 
550       0xe8, 0x00, 0x00, 0x00, 0x00,
551       // offset 10 -- calll 0
552       // call the next instruction, to put the pc on the stack
553 
554       0x59,
555       // offset 15 -- popl %ecx
556       // pop the saved pc address into ecx
557 
558       0x89, 0x4c, 0x24, 0x08,
559       // offset 16 -- movl %ecx, 0x8(%esp)
560 
561       // ....
562 
563       0x83, 0xec, 0x08,
564       // offset 20 -- subl $0x8, %esp
565 
566       0x50,
567       // offset 23 -- pushl %eax
568 
569       0xff, 0x74, 0x24, 0x20,
570       // offset 24 -- pushl 0x20(%esp)
571 
572       0xe8, 0x8c, 0x00, 0x00, 0x00,
573       // offset 28 -- calll puts
574 
575       0x83, 0xc4, 0x10,
576       // offset 33 -- addl $0x10, %esp
577       // get esp back to the value it was before the
578       // alignment & argument saves for the puts call
579 
580       0x43,
581       // offset 36 -- incl %ebx
582 
583       // ....
584 
585       0x81, 0xc4, 0x6c, 0x38, 0x00, 0x00,
586       // offset 37 -- addl $0x386c, %esp
587 
588       0x5e,
589       // offset 43 -- popl %esi
590 
591       0x5f,
592       // offset 44 -- popl %edi
593 
594       0x5b,
595       // offset 45 -- popl %ebx
596 
597       0x5d,
598       // offset 46 -- popl %ebp
599 
600       0xc3,
601       // offset 47 -- retl
602 
603       0xe8, 0x12, 0x34, 0x56, 0x78,
604       // offset 48 -- calll __stack_chk_fail
605   };
606 
607   AddressRange sample_range(0x1000, sizeof(data));
608 
609   UnwindPlan unwind_plan(eRegisterKindLLDB);
610   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
611       data, sizeof(data), sample_range, unwind_plan));
612 
613   // Unwind rules should look like
614   //
615   //   0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
616   //   1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
617   //   2: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
618   //   3: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0
619   //   eip=[CFA-4]
620   //   4: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
621   //   esp=CFA+0 eip=[CFA-4]
622   //  10: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
623   //  esp=CFA+0 eip=[CFA-4]
624   //  15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
625   //  esp=CFA+0 eip=[CFA-4]
626   //  16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
627   //  esp=CFA+0 eip=[CFA-4]
628   //
629   //  ....
630   //
631   //  23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
632   //  esp=CFA+0 eip=[CFA-4]
633   //  24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
634   //  esp=CFA+0 eip=[CFA-4]
635   //  28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
636   //  esp=CFA+0 eip=[CFA-4]
637   //  36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
638   //  esp=CFA+0 eip=[CFA-4]
639   //
640   //  .....
641   //
642   //  37: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
643   //  esp=CFA+0 eip=[CFA-4]
644   //  43: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
645   //  esp=CFA+0 eip=[CFA-4]
646   //  44: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0
647   //  eip=[CFA-4]
648   //  45: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
649   //  46: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
650   //  47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
651   //  48: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
652   //  esp=CFA+0 eip=[CFA-4]
653 
654   UnwindPlan::Row::RegisterLocation regloc;
655   UnwindPlan::RowSP row_sp;
656 
657   // Check that we get the CFA correct for the pic base setup sequence
658 
659   // CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
660   // esp=CFA+0 eip=[CFA-4]
661   row_sp = unwind_plan.GetRowForFunctionOffset(10);
662   EXPECT_EQ(10ull, row_sp->GetOffset());
663   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
664   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
665   EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset());
666 
667   // 15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
668   // esp=CFA+0 eip=[CFA-4]
669   row_sp = unwind_plan.GetRowForFunctionOffset(15);
670   EXPECT_EQ(15ull, row_sp->GetOffset());
671   EXPECT_EQ(14468, row_sp->GetCFAValue().GetOffset());
672 
673   // 16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
674   // esp=CFA+0 eip=[CFA-4]
675   row_sp = unwind_plan.GetRowForFunctionOffset(16);
676   EXPECT_EQ(16ull, row_sp->GetOffset());
677   EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset());
678 
679   // Check that the row for offset 16 has the registers saved that we expect
680 
681   EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
682   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
683   EXPECT_EQ(-4, regloc.GetOffset());
684 
685   EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc));
686   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
687   EXPECT_EQ(-8, regloc.GetOffset());
688 
689   EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc));
690   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
691   EXPECT_EQ(-12, regloc.GetOffset());
692 
693   EXPECT_TRUE(row_sp->GetRegisterInfo(k_edi, regloc));
694   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
695   EXPECT_EQ(-16, regloc.GetOffset());
696 
697   EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc));
698   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
699   EXPECT_EQ(-20, regloc.GetOffset());
700 
701   //
702   // Check the pushing & popping around the call printf instruction
703 
704   // 23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
705   // esp=CFA+0 eip=[CFA-4]
706   row_sp = unwind_plan.GetRowForFunctionOffset(23);
707   EXPECT_EQ(23ull, row_sp->GetOffset());
708   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
709   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
710   EXPECT_EQ(14472, row_sp->GetCFAValue().GetOffset());
711 
712   // 24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
713   // esp=CFA+0 eip=[CFA-4]
714   row_sp = unwind_plan.GetRowForFunctionOffset(24);
715   EXPECT_EQ(24ull, row_sp->GetOffset());
716   EXPECT_EQ(14476, row_sp->GetCFAValue().GetOffset());
717 
718   // 28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
719   // esp=CFA+0 eip=[CFA-4]
720   row_sp = unwind_plan.GetRowForFunctionOffset(28);
721   EXPECT_EQ(28ull, row_sp->GetOffset());
722   EXPECT_EQ(14480, row_sp->GetCFAValue().GetOffset());
723 
724   // 36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
725   // esp=CFA+0 eip=[CFA-4]
726   row_sp = unwind_plan.GetRowForFunctionOffset(36);
727   EXPECT_EQ(36ull, row_sp->GetOffset());
728   EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset());
729 
730   // Check that the epilogue gets us back to the original unwind state
731 
732   //  47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
733   row_sp = unwind_plan.GetRowForFunctionOffset(47);
734   EXPECT_EQ(47ull, row_sp->GetOffset());
735   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
736   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
737   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
738 
739   EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
740   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
741   EXPECT_EQ(-4, regloc.GetOffset());
742 
743   EXPECT_TRUE(row_sp->GetRegisterInfo(k_esp, regloc));
744   EXPECT_TRUE(regloc.IsCFAPlusOffset());
745   EXPECT_EQ(0, regloc.GetOffset());
746 
747   // Check that no unexpected registers were saved
748 
749   EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc));
750   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc));
751   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc));
752   EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc));
753   EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc));
754   EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc));
755   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
756 }
757 
758 TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessSmallStackFrame) {
759   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
760 
761   // this source file:
762   // #include <stdio.h>
763   // int main () {
764   //    puts ("HI");
765   // }
766   //
767   // compiled 'clang -fomit-frame-pointer' for x86_64-apple-macosx
768 
769   uint8_t data[] = {
770       0x50,
771       // offset 0  -- pushq %rax
772 
773       0x48, 0x8d, 0x3d, 0x32, 0x00, 0x00, 0x00,
774       // offset 1 -- leaq 0x32(%rip), %rdi ; "HI"
775 
776       0xe8, 0x0b, 0x00, 0x00, 0x00,
777       // offset 8 -- callq 0x100000f58 ; puts
778 
779       0x31, 0xc9,
780       // offset 13 -- xorl %ecx, %ecx
781 
782       0x89, 0x44, 0x24, 0x04,
783       // offset 15 -- movl %eax, 0x4(%rsp)
784 
785       0x89, 0xc8,
786       // offset 19 -- movl %ecx, %eax
787 
788       0x59,
789       // offset 21 -- popq %rcx
790 
791       0xc3
792       // offset 22 -- retq
793   };
794 
795   AddressRange sample_range(0x1000, sizeof(data));
796 
797   UnwindPlan unwind_plan(eRegisterKindLLDB);
798   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
799       data, sizeof(data), sample_range, unwind_plan));
800 
801   // Unwind rules should look like
802   //     0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
803   //     1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]
804   //    22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
805 
806   UnwindPlan::Row::RegisterLocation regloc;
807 
808   // grab the Row for when the prologue has finished executing:
809   //     1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]
810 
811   UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(13);
812 
813   EXPECT_EQ(1ull, row_sp->GetOffset());
814   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
815   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
816   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
817 
818   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
819   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
820   EXPECT_EQ(-8, regloc.GetOffset());
821 
822   // none of these were spilled
823 
824   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rax, regloc));
825   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbx, regloc));
826   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rcx, regloc));
827   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdx, regloc));
828   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
829   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rsi, regloc));
830   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdi, regloc));
831   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r8, regloc));
832   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r9, regloc));
833   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r10, regloc));
834   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r11, regloc));
835   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r12, regloc));
836   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc));
837   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc));
838   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc));
839 
840   // grab the Row for when the epilogue has finished executing:
841   //     22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
842 
843   row_sp = unwind_plan.GetRowForFunctionOffset(22);
844 
845   EXPECT_EQ(22ull, row_sp->GetOffset());
846   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
847   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
848   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
849 
850   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
851   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
852   EXPECT_EQ(-8, regloc.GetOffset());
853 }
854 
855 TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessSmallStackFrame) {
856   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
857 
858   // this source file:
859   // #include <stdio.h>
860   // int main () {
861   //    puts ("HI");
862   // }
863   //
864   // compiled 'clang -arch i386 -fomit-frame-pointer' for i386-apple-macosx
865 
866   uint8_t data[] = {
867       0x83, 0xec, 0x0c,
868       // offset 0 -- subl $0xc, %esp
869 
870       0xe8, 0x00, 0x00, 0x00, 0x00,
871       // offset 3 -- calll 0 {call the next instruction, to put the pc on
872       // the stack}
873 
874       0x58,
875       // offset 8 -- popl %eax {pop the saved pc value off stack, into eax}
876 
877       0x8d, 0x80, 0x3a, 0x00, 0x00, 0x00,
878       // offset 9 -- leal 0x3a(%eax),%eax
879 
880       0x89, 0x04, 0x24,
881       // offset 15 -- movl %eax, (%esp)
882 
883       0xe8, 0x0d, 0x00, 0x00, 0x00,
884       // offset 18 -- calll 0x1f94 (puts)
885 
886       0x31, 0xc9,
887       // offset 23 -- xorl %ecx, %ecx
888 
889       0x89, 0x44, 0x24, 0x08,
890       // offset 25 -- movl %eax, 0x8(%esp)
891 
892       0x89, 0xc8,
893       // offset 29 -- movl %ecx, %eax
894 
895       0x83, 0xc4, 0x0c,
896       // offset 31 -- addl $0xc, %esp
897 
898       0xc3
899       // offset 34 -- retl
900   };
901 
902   AddressRange sample_range(0x1000, sizeof(data));
903 
904   UnwindPlan unwind_plan(eRegisterKindLLDB);
905   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
906       data, sizeof(data), sample_range, unwind_plan));
907 
908   // Unwind rules should look like
909   // row[0]:    0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
910   // row[1]:    3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
911   // row[2]:    8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4]
912   // row[3]:    9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
913   // row[4]:   34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
914 
915   UnwindPlan::Row::RegisterLocation regloc;
916 
917   // Check unwind state before we set up the picbase register
918   //      3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
919 
920   UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(3);
921 
922   EXPECT_EQ(3ull, row_sp->GetOffset());
923   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
924   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
925   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
926 
927   // Check unwind state after we call the next instruction
928   // 8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4]
929 
930   row_sp = unwind_plan.GetRowForFunctionOffset(8);
931   EXPECT_EQ(8ull, row_sp->GetOffset());
932   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
933   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
934   EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset());
935 
936   // Check unwind state after we pop the pic base value off the stack
937   // row[3]:    9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
938 
939   row_sp = unwind_plan.GetRowForFunctionOffset(9);
940   EXPECT_EQ(9ull, row_sp->GetOffset());
941   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
942   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
943   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
944 
945   // Check that no unexpected registers were saved
946 
947   EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc));
948   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc));
949   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc));
950   EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc));
951   EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc));
952   EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc));
953   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
954 
955   // verify that we get back to the original unwind state before the ret
956   //  34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
957 
958   row_sp = unwind_plan.GetRowForFunctionOffset(34);
959   EXPECT_EQ(34ull, row_sp->GetOffset());
960   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
961   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
962   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
963 }
964 
965 TEST_F(Testx86AssemblyInspectionEngine, TestPushRBP) {
966   UnwindPlan::Row::RegisterLocation regloc;
967   UnwindPlan::RowSP row_sp;
968 
969   uint8_t data[] = {
970       0x55, // pushq %rbp
971       0x90  // nop
972   };
973 
974   AddressRange sample_range(0x1000, sizeof(data));
975   UnwindPlan unwind_plan(eRegisterKindLLDB);
976 
977   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
978   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
979       data, sizeof(data), sample_range, unwind_plan));
980 
981   row_sp = unwind_plan.GetRowForFunctionOffset(1);
982 
983   EXPECT_EQ(1ull, row_sp->GetOffset());
984   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
985   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
986   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
987 
988   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc));
989   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
990   EXPECT_EQ(-16, regloc.GetOffset());
991 
992   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
993   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
994       data, sizeof(data), sample_range, unwind_plan));
995 
996   row_sp = unwind_plan.GetRowForFunctionOffset(1);
997 
998   EXPECT_EQ(1ull, row_sp->GetOffset());
999   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1000   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1001   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1002 
1003   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc));
1004   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1005   EXPECT_EQ(-8, regloc.GetOffset());
1006 }
1007 
1008 TEST_F(Testx86AssemblyInspectionEngine, TestPushImm) {
1009   UnwindPlan::Row::RegisterLocation regloc;
1010   UnwindPlan::RowSP row_sp;
1011 
1012   uint8_t data[] = {
1013       0x68, 0xff, 0xff, 0x01, 0x69, // pushq $0x6901ffff
1014       0x6a, 0x7d,                   // pushl $0x7d
1015       0x90                          // nop
1016   };
1017 
1018   AddressRange sample_range(0x1000, sizeof(data));
1019   UnwindPlan unwind_plan(eRegisterKindLLDB);
1020 
1021   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1022   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1023       data, sizeof(data), sample_range, unwind_plan));
1024 
1025   row_sp = unwind_plan.GetRowForFunctionOffset(5);
1026   EXPECT_EQ(5ull, row_sp->GetOffset());
1027   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1028   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1029   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1030 
1031   row_sp = unwind_plan.GetRowForFunctionOffset(7);
1032   EXPECT_EQ(7ull, row_sp->GetOffset());
1033   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1034   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1035   EXPECT_EQ(24, row_sp->GetCFAValue().GetOffset());
1036 
1037   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1038   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1039       data, sizeof(data), sample_range, unwind_plan));
1040 
1041   row_sp = unwind_plan.GetRowForFunctionOffset(5);
1042   EXPECT_EQ(5ull, row_sp->GetOffset());
1043   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1044   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1045   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1046 
1047   row_sp = unwind_plan.GetRowForFunctionOffset(7);
1048   EXPECT_EQ(7ull, row_sp->GetOffset());
1049   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1050   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1051   EXPECT_EQ(12, row_sp->GetCFAValue().GetOffset());
1052 }
1053 
1054 // We treat 'pushq $0' / 'pushl $0' specially - this shows up
1055 // in the first function called in a new thread and it needs to
1056 // put a 0 as the saved pc.  We pretend it didn't change the CFA.
1057 TEST_F(Testx86AssemblyInspectionEngine, TestPush0) {
1058   UnwindPlan::Row::RegisterLocation regloc;
1059   UnwindPlan::RowSP row_sp;
1060 
1061   uint8_t data[] = {
1062       0x6a, 0x00, // pushq $0
1063       0x90        // nop
1064   };
1065 
1066   AddressRange sample_range(0x1000, sizeof(data));
1067   UnwindPlan unwind_plan(eRegisterKindLLDB);
1068 
1069   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1070   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1071       data, sizeof(data), sample_range, unwind_plan));
1072 
1073   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1074 
1075   // We're verifying that no row was created for the 'pushq $0'
1076   EXPECT_EQ(0ull, row_sp->GetOffset());
1077 
1078   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1079   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1080       data, sizeof(data), sample_range, unwind_plan));
1081 
1082   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1083 
1084   // We're verifying that no row was created for the 'pushq $0'
1085   EXPECT_EQ(0ull, row_sp->GetOffset());
1086 }
1087 
1088 TEST_F(Testx86AssemblyInspectionEngine, TestPushExtended) {
1089   UnwindPlan::Row::RegisterLocation regloc;
1090   UnwindPlan::RowSP row_sp;
1091 
1092   uint8_t data[] = {
1093       0xff, 0x74, 0x24, 0x20,             // pushl 0x20(%esp)
1094       0xff, 0xb6, 0xce, 0x01, 0xf0, 0x00, // pushl  0xf001ce(%esi)
1095       0xff, 0x30,                         // pushl  (%eax)
1096       0x90                                // nop
1097   };
1098 
1099   AddressRange sample_range(0x1000, sizeof(data));
1100   UnwindPlan unwind_plan(eRegisterKindLLDB);
1101 
1102   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1103   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1104       data, sizeof(data), sample_range, unwind_plan));
1105 
1106   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1107 
1108   EXPECT_EQ(4ull, row_sp->GetOffset());
1109   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1110   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1111   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1112 
1113   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1114   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1115       data, sizeof(data), sample_range, unwind_plan));
1116 
1117   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1118   EXPECT_EQ(4ull, row_sp->GetOffset());
1119   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1120   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1121   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1122 
1123   row_sp = unwind_plan.GetRowForFunctionOffset(10);
1124   EXPECT_EQ(10ull, row_sp->GetOffset());
1125   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1126   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1127   EXPECT_EQ(12, row_sp->GetCFAValue().GetOffset());
1128 
1129   row_sp = unwind_plan.GetRowForFunctionOffset(12);
1130   EXPECT_EQ(12ull, row_sp->GetOffset());
1131   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1132   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1133   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1134 }
1135 
1136 TEST_F(Testx86AssemblyInspectionEngine, TestPushR15) {
1137   UnwindPlan::Row::RegisterLocation regloc;
1138   UnwindPlan::RowSP row_sp;
1139 
1140   uint8_t data[] = {
1141       0x41, 0x57, // pushq %r15
1142       0x90        // nop
1143   };
1144 
1145   AddressRange sample_range(0x1000, sizeof(data));
1146   UnwindPlan unwind_plan(eRegisterKindLLDB);
1147 
1148   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1149   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1150       data, sizeof(data), sample_range, unwind_plan));
1151 
1152   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1153 
1154   EXPECT_EQ(2ull, row_sp->GetOffset());
1155   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1156   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1157   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1158 
1159   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc));
1160   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1161   EXPECT_EQ(-16, regloc.GetOffset());
1162 }
1163 
1164 TEST_F(Testx86AssemblyInspectionEngine, TestPushR14) {
1165   UnwindPlan::Row::RegisterLocation regloc;
1166   UnwindPlan::RowSP row_sp;
1167 
1168   uint8_t data[] = {
1169       0x41, 0x56, // pushq %r14
1170       0x90        // nop
1171   };
1172 
1173   AddressRange sample_range(0x1000, sizeof(data));
1174   UnwindPlan unwind_plan(eRegisterKindLLDB);
1175 
1176   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1177   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1178       data, sizeof(data), sample_range, unwind_plan));
1179 
1180   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1181 
1182   EXPECT_EQ(2ull, row_sp->GetOffset());
1183   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1184   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1185   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1186 
1187   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc));
1188   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1189   EXPECT_EQ(-16, regloc.GetOffset());
1190 }
1191 
1192 TEST_F(Testx86AssemblyInspectionEngine, TestPushR13) {
1193   UnwindPlan::Row::RegisterLocation regloc;
1194   UnwindPlan::RowSP row_sp;
1195 
1196   uint8_t data[] = {
1197       0x41, 0x55, // pushq %r13
1198       0x90        // nop
1199   };
1200 
1201   AddressRange sample_range(0x1000, sizeof(data));
1202   UnwindPlan unwind_plan(eRegisterKindLLDB);
1203 
1204   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1205   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1206       data, sizeof(data), sample_range, unwind_plan));
1207 
1208   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1209 
1210   EXPECT_EQ(2ull, row_sp->GetOffset());
1211   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1212   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1213   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1214 
1215   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc));
1216   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1217   EXPECT_EQ(-16, regloc.GetOffset());
1218 }
1219 
1220 TEST_F(Testx86AssemblyInspectionEngine, TestPushR12) {
1221   UnwindPlan::Row::RegisterLocation regloc;
1222   UnwindPlan::RowSP row_sp;
1223 
1224   uint8_t data[] = {
1225       0x41, 0x54, // pushq %r13
1226       0x90        // nop
1227   };
1228 
1229   AddressRange sample_range(0x1000, sizeof(data));
1230   UnwindPlan unwind_plan(eRegisterKindLLDB);
1231 
1232   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1233   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1234       data, sizeof(data), sample_range, unwind_plan));
1235 
1236   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1237 
1238   EXPECT_EQ(2ull, row_sp->GetOffset());
1239   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1240   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1241   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1242 
1243   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc));
1244   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1245   EXPECT_EQ(-16, regloc.GetOffset());
1246 }
1247 
1248 TEST_F(Testx86AssemblyInspectionEngine, TestPushRBX) {
1249   UnwindPlan::Row::RegisterLocation regloc;
1250   UnwindPlan::RowSP row_sp;
1251 
1252   uint8_t data[] = {
1253       0x53, // pushq %rbx
1254       0x90  // nop
1255   };
1256 
1257   AddressRange sample_range(0x1000, sizeof(data));
1258   UnwindPlan unwind_plan(eRegisterKindLLDB);
1259 
1260   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1261   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1262       data, sizeof(data), sample_range, unwind_plan));
1263 
1264   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1265 
1266   EXPECT_EQ(1ull, row_sp->GetOffset());
1267   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1268   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1269   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
1270 
1271   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc));
1272   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1273   EXPECT_EQ(-16, regloc.GetOffset());
1274 }
1275 
1276 // The ABI is hardcoded in x86AssemblyInspectionEngine such that
1277 // eax, ecx, edx are all considered volatile and push/pops of them are
1278 // not tracked (except to keep track of stack pointer movement)
1279 TEST_F(Testx86AssemblyInspectionEngine, TestPushEAX) {
1280   UnwindPlan::Row::RegisterLocation regloc;
1281   UnwindPlan::RowSP row_sp;
1282   AddressRange sample_range;
1283   UnwindPlan unwind_plan(eRegisterKindLLDB);
1284   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1285 
1286   uint8_t data[] = {
1287       0x50, // pushl %eax
1288       0x90  // nop
1289   };
1290 
1291   sample_range = AddressRange(0x1000, sizeof(data));
1292 
1293   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1294       data, sizeof(data), sample_range, unwind_plan));
1295 
1296   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1297   EXPECT_EQ(1ull, row_sp->GetOffset());
1298   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1299   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1300   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1301 
1302   EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc));
1303 }
1304 
1305 // The ABI is hardcoded in x86AssemblyInspectionEngine such that
1306 // eax, ecx, edx are all considered volatile and push/pops of them are
1307 // not tracked (except to keep track of stack pointer movement)
1308 TEST_F(Testx86AssemblyInspectionEngine, TestPushECX) {
1309   UnwindPlan::Row::RegisterLocation regloc;
1310   UnwindPlan::RowSP row_sp;
1311   AddressRange sample_range;
1312   UnwindPlan unwind_plan(eRegisterKindLLDB);
1313   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1314 
1315   uint8_t data[] = {
1316       0x51, // pushl %ecx
1317       0x90  // nop
1318   };
1319 
1320   sample_range = AddressRange(0x1000, sizeof(data));
1321 
1322   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1323       data, sizeof(data), sample_range, unwind_plan));
1324 
1325   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1326   EXPECT_EQ(1ull, row_sp->GetOffset());
1327   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1328   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1329   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1330 
1331   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc));
1332 }
1333 
1334 // The ABI is hardcoded in x86AssemblyInspectionEngine such that
1335 // eax, ecx, edx are all considered volatile and push/pops of them are
1336 // not tracked (except to keep track of stack pointer movement)
1337 TEST_F(Testx86AssemblyInspectionEngine, TestPushEDX) {
1338   UnwindPlan::Row::RegisterLocation regloc;
1339   UnwindPlan::RowSP row_sp;
1340   AddressRange sample_range;
1341   UnwindPlan unwind_plan(eRegisterKindLLDB);
1342   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1343 
1344   uint8_t data[] = {
1345       0x52, // pushl %edx
1346       0x90  // nop
1347   };
1348 
1349   sample_range = AddressRange(0x1000, sizeof(data));
1350 
1351   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1352       data, sizeof(data), sample_range, unwind_plan));
1353 
1354   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1355   EXPECT_EQ(1ull, row_sp->GetOffset());
1356   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1357   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1358   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1359 
1360   EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc));
1361 }
1362 
1363 TEST_F(Testx86AssemblyInspectionEngine, TestPushEBX) {
1364   UnwindPlan::Row::RegisterLocation regloc;
1365   UnwindPlan::RowSP row_sp;
1366   AddressRange sample_range;
1367   UnwindPlan unwind_plan(eRegisterKindLLDB);
1368   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1369 
1370   uint8_t data[] = {
1371       0x53, // pushl %ebx
1372       0x90  // nop
1373   };
1374 
1375   sample_range = AddressRange(0x1000, sizeof(data));
1376 
1377   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1378       data, sizeof(data), sample_range, unwind_plan));
1379 
1380   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1381   EXPECT_EQ(1ull, row_sp->GetOffset());
1382   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1383   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1384   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1385 
1386   EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc));
1387   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1388   EXPECT_EQ(-8, regloc.GetOffset());
1389 }
1390 
1391 TEST_F(Testx86AssemblyInspectionEngine, TestPushEBP) {
1392   UnwindPlan::Row::RegisterLocation regloc;
1393   UnwindPlan::RowSP row_sp;
1394   AddressRange sample_range;
1395   UnwindPlan unwind_plan(eRegisterKindLLDB);
1396   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1397 
1398   uint8_t data[] = {
1399       0x55, // pushl %ebp
1400       0x90  // nop
1401   };
1402 
1403   sample_range = AddressRange(0x1000, sizeof(data));
1404 
1405   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1406       data, sizeof(data), sample_range, unwind_plan));
1407 
1408   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1409   EXPECT_EQ(1ull, row_sp->GetOffset());
1410   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1411   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1412   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1413 
1414   EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc));
1415   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1416   EXPECT_EQ(-8, regloc.GetOffset());
1417 }
1418 
1419 TEST_F(Testx86AssemblyInspectionEngine, TestPushESI) {
1420   UnwindPlan::Row::RegisterLocation regloc;
1421   UnwindPlan::RowSP row_sp;
1422   AddressRange sample_range;
1423   UnwindPlan unwind_plan(eRegisterKindLLDB);
1424   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1425 
1426   uint8_t data[] = {
1427       0x56, // pushl %esi
1428       0x90  // nop
1429   };
1430 
1431   sample_range = AddressRange(0x1000, sizeof(data));
1432 
1433   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1434       data, sizeof(data), sample_range, unwind_plan));
1435 
1436   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1437   EXPECT_EQ(1ull, row_sp->GetOffset());
1438   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1439   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1440   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1441 
1442   EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc));
1443   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1444   EXPECT_EQ(-8, regloc.GetOffset());
1445 }
1446 
1447 TEST_F(Testx86AssemblyInspectionEngine, TestPushEDI) {
1448   UnwindPlan::Row::RegisterLocation regloc;
1449   UnwindPlan::RowSP row_sp;
1450   AddressRange sample_range;
1451   UnwindPlan unwind_plan(eRegisterKindLLDB);
1452   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1453 
1454   uint8_t data[] = {
1455       0x57, // pushl %edi
1456       0x90  // nop
1457   };
1458 
1459   sample_range = AddressRange(0x1000, sizeof(data));
1460 
1461   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1462       data, sizeof(data), sample_range, unwind_plan));
1463 
1464   row_sp = unwind_plan.GetRowForFunctionOffset(1);
1465   EXPECT_EQ(1ull, row_sp->GetOffset());
1466   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
1467   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1468   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1469 
1470   EXPECT_TRUE(row_sp->GetRegisterInfo(k_edi, regloc));
1471   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
1472   EXPECT_EQ(-8, regloc.GetOffset());
1473 }
1474 
1475 TEST_F(Testx86AssemblyInspectionEngine, TestMovRSPtoRBP) {
1476   UnwindPlan::Row::RegisterLocation regloc;
1477   UnwindPlan::RowSP row_sp;
1478 
1479   uint8_t data64_1[] = {
1480       0x48, 0x8b, 0xec, // movq %rsp, %rbp
1481       0x90              // nop
1482   };
1483 
1484   AddressRange sample_range(0x1000, sizeof(data64_1));
1485   UnwindPlan unwind_plan(eRegisterKindLLDB);
1486 
1487   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1488   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1489       data64_1, sizeof(data64_1), sample_range, unwind_plan));
1490 
1491   row_sp = unwind_plan.GetRowForFunctionOffset(3);
1492 
1493   EXPECT_EQ(3ull, row_sp->GetOffset());
1494   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp);
1495   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1496   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1497 
1498   uint8_t data64_2[] = {
1499       0x48, 0x89, 0xe5, // movq %rsp, %rbp
1500       0x90              // nop
1501   };
1502 
1503   sample_range = AddressRange(0x1000, sizeof(data64_2));
1504   unwind_plan.Clear();
1505   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1506       data64_2, sizeof(data64_2), sample_range, unwind_plan));
1507 
1508   row_sp = unwind_plan.GetRowForFunctionOffset(3);
1509   EXPECT_EQ(3ull, row_sp->GetOffset());
1510   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp);
1511   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1512   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1513 
1514   uint8_t data32_1[] = {
1515       0x8b, 0xec, // movl %rsp, %rbp
1516       0x90        // nop
1517   };
1518 
1519   sample_range = AddressRange(0x1000, sizeof(data32_1));
1520   unwind_plan.Clear();
1521   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1522       data32_1, sizeof(data32_1), sample_range, unwind_plan));
1523 
1524   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1525   EXPECT_EQ(2ull, row_sp->GetOffset());
1526   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp);
1527   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1528   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1529 
1530   uint8_t data32_2[] = {
1531       0x89, 0xe5, // movl %rsp, %rbp
1532       0x90        // nop
1533   };
1534 
1535   sample_range = AddressRange(0x1000, sizeof(data32_2));
1536   unwind_plan.Clear();
1537   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1538       data32_2, sizeof(data32_2), sample_range, unwind_plan));
1539 
1540   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1541   EXPECT_EQ(2ull, row_sp->GetOffset());
1542   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp);
1543   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1544   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1545 }
1546 
1547 TEST_F(Testx86AssemblyInspectionEngine, TestSubRSP) {
1548   UnwindPlan::Row::RegisterLocation regloc;
1549   UnwindPlan::RowSP row_sp;
1550   AddressRange sample_range;
1551   UnwindPlan unwind_plan(eRegisterKindLLDB);
1552   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1553 
1554   uint8_t data1[] = {
1555       0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $0x100, $rsp
1556       0x90                                      // nop
1557   };
1558 
1559   sample_range = AddressRange(0x1000, sizeof(data1));
1560 
1561   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1562       data1, sizeof(data1), sample_range, unwind_plan));
1563 
1564   row_sp = unwind_plan.GetRowForFunctionOffset(7);
1565   EXPECT_EQ(7ull, row_sp->GetOffset());
1566   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1567   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1568   EXPECT_EQ(264, row_sp->GetCFAValue().GetOffset());
1569 
1570   uint8_t data2[] = {
1571       0x48, 0x83, 0xec, 0x10, // subq $0x10, %rsp
1572       0x90                    // nop
1573   };
1574 
1575   sample_range = AddressRange(0x1000, sizeof(data2));
1576 
1577   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1578       data2, sizeof(data2), sample_range, unwind_plan));
1579 
1580   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1581   EXPECT_EQ(4ull, row_sp->GetOffset());
1582   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1583   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1584   EXPECT_EQ(24, row_sp->GetCFAValue().GetOffset());
1585 }
1586 
1587 TEST_F(Testx86AssemblyInspectionEngine, TestSubESP) {
1588   UnwindPlan::Row::RegisterLocation regloc;
1589   UnwindPlan::RowSP row_sp;
1590   AddressRange sample_range;
1591   UnwindPlan unwind_plan(eRegisterKindLLDB);
1592   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1593 
1594   uint8_t data1[] = {
1595       0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subl $0x100, %esp
1596       0x90                                // nop
1597   };
1598 
1599   sample_range = AddressRange(0x1000, sizeof(data1));
1600 
1601   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1602       data1, sizeof(data1), sample_range, unwind_plan));
1603 
1604   row_sp = unwind_plan.GetRowForFunctionOffset(6);
1605   EXPECT_EQ(6ull, row_sp->GetOffset());
1606   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1607   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1608   EXPECT_EQ(260, row_sp->GetCFAValue().GetOffset());
1609 
1610   uint8_t data2[] = {
1611       0x83, 0xec, 0x10, // subq $0x10, %esp
1612       0x90              // nop
1613   };
1614 
1615   sample_range = AddressRange(0x1000, sizeof(data2));
1616 
1617   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1618       data2, sizeof(data2), sample_range, unwind_plan));
1619 
1620   row_sp = unwind_plan.GetRowForFunctionOffset(3);
1621   EXPECT_EQ(3ull, row_sp->GetOffset());
1622   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1623   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1624   EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset());
1625 }
1626 
1627 TEST_F(Testx86AssemblyInspectionEngine, TestAddRSP) {
1628   UnwindPlan::Row::RegisterLocation regloc;
1629   UnwindPlan::RowSP row_sp;
1630   AddressRange sample_range;
1631   UnwindPlan unwind_plan(eRegisterKindLLDB);
1632   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
1633 
1634   uint8_t data1[] = {
1635       0x48, 0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addq $0x100, %rsp
1636       0x90                                      // nop
1637   };
1638 
1639   sample_range = AddressRange(0x1000, sizeof(data1));
1640 
1641   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1642       data1, sizeof(data1), sample_range, unwind_plan));
1643 
1644   row_sp = unwind_plan.GetRowForFunctionOffset(7);
1645   EXPECT_EQ(7ull, row_sp->GetOffset());
1646   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1647   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1648   EXPECT_EQ(8 - 256, row_sp->GetCFAValue().GetOffset());
1649 
1650   uint8_t data2[] = {
1651       0x48, 0x83, 0xc4, 0x10, // addq $0x10, %rsp
1652       0x90                    // nop
1653   };
1654 
1655   sample_range = AddressRange(0x1000, sizeof(data2));
1656 
1657   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
1658       data2, sizeof(data2), sample_range, unwind_plan));
1659 
1660   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1661   EXPECT_EQ(4ull, row_sp->GetOffset());
1662   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1663   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1664   EXPECT_EQ(8 - 16, row_sp->GetCFAValue().GetOffset());
1665 }
1666 
1667 TEST_F(Testx86AssemblyInspectionEngine, TestAddESP) {
1668   UnwindPlan::Row::RegisterLocation regloc;
1669   UnwindPlan::RowSP row_sp;
1670   AddressRange sample_range;
1671   UnwindPlan unwind_plan(eRegisterKindLLDB);
1672   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
1673 
1674   uint8_t data1[] = {
1675       0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addl $0x100, %esp
1676       0x90                                // nop
1677   };
1678 
1679   sample_range = AddressRange(0x1000, sizeof(data1));
1680 
1681   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1682       data1, sizeof(data1), sample_range, unwind_plan));
1683 
1684   row_sp = unwind_plan.GetRowForFunctionOffset(6);
1685   EXPECT_EQ(6ull, row_sp->GetOffset());
1686   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1687   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1688   EXPECT_EQ(4 - 256, row_sp->GetCFAValue().GetOffset());
1689 
1690   uint8_t data2[] = {
1691       0x83, 0xc4, 0x10, // addq $0x10, %esp
1692       0x90              // nop
1693   };
1694 
1695   sample_range = AddressRange(0x1000, sizeof(data2));
1696 
1697   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
1698       data2, sizeof(data2), sample_range, unwind_plan));
1699 
1700   row_sp = unwind_plan.GetRowForFunctionOffset(3);
1701   EXPECT_EQ(3ull, row_sp->GetOffset());
1702   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1703   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1704   EXPECT_EQ(4 - 16, row_sp->GetCFAValue().GetOffset());
1705 }
1706 
1707 // FIXME add test for lea_rsp_pattern_p
1708 
1709 TEST_F(Testx86AssemblyInspectionEngine, TestPopRBX) {
1710   UnwindPlan::Row::RegisterLocation regloc;
1711   UnwindPlan::RowSP row_sp;
1712   AddressRange sample_range;
1713   UnwindPlan unwind_plan(eRegisterKindLLDB);
1714   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
1715 
1716   uint8_t data[] = {
1717       0x53, // pushq %rbx
1718       0x5b, // popq %rbx
1719       0x90  // nop
1720   };
1721 
1722   sample_range = AddressRange(0x1000, sizeof(data));
1723 
1724   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1725       data, sizeof(data), sample_range, unwind_plan));
1726 
1727   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1728   EXPECT_EQ(2ull, row_sp->GetOffset());
1729   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1730   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1731   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1732   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbx, regloc));
1733 }
1734 
1735 TEST_F(Testx86AssemblyInspectionEngine, TestPopRBP) {
1736   UnwindPlan::Row::RegisterLocation regloc;
1737   UnwindPlan::RowSP row_sp;
1738   AddressRange sample_range;
1739   UnwindPlan unwind_plan(eRegisterKindLLDB);
1740   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
1741 
1742   uint8_t data[] = {
1743       0x55, // pushq %rbp
1744       0x5d, // popq %rbp
1745       0x90  // nop
1746   };
1747 
1748   sample_range = AddressRange(0x1000, sizeof(data));
1749 
1750   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1751       data, sizeof(data), sample_range, unwind_plan));
1752 
1753   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1754   EXPECT_EQ(2ull, row_sp->GetOffset());
1755   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1756   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1757   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1758   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
1759 }
1760 
1761 TEST_F(Testx86AssemblyInspectionEngine, TestPopR12) {
1762   UnwindPlan::Row::RegisterLocation regloc;
1763   UnwindPlan::RowSP row_sp;
1764   AddressRange sample_range;
1765   UnwindPlan unwind_plan(eRegisterKindLLDB);
1766   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
1767 
1768   uint8_t data[] = {
1769       0x41, 0x54, // pushq %r12
1770       0x41, 0x5c, // popq %r12
1771       0x90        // nop
1772   };
1773 
1774   sample_range = AddressRange(0x1000, sizeof(data));
1775 
1776   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1777       data, sizeof(data), sample_range, unwind_plan));
1778 
1779   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1780   EXPECT_EQ(4ull, row_sp->GetOffset());
1781   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1782   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1783   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1784   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r12, regloc));
1785 }
1786 
1787 TEST_F(Testx86AssemblyInspectionEngine, TestPopR13) {
1788   UnwindPlan::Row::RegisterLocation regloc;
1789   UnwindPlan::RowSP row_sp;
1790   AddressRange sample_range;
1791   UnwindPlan unwind_plan(eRegisterKindLLDB);
1792   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
1793 
1794   uint8_t data[] = {
1795       0x41, 0x55, // pushq %r13
1796       0x41, 0x5d, // popq %r13
1797       0x90        // nop
1798   };
1799 
1800   sample_range = AddressRange(0x1000, sizeof(data));
1801 
1802   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1803       data, sizeof(data), sample_range, unwind_plan));
1804 
1805   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1806   EXPECT_EQ(4ull, row_sp->GetOffset());
1807   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1808   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1809   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1810   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc));
1811 }
1812 
1813 TEST_F(Testx86AssemblyInspectionEngine, TestPopR14) {
1814   UnwindPlan::Row::RegisterLocation regloc;
1815   UnwindPlan::RowSP row_sp;
1816   AddressRange sample_range;
1817   UnwindPlan unwind_plan(eRegisterKindLLDB);
1818   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
1819 
1820   uint8_t data[] = {
1821       0x41, 0x56, // pushq %r14
1822       0x41, 0x5e, // popq %r14
1823       0x90        // nop
1824   };
1825 
1826   sample_range = AddressRange(0x1000, sizeof(data));
1827 
1828   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1829       data, sizeof(data), sample_range, unwind_plan));
1830 
1831   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1832   EXPECT_EQ(4ull, row_sp->GetOffset());
1833   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1834   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1835   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1836   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc));
1837 }
1838 
1839 TEST_F(Testx86AssemblyInspectionEngine, TestPopR15) {
1840   UnwindPlan::Row::RegisterLocation regloc;
1841   UnwindPlan::RowSP row_sp;
1842   AddressRange sample_range;
1843   UnwindPlan unwind_plan(eRegisterKindLLDB);
1844   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
1845 
1846   uint8_t data[] = {
1847       0x41, 0x57, // pushq %r15
1848       0x41, 0x5f, // popq %r15
1849       0x90        // nop
1850   };
1851 
1852   sample_range = AddressRange(0x1000, sizeof(data));
1853 
1854   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1855       data, sizeof(data), sample_range, unwind_plan));
1856 
1857   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1858   EXPECT_EQ(4ull, row_sp->GetOffset());
1859   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1860   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1861   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
1862   EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc));
1863 }
1864 
1865 TEST_F(Testx86AssemblyInspectionEngine, TestPopEBX) {
1866   UnwindPlan::Row::RegisterLocation regloc;
1867   UnwindPlan::RowSP row_sp;
1868   AddressRange sample_range;
1869   UnwindPlan unwind_plan(eRegisterKindLLDB);
1870   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
1871 
1872   uint8_t data[] = {
1873       0x53, // pushl %ebx
1874       0x5b, // popl %ebx
1875       0x90  // nop
1876   };
1877 
1878   sample_range = AddressRange(0x1000, sizeof(data));
1879 
1880   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1881       data, sizeof(data), sample_range, unwind_plan));
1882 
1883   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1884   EXPECT_EQ(2ull, row_sp->GetOffset());
1885   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1886   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1887   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
1888   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc));
1889 }
1890 
1891 TEST_F(Testx86AssemblyInspectionEngine, TestPopEBP) {
1892   UnwindPlan::Row::RegisterLocation regloc;
1893   UnwindPlan::RowSP row_sp;
1894   AddressRange sample_range;
1895   UnwindPlan unwind_plan(eRegisterKindLLDB);
1896   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
1897 
1898   uint8_t data[] = {
1899       0x55, // pushl %ebp
1900       0x5d, // popl %ebp
1901       0x90  // nop
1902   };
1903 
1904   sample_range = AddressRange(0x1000, sizeof(data));
1905 
1906   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1907       data, sizeof(data), sample_range, unwind_plan));
1908 
1909   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1910   EXPECT_EQ(2ull, row_sp->GetOffset());
1911   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1912   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1913   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
1914   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
1915 }
1916 
1917 TEST_F(Testx86AssemblyInspectionEngine, TestPopESI) {
1918   UnwindPlan::Row::RegisterLocation regloc;
1919   UnwindPlan::RowSP row_sp;
1920   AddressRange sample_range;
1921   UnwindPlan unwind_plan(eRegisterKindLLDB);
1922   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
1923 
1924   uint8_t data[] = {
1925       0x56, // pushl %esi
1926       0x5e, // popl %esi
1927       0x90  // nop
1928   };
1929 
1930   sample_range = AddressRange(0x1000, sizeof(data));
1931 
1932   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1933       data, sizeof(data), sample_range, unwind_plan));
1934 
1935   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1936   EXPECT_EQ(2ull, row_sp->GetOffset());
1937   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1938   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1939   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
1940   EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc));
1941 }
1942 
1943 TEST_F(Testx86AssemblyInspectionEngine, TestPopEDI) {
1944   UnwindPlan::Row::RegisterLocation regloc;
1945   UnwindPlan::RowSP row_sp;
1946   AddressRange sample_range;
1947   UnwindPlan unwind_plan(eRegisterKindLLDB);
1948   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
1949 
1950   uint8_t data[] = {
1951       0x57, // pushl %edi
1952       0x5f, // popl %edi
1953       0x90  // nop
1954   };
1955 
1956   sample_range = AddressRange(0x1000, sizeof(data));
1957 
1958   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1959       data, sizeof(data), sample_range, unwind_plan));
1960 
1961   row_sp = unwind_plan.GetRowForFunctionOffset(2);
1962   EXPECT_EQ(2ull, row_sp->GetOffset());
1963   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1964   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
1965   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
1966   EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc));
1967 }
1968 
1969 // We don't track these registers, but make sure the CFA address is updated
1970 // if we're defining the CFA in term of esp.
1971 TEST_F(Testx86AssemblyInspectionEngine, Testi386IgnoredRegisters) {
1972   UnwindPlan::Row::RegisterLocation regloc;
1973   UnwindPlan::RowSP row_sp;
1974   AddressRange sample_range;
1975   UnwindPlan unwind_plan(eRegisterKindLLDB);
1976   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
1977 
1978   uint8_t data[] = {
1979       0x0e, // push cs
1980       0x16, // push ss
1981       0x1e, // push ds
1982       0x06, // push es
1983 
1984       0x07, // pop es
1985       0x1f, // pop ds
1986       0x17, // pop ss
1987 
1988       0x90 // nop
1989   };
1990 
1991   sample_range = AddressRange(0x1000, sizeof(data));
1992 
1993   EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
1994       data, sizeof(data), sample_range, unwind_plan));
1995 
1996   row_sp = unwind_plan.GetRowForFunctionOffset(4);
1997   EXPECT_EQ(4ull, row_sp->GetOffset());
1998   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
1999   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2000   EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset());
2001 
2002   row_sp = unwind_plan.GetRowForFunctionOffset(7);
2003   EXPECT_EQ(7ull, row_sp->GetOffset());
2004   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
2005   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2006   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2007 }
2008 
2009 TEST_F(Testx86AssemblyInspectionEngine, TestLEAVE) {
2010   UnwindPlan::Row::RegisterLocation regloc;
2011   UnwindPlan::RowSP row_sp;
2012   AddressRange sample_range;
2013   UnwindPlan unwind_plan(eRegisterKindLLDB);
2014   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
2015   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
2016 
2017   uint8_t data[] = {
2018       0x55, // push %rbp/ebp
2019       0xc9, // leave
2020       0x90  // nop
2021   };
2022 
2023   sample_range = AddressRange(0x1000, sizeof(data));
2024 
2025   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
2026       data, sizeof(data), sample_range, unwind_plan));
2027 
2028   row_sp = unwind_plan.GetRowForFunctionOffset(2);
2029   EXPECT_EQ(2ull, row_sp->GetOffset());
2030   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
2031   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2032   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2033   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
2034 
2035   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
2036       data, sizeof(data), sample_range, unwind_plan));
2037 
2038   row_sp = unwind_plan.GetRowForFunctionOffset(2);
2039   EXPECT_EQ(2ull, row_sp->GetOffset());
2040   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
2041   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2042   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
2043   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
2044 }
2045 
2046 // In i386, which lacks pc-relative addressing, a common code sequence
2047 // is to call the next instruction (i.e. call imm32, value of 0) which
2048 // pushes the addr of the next insn on the stack, and then pop that value
2049 // into a register (the "pic base" register).
2050 TEST_F(Testx86AssemblyInspectionEngine, TestCALLNextInsn) {
2051   UnwindPlan::Row::RegisterLocation regloc;
2052   UnwindPlan::RowSP row_sp;
2053   AddressRange sample_range;
2054   UnwindPlan unwind_plan(eRegisterKindLLDB);
2055   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
2056 
2057   uint8_t data[] = {
2058       0xe8, 0x00, 0x00, 0x00, 0x00, // call 0
2059       0x90                          // nop
2060   };
2061 
2062   sample_range = AddressRange(0x1000, sizeof(data));
2063 
2064   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
2065       data, sizeof(data), sample_range, unwind_plan));
2066 
2067   row_sp = unwind_plan.GetRowForFunctionOffset(5);
2068   EXPECT_EQ(5ull, row_sp->GetOffset());
2069   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
2070   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2071   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2072   EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
2073 }
2074 
2075 TEST_F(Testx86AssemblyInspectionEngine, TestSpillRegToStackViaMOVx86_64) {
2076   UnwindPlan::Row::RegisterLocation regloc;
2077   UnwindPlan::RowSP row_sp;
2078   AddressRange sample_range;
2079   UnwindPlan unwind_plan(eRegisterKindLLDB);
2080   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
2081 
2082   uint8_t data[] = {
2083       0x55,                                     // pushq %rbp
2084       0x48, 0x89, 0xe5,                         // movq %rsp, %rbp
2085       0x4c, 0x89, 0x75, 0xc0,                   // movq   %r14, -0x40(%rbp)
2086       0x4c, 0x89, 0xbd, 0x28, 0xfa, 0xff, 0xff, // movq   %r15, -0x5d8(%rbp)
2087       0x48, 0x89, 0x5d, 0xb8,                   // movq %rbx, -0x48(%rbp)
2088       0x90                                      // nop
2089   };
2090 
2091   sample_range = AddressRange(0x1000, sizeof(data));
2092 
2093   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
2094       data, sizeof(data), sample_range, unwind_plan));
2095 
2096   row_sp = unwind_plan.GetRowForFunctionOffset(19);
2097   EXPECT_EQ(19ull, row_sp->GetOffset());
2098   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp);
2099   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
2100 
2101   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc));
2102   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
2103   EXPECT_EQ(-80, regloc.GetOffset());
2104 
2105   EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc));
2106   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
2107   EXPECT_EQ(-1512, regloc.GetOffset());
2108 
2109   EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc));
2110   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
2111   EXPECT_EQ(-88, regloc.GetOffset());
2112 }
2113 
2114 TEST_F(Testx86AssemblyInspectionEngine, TestSpillRegToStackViaMOVi386) {
2115   UnwindPlan::Row::RegisterLocation regloc;
2116   UnwindPlan::RowSP row_sp;
2117   AddressRange sample_range;
2118   UnwindPlan unwind_plan(eRegisterKindLLDB);
2119   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
2120 
2121   uint8_t data[] = {
2122       0x55,                               // pushl %ebp
2123       0x89, 0xe5,                         // movl %esp, %ebp
2124       0x89, 0x9d, 0xb0, 0xfe, 0xff, 0xff, // movl %ebx, -0x150(%ebp)
2125       0x89, 0x75, 0xe0,                   // movl %esi, -0x20(%ebp)
2126       0x90                                // nop
2127   };
2128 
2129   sample_range = AddressRange(0x1000, sizeof(data));
2130 
2131   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
2132       data, sizeof(data), sample_range, unwind_plan));
2133 
2134   row_sp = unwind_plan.GetRowForFunctionOffset(12);
2135   EXPECT_EQ(12ull, row_sp->GetOffset());
2136   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp);
2137   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2138 
2139   EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc));
2140   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
2141   EXPECT_EQ(-344, regloc.GetOffset());
2142 
2143   EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc));
2144   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
2145   EXPECT_EQ(-40, regloc.GetOffset());
2146 }
2147 
2148 TEST_F(Testx86AssemblyInspectionEngine, TestSimplex86_64Augmented) {
2149   UnwindPlan::Row::RegisterLocation regloc;
2150   UnwindPlan::RowSP row_sp;
2151   AddressRange sample_range;
2152   UnwindPlan unwind_plan(eRegisterKindLLDB);
2153   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
2154 
2155   uint8_t data[] = {
2156       0x55,             // pushq %rbp
2157       0x48, 0x89, 0xe5, // movq %rsp, %rbp
2158 
2159       // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite
2160       // has a bug where it can't augment a function that is just
2161       // prologue+epilogue - it needs at least one other instruction
2162       // in between.
2163       0x90, // nop
2164 
2165       0x5d, // popq %rbp
2166       0xc3  // retq
2167   };
2168 
2169   sample_range = AddressRange(0x1000, sizeof(data));
2170 
2171   unwind_plan.SetSourceName("unit testing hand-created unwind plan");
2172   unwind_plan.SetPlanValidAddressRange(sample_range);
2173   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
2174 
2175   row_sp.reset(new UnwindPlan::Row);
2176 
2177   // Describe offset 0
2178   row_sp->SetOffset(0);
2179   row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 8);
2180 
2181   regloc.SetAtCFAPlusOffset(-8);
2182   row_sp->SetRegisterInfo(k_rip, regloc);
2183 
2184   unwind_plan.AppendRow(row_sp);
2185 
2186   // Allocate a new Row, populate it with the existing Row contents.
2187   UnwindPlan::Row *new_row = new UnwindPlan::Row;
2188   *new_row = *row_sp.get();
2189   row_sp.reset(new_row);
2190 
2191   // Describe offset 1
2192   row_sp->SetOffset(1);
2193   row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 16);
2194   regloc.SetAtCFAPlusOffset(-16);
2195   row_sp->SetRegisterInfo(k_rbp, regloc);
2196   unwind_plan.AppendRow(row_sp);
2197 
2198   // Allocate a new Row, populate it with the existing Row contents.
2199   new_row = new UnwindPlan::Row;
2200   *new_row = *row_sp.get();
2201   row_sp.reset(new_row);
2202 
2203   // Describe offset 4
2204   row_sp->SetOffset(4);
2205   row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_rbp, 16);
2206   unwind_plan.AppendRow(row_sp);
2207 
2208   RegisterContextSP reg_ctx_sp;
2209   EXPECT_TRUE(engine64->AugmentUnwindPlanFromCallSite(
2210       data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp));
2211 
2212   row_sp = unwind_plan.GetRowForFunctionOffset(6);
2213   EXPECT_EQ(6ull, row_sp->GetOffset());
2214   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
2215   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2216 
2217   // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite
2218   // doesn't track register restores (pop'ing a reg value back from
2219   // the stack) - it was just written to make stepping work correctly.
2220   // Technically we should be able to do the following test, but it
2221   // won't work today - the unwind plan will still say that the caller's
2222   // rbp is on the stack.
2223   // EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
2224 }
2225 
2226 TEST_F(Testx86AssemblyInspectionEngine, TestSimplei386ugmented) {
2227   UnwindPlan::Row::RegisterLocation regloc;
2228   UnwindPlan::RowSP row_sp;
2229   AddressRange sample_range;
2230   UnwindPlan unwind_plan(eRegisterKindLLDB);
2231   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
2232 
2233   uint8_t data[] = {
2234       0x55,       // pushl %ebp
2235       0x89, 0xe5, // movl %esp, %ebp
2236 
2237       // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite
2238       // has a bug where it can't augment a function that is just
2239       // prologue+epilogue - it needs at least one other instruction
2240       // in between.
2241       0x90, // nop
2242 
2243       0x5d, // popl %ebp
2244       0xc3  // retl
2245   };
2246 
2247   sample_range = AddressRange(0x1000, sizeof(data));
2248 
2249   unwind_plan.SetSourceName("unit testing hand-created unwind plan");
2250   unwind_plan.SetPlanValidAddressRange(sample_range);
2251   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
2252 
2253   row_sp.reset(new UnwindPlan::Row);
2254 
2255   // Describe offset 0
2256   row_sp->SetOffset(0);
2257   row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_esp, 4);
2258 
2259   regloc.SetAtCFAPlusOffset(-4);
2260   row_sp->SetRegisterInfo(k_eip, regloc);
2261 
2262   unwind_plan.AppendRow(row_sp);
2263 
2264   // Allocate a new Row, populate it with the existing Row contents.
2265   UnwindPlan::Row *new_row = new UnwindPlan::Row;
2266   *new_row = *row_sp.get();
2267   row_sp.reset(new_row);
2268 
2269   // Describe offset 1
2270   row_sp->SetOffset(1);
2271   row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_esp, 8);
2272   regloc.SetAtCFAPlusOffset(-8);
2273   row_sp->SetRegisterInfo(k_ebp, regloc);
2274   unwind_plan.AppendRow(row_sp);
2275 
2276   // Allocate a new Row, populate it with the existing Row contents.
2277   new_row = new UnwindPlan::Row;
2278   *new_row = *row_sp.get();
2279   row_sp.reset(new_row);
2280 
2281   // Describe offset 3
2282   row_sp->SetOffset(3);
2283   row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_ebp, 8);
2284   unwind_plan.AppendRow(row_sp);
2285 
2286   RegisterContextSP reg_ctx_sp;
2287   EXPECT_TRUE(engine32->AugmentUnwindPlanFromCallSite(
2288       data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp));
2289 
2290   row_sp = unwind_plan.GetRowForFunctionOffset(5);
2291   EXPECT_EQ(5ull, row_sp->GetOffset());
2292   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
2293   EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
2294 
2295   // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite
2296   // doesn't track register restores (pop'ing a reg value back from
2297   // the stack) - it was just written to make stepping work correctly.
2298   // Technically we should be able to do the following test, but it
2299   // won't work today - the unwind plan will still say that the caller's
2300   // ebp is on the stack.
2301   // EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
2302 }
2303 
2304 // Check that the i386 disassembler disassembles past an opcode that
2305 // is only valid in 32-bit mode (non-long mode), and the x86_64 disassembler
2306 // stops
2307 // disassembling at that point (long-mode).
2308 TEST_F(Testx86AssemblyInspectionEngine, Test32BitOnlyInstruction) {
2309   UnwindPlan::Row::RegisterLocation regloc;
2310   UnwindPlan::RowSP row_sp;
2311   AddressRange sample_range;
2312   UnwindPlan unwind_plan(eRegisterKindLLDB);
2313   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
2314   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
2315 
2316   uint8_t data[] = {
2317       0x43, // incl $ebx --- an invalid opcode in 64-bit mode
2318       0x55, // pushl %ebp
2319       0x90  // nop
2320   };
2321 
2322   sample_range = AddressRange(0x1000, sizeof(data));
2323 
2324   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
2325       data, sizeof(data), sample_range, unwind_plan));
2326 
2327   row_sp = unwind_plan.GetRowForFunctionOffset(2);
2328   EXPECT_EQ(2ull, row_sp->GetOffset());
2329   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
2330   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2331   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2332 
2333   EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc));
2334   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
2335   EXPECT_EQ(-8, regloc.GetOffset());
2336 
2337   unwind_plan.Clear();
2338 
2339   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
2340       data, sizeof(data), sample_range, unwind_plan));
2341 
2342   row_sp = unwind_plan.GetRowForFunctionOffset(2);
2343   EXPECT_EQ(0ull, row_sp->GetOffset());
2344   EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
2345   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
2346   EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset());
2347 
2348   EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
2349 }
2350 
2351 TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign8BitDisp_i386) {
2352   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
2353 
2354   uint8_t data[] = {
2355       0x55,             // pushl %ebp
2356       0x89, 0xe5,       // movl %esp, %ebp
2357       0x53,             // pushl %ebx
2358       0x83, 0xe4, 0xf0, // andl $-16, %esp
2359       0x83, 0xec, 0x10, // subl $16, %esp
2360       0x8d, 0x65, 0xfc, // leal -4(%ebp), %esp
2361       0x5b,             // popl %ebx
2362       0x5d,             // popl %ebp
2363       0xc3,             // retl
2364   };
2365 
2366   AddressRange sample_range(0x1000, sizeof(data));
2367   UnwindPlan plan(eRegisterKindLLDB);
2368   ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
2369                                                            sample_range, plan));
2370 
2371   UnwindPlan::Row::CFAValue esp_plus_4, esp_plus_8, ebp_plus_8;
2372   esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);
2373   esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);
2374   ebp_plus_8.SetIsRegisterPlusOffset(k_ebp, 8);
2375 
2376   EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(0)->GetCFAValue());
2377   EXPECT_EQ(esp_plus_8, plan.GetRowForFunctionOffset(1)->GetCFAValue());
2378   for (size_t i = 3; i < sizeof(data) - 2; ++i)
2379     EXPECT_EQ(ebp_plus_8, plan.GetRowForFunctionOffset(i)->GetCFAValue())
2380         << "i: " << i;
2381   EXPECT_EQ(esp_plus_4,
2382             plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());
2383 }
2384 
2385 TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) {
2386   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
2387 
2388   uint8_t data[] = {
2389       0x55,                                     // pushq %rbp
2390       0x48, 0x89, 0xe5,                         // movq %rsp, %rbp
2391       0x53,                                     // pushl %rbx
2392       0x48, 0x83, 0xe4, 0xf0,                   // andq $-16, %rsp
2393       0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $256, %rsp
2394       0x48, 0x8d, 0x65, 0xf8,                   // leaq -8(%rbp), %rsp
2395       0x5b,                                     // popq %rbx
2396       0x5d,                                     // popq %rbp
2397       0xc3,                                     // retq
2398   };
2399 
2400   AddressRange sample_range(0x1000, sizeof(data));
2401   UnwindPlan plan(eRegisterKindLLDB);
2402   ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
2403                                                            sample_range, plan));
2404 
2405   UnwindPlan::Row::CFAValue rsp_plus_8, rsp_plus_16, rbp_plus_16;
2406   rsp_plus_8.SetIsRegisterPlusOffset(k_rsp, 8);
2407   rsp_plus_16.SetIsRegisterPlusOffset(k_rsp, 16);
2408   rbp_plus_16.SetIsRegisterPlusOffset(k_rbp, 16);
2409 
2410   EXPECT_EQ(rsp_plus_8, plan.GetRowForFunctionOffset(0)->GetCFAValue());
2411   EXPECT_EQ(rsp_plus_16, plan.GetRowForFunctionOffset(1)->GetCFAValue());
2412   for (size_t i = 4; i < sizeof(data) - 2; ++i)
2413     EXPECT_EQ(rbp_plus_16, plan.GetRowForFunctionOffset(i)->GetCFAValue())
2414         << "i: " << i;
2415   EXPECT_EQ(rsp_plus_8,
2416             plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());
2417 }
2418 
2419 // Give the disassembler random bytes to test that it doesn't exceed
2420 // the bounds of the array when run under clang's address sanitizer.
2421 TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) {
2422   AddressRange sample_range;
2423   UnwindPlan unwind_plan(eRegisterKindLLDB);
2424   std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
2425   std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
2426 
2427   uint8_t data[] = {
2428       0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2429       0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
2430 
2431   sample_range = AddressRange(0x1000, sizeof(data));
2432 
2433   EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
2434       data, sizeof(data), sample_range, unwind_plan));
2435 
2436   unwind_plan.Clear();
2437 
2438   EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
2439       data, sizeof(data), sample_range, unwind_plan));
2440 
2441 }
2442 
2443