brintos

brintos / llvm-project-archived public Read only

0
0
Text · 102.5 KiB · 30e2634 Raw
2925 lines · cpp
1//===-- Testx86AssemblyInspectionEngine.cpp -------------------------------===//2 3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#include "gtest/gtest.h"11 12#include <memory>13#include <vector>14 15#include "Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h"16#include "lldb/Core/Address.h"17#include "lldb/Core/AddressRange.h"18#include "lldb/Symbol/UnwindPlan.h"19#include "lldb/Utility/ArchSpec.h"20#include "lldb/Utility/StreamString.h"21 22#include "llvm/Support/TargetSelect.h"23 24using namespace lldb;25using namespace lldb_private;26 27class Testx86AssemblyInspectionEngine : public testing::Test {28public:29  static void SetUpTestCase();30 31  //  static void TearDownTestCase() { }32 33  //  virtual void SetUp() override { }34 35  //  virtual void TearDown() override { }36 37protected:38};39 40void Testx86AssemblyInspectionEngine::SetUpTestCase() {41  llvm::InitializeAllTargets();42  llvm::InitializeAllAsmPrinters();43  llvm::InitializeAllTargetMCs();44  llvm::InitializeAllDisassemblers();45}46 47// only defining the register names / numbers that the unwinder is actually48// using today49 50// names should match the constants below.  These will be the eRegisterKindLLDB51// register numbers.52 53const char *x86_64_reg_names[] = {"rax", "rbx", "rcx", "rdx", "rsp", "rbp",54                                  "rsi", "rdi", "r8",  "r9",  "r10", "r11",55                                  "r12", "r13", "r14", "r15", "rip"};56 57enum x86_64_regs {58  k_rax = 0,59  k_rbx = 1,60  k_rcx = 2,61  k_rdx = 3,62  k_rsp = 4,63  k_rbp = 5,64  k_rsi = 6,65  k_rdi = 7,66  k_r8 = 8,67  k_r9 = 9,68  k_r10 = 10,69  k_r11 = 11,70  k_r12 = 12,71  k_r13 = 13,72  k_r14 = 14,73  k_r15 = 15,74  k_rip = 1675};76 77// names should match the constants below.  These will be the eRegisterKindLLDB78// register numbers.79 80const char *i386_reg_names[] = {"eax", "ecx", "edx", "ebx", "esp",81                                "ebp", "esi", "edi", "eip"};82 83enum i386_regs {84  k_eax = 0,85  k_ecx = 1,86  k_edx = 2,87  k_ebx = 3,88  k_esp = 4,89  k_ebp = 5,90  k_esi = 6,91  k_edi = 7,92  k_eip = 893};94 95std::unique_ptr<x86AssemblyInspectionEngine> Getx86_64Inspector() {96 97  ArchSpec arch("x86_64-apple-macosx");98  std::unique_ptr<x86AssemblyInspectionEngine> engine(99      new x86AssemblyInspectionEngine(arch));100 101  std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;102  int i = 0;103  for (const auto &name : x86_64_reg_names) {104    x86AssemblyInspectionEngine::lldb_reg_info ri;105    ri.name = name;106    ri.lldb_regnum = i++;107    lldb_regnums.push_back(ri);108  }109 110  engine->Initialize(lldb_regnums);111  return engine;112}113 114std::unique_ptr<x86AssemblyInspectionEngine> Geti386Inspector() {115 116  ArchSpec arch("i386-apple-macosx");117  std::unique_ptr<x86AssemblyInspectionEngine> engine(118      new x86AssemblyInspectionEngine(arch));119 120  std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;121  int i = 0;122  for (const auto &name : i386_reg_names) {123    x86AssemblyInspectionEngine::lldb_reg_info ri;124    ri.name = name;125    ri.lldb_regnum = i++;126    lldb_regnums.push_back(ri);127  }128 129  engine->Initialize(lldb_regnums);130  return engine;131}132 133namespace lldb_private {134static std::ostream &operator<<(std::ostream &OS,135                                const UnwindPlan::Row::FAValue &CFA) {136  StreamString S;137  CFA.Dump(S, nullptr, nullptr);138  return OS << S.GetData();139}140} // namespace lldb_private141 142TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) {143  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();144 145  // 'int main() { }' compiled for x86_64-apple-macosx with clang146  uint8_t data[] = {147      0x55,             // offset 0 -- pushq %rbp148      0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp149      0x31, 0xc0,       // offset 4 -- xorl %eax, %eax150      0x5d,             // offset 6 -- popq %rbp151      0xc3              // offset 7 -- retq152  };153 154  AddressRange sample_range(0x1000, sizeof(data));155 156  UnwindPlan unwind_plan(eRegisterKindLLDB);157  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(158      data, sizeof(data), sample_range, unwind_plan));159 160  // Expect four unwind rows:161  // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]162  // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]163  // 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]164  // 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]165 166  EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_rsp);167  EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==168              eLazyBoolYes);169  EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);170 171  UnwindPlan::Row::AbstractRegisterLocation regloc;172 173  // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]174  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(0);175  EXPECT_EQ(0, row->GetOffset());176  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);177  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);178  EXPECT_EQ(8, row->GetCFAValue().GetOffset());179 180  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));181  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());182  EXPECT_EQ(-8, regloc.GetOffset());183 184  // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]185  row = unwind_plan.GetRowForFunctionOffset(1);186  EXPECT_EQ(1, row->GetOffset());187  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);188  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);189  EXPECT_EQ(16, row->GetCFAValue().GetOffset());190 191  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));192  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());193  EXPECT_EQ(-8, regloc.GetOffset());194 195  // 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]196  row = unwind_plan.GetRowForFunctionOffset(4);197  EXPECT_EQ(4, row->GetOffset());198  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);199  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);200  EXPECT_EQ(16, row->GetCFAValue().GetOffset());201 202  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));203  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());204  EXPECT_EQ(-8, regloc.GetOffset());205 206  // 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]207  row = unwind_plan.GetRowForFunctionOffset(7);208  EXPECT_EQ(7, row->GetOffset());209  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);210  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);211  EXPECT_EQ(8, row->GetCFAValue().GetOffset());212 213  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));214  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());215  EXPECT_EQ(-8, regloc.GetOffset());216}217 218TEST_F(Testx86AssemblyInspectionEngine, TestSimple32bitFrameFunction) {219  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();220 221  // 'int main() { }' compiled for i386-apple-macosx with clang222  uint8_t data[] = {223      0x55,       // offset 0 -- pushl %ebp224      0x89, 0xe5, // offset 1 -- movl %esp, %ebp225      0x31, 0xc0, // offset 3 -- xorl %eax, %eax226      0x5d,       // offset 5 -- popl %ebp227      0xc3        // offset 6 -- retl228  };229 230  AddressRange sample_range(0x1000, sizeof(data));231 232  UnwindPlan unwind_plan(eRegisterKindLLDB);233  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(234      data, sizeof(data), sample_range, unwind_plan));235 236  // Expect four unwind rows:237  // 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]238  // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]239  // 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]240  // 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]241 242  EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_esp);243  EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==244              eLazyBoolYes);245  EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);246 247  UnwindPlan::Row::AbstractRegisterLocation regloc;248 249  // offset 0 -- pushl %ebp250  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(0);251  EXPECT_EQ(0, row->GetOffset());252  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);253  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);254  EXPECT_EQ(4, row->GetCFAValue().GetOffset());255 256  EXPECT_TRUE(row->GetRegisterInfo(k_eip, regloc));257  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());258  EXPECT_TRUE(regloc.GetOffset() == -4);259 260  // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]261  row = unwind_plan.GetRowForFunctionOffset(1);262  EXPECT_EQ(1, row->GetOffset());263  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);264  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);265  EXPECT_EQ(8, row->GetCFAValue().GetOffset());266 267  EXPECT_TRUE(row->GetRegisterInfo(k_eip, regloc));268  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());269  EXPECT_EQ(-4, regloc.GetOffset());270 271  // 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]272  row = unwind_plan.GetRowForFunctionOffset(3);273  EXPECT_EQ(3, row->GetOffset());274  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_ebp);275  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);276  EXPECT_EQ(8, row->GetCFAValue().GetOffset());277 278  EXPECT_TRUE(row->GetRegisterInfo(k_eip, regloc));279  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());280  EXPECT_EQ(-4, regloc.GetOffset());281 282  // 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]283  row = unwind_plan.GetRowForFunctionOffset(6);284  EXPECT_EQ(6, row->GetOffset());285  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);286  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);287  EXPECT_EQ(4, row->GetCFAValue().GetOffset());288 289  EXPECT_TRUE(row->GetRegisterInfo(k_eip, regloc));290  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());291  EXPECT_EQ(-4, regloc.GetOffset());292}293 294TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessBigStackFrame) {295  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();296 297  // this source file:298  //299  // #include <stdio.h>300  // int main (int argc, char **argv)301  // {302  //303  //     const int arrsize = 60;304  //     int buf[arrsize * arrsize];305  //     int accum = argc;306  //     for (int i = 0; i < arrsize; i++)307  //         for (int j = 0; j < arrsize; j++)308  //         {309  //             if (i > 0 && j > 0)310  //             {311  //                 int n = buf[(i-1) * (j-1)] * 2;312  //                 int m = buf[(i-1) * (j-1)] / 2;313  //                 int j = buf[(i-1) * (j-1)] + 2;314  //                 int k = buf[(i-1) * (j-1)] - 2;315  //                 printf ("%d ", n + m + j + k);316  //                 buf[(i-1) * (j-1)] += n - m + j - k;317  //             }318  //             buf[i*j] = accum++;319  //         }320  //321  //     return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize *322  //     arrsize) - 3]);323  // }324  //325  // compiled 'clang -fomit-frame-pointer -Os' for x86_64-apple-macosx326 327  uint8_t data[] = {328      0x55,       // offset 0  -- pushq %rbp329      0x41, 0x57, // offset 1  -- pushq %r15330      0x41, 0x56, // offset 3  -- pushq %r14331      0x41, 0x55, // offset 5  -- pushq %r13332      0x41, 0x54, // offset 7  -- pushq %r12333      0x53,       // offset 9  -- pushq %rbx334      0x48, 0x81, 0xec, 0x68, 0x38, 0x00,335      0x00, // offset 10 -- subq $0x3868, %rsp336 337      // ....338 339      0x48, 0x81, 0xc4, 0x68, 0x38, 0x00,340      0x00,                        // offset 17 -- addq $0x3868, %rsp341      0x5b,                        // offset 24 -- popq %rbx342      0x41, 0x5c,                  // offset 25 -- popq %r12343      0x41, 0x5d,                  // offset 27 -- popq %r13344      0x41, 0x5e,                  // offset 29 -- popq %r14345      0x41, 0x5f,                  // offset 31 -- popq %r15346      0x5d,                        // offset 33 -- popq %rbp347      0xc3,                        // offset 34 -- retq348      0xe8, 0x12, 0x34, 0x56, 0x78 // offset 35 -- callq whatever349  };350 351  AddressRange sample_range(0x1000, sizeof(data));352 353  UnwindPlan unwind_plan(eRegisterKindLLDB);354  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(355      data, sizeof(data), sample_range, unwind_plan));356 357  // Unwind rules should look like358  // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]359  // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]360  // 3: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8]361  // 5: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24]362  // rip=[CFA-8363  // 7: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32]364  // r15=[CFA-24] rip=[CFA-8]365  // 9: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40]366  // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]367  // 10: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]368  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]369  // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]370  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]371 372  // 24: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]373  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]374  // 25: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40]375  // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]376  // 27: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32]377  // r15=[CFA-24] rip=[CFA-8]378  // 29: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24]379  // rip=[CFA-8]380  // 31: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8]381  // 33: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]382  // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]383 384  UnwindPlan::Row::AbstractRegisterLocation regloc;385 386  // grab the Row for when the prologue has finished executing:387  // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]388  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]389 390  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(17);391 392  EXPECT_EQ(17, row->GetOffset());393  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);394  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);395  EXPECT_EQ(14496, row->GetCFAValue().GetOffset());396 397  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));398  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());399  EXPECT_EQ(-8, regloc.GetOffset());400 401  EXPECT_TRUE(row->GetRegisterInfo(k_rbp, regloc));402  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());403  EXPECT_EQ(-16, regloc.GetOffset());404 405  EXPECT_TRUE(row->GetRegisterInfo(k_r15, regloc));406  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());407  EXPECT_EQ(-24, regloc.GetOffset());408 409  EXPECT_TRUE(row->GetRegisterInfo(k_r14, regloc));410  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());411  EXPECT_EQ(-32, regloc.GetOffset());412 413  EXPECT_TRUE(row->GetRegisterInfo(k_r13, regloc));414  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());415  EXPECT_EQ(-40, regloc.GetOffset());416 417  EXPECT_TRUE(row->GetRegisterInfo(k_r12, regloc));418  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());419  EXPECT_EQ(-48, regloc.GetOffset());420 421  EXPECT_TRUE(row->GetRegisterInfo(k_rbx, regloc));422  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());423  EXPECT_EQ(-56, regloc.GetOffset());424 425  // grab the Row for when the epilogue has finished executing:426  // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]427 428  row = unwind_plan.GetRowForFunctionOffset(34);429 430  EXPECT_EQ(34, row->GetOffset());431  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);432  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);433  EXPECT_EQ(8, row->GetCFAValue().GetOffset());434 435  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));436  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());437  EXPECT_EQ(-8, regloc.GetOffset());438 439  // these could be set to IsSame and be valid -- meaning that the440  // register value is the same as the caller's -- but I'd rather441  // they not be mentioned at all.442 443  EXPECT_FALSE(row->GetRegisterInfo(k_rax, regloc));444  EXPECT_FALSE(row->GetRegisterInfo(k_rbx, regloc));445  EXPECT_FALSE(row->GetRegisterInfo(k_rcx, regloc));446  EXPECT_FALSE(row->GetRegisterInfo(k_rdx, regloc));447  EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));448  EXPECT_FALSE(row->GetRegisterInfo(k_rsi, regloc));449  EXPECT_FALSE(row->GetRegisterInfo(k_rdi, regloc));450  EXPECT_FALSE(row->GetRegisterInfo(k_r8, regloc));451  EXPECT_FALSE(row->GetRegisterInfo(k_r9, regloc));452  EXPECT_FALSE(row->GetRegisterInfo(k_r10, regloc));453  EXPECT_FALSE(row->GetRegisterInfo(k_r11, regloc));454  EXPECT_FALSE(row->GetRegisterInfo(k_r12, regloc));455  EXPECT_FALSE(row->GetRegisterInfo(k_r13, regloc));456  EXPECT_FALSE(row->GetRegisterInfo(k_r14, regloc));457  EXPECT_FALSE(row->GetRegisterInfo(k_r15, regloc));458}459 460TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessBigStackFrame) {461  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();462 463  // this source file:464  //465  // #include <stdio.h>466  // int main (int argc, char **argv)467  // {468  //469  //     const int arrsize = 60;470  //     int buf[arrsize * arrsize];471  //     int accum = argc;472  //     for (int i = 0; i < arrsize; i++)473  //         for (int j = 0; j < arrsize; j++)474  //         {475  //             if (i > 0 && j > 0)476  //             {477  //                 int n = buf[(i-1) * (j-1)] * 2;478  //                 int m = buf[(i-1) * (j-1)] / 2;479  //                 int j = buf[(i-1) * (j-1)] + 2;480  //                 int k = buf[(i-1) * (j-1)] - 2;481  //                 printf ("%d ", n + m + j + k);482  //                 buf[(i-1) * (j-1)] += n - m + j - k;483  //             }484  //             buf[i*j] = accum++;485  //         }486  //487  //     return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize *488  //     arrsize) - 3]);489  // }490  //491  // compiled 'clang -arch i386 -fomit-frame-pointer -Os' for i386-apple-macosx492 493  // simplified assembly version of the above function, which is used as the494  // input495  // data:496  //497  // 	.section	__TEXT,__text,regular,pure_instructions498  // 	.macosx_version_min 10, 12499  // 	.globl	_main500  // 	.align	4, 0x90501  // _main:                                  ## @main502  // ## BB#0:503  // 	pushl %ebp504  // 	pushl %ebx505  // 	pushl %edi506  // 	pushl %esi507  // L0$pb:508  // 	subl $0x386c, %esp509  //     calll L1510  // L1:511  //     popl %ecx512  //     movl %ecx, 0x8(%esp)513  //     subl $0x8, %esp514  //     pushl %eax515  //     pushl 0x20(%esp)516  //     calll _puts517  //     addl $0x10, %esp518  //     incl %ebx519  //     addl $0x386c, %esp520  //     popl %esi521  //     popl %edi522  //     popl %ebx523  //     popl %ebp524  //     retl525  //526  // 	.section	__TEXT,__cstring,cstring_literals527  // L_.str:                                 ## @.str528  // 	.asciz	"HI"529  //530  //531  // .subsections_via_symbols532 533  uint8_t data[] = {534      0x55,535      // offset 0 -- pushl %ebp536 537      0x53,538      // offset 1 -- pushl %ebx539 540      0x57,541      // offset 2 -- pushl %edi542 543      0x56,544      // offset 3 -- pushl %esi545 546      0x81, 0xec, 0x6c, 0x38, 0x00, 0x00,547      // offset 4 -- subl $0x386c, %esp548 549      0xe8, 0x00, 0x00, 0x00, 0x00,550      // offset 10 -- calll 0551      // call the next instruction, to put the pc on the stack552 553      0x59,554      // offset 15 -- popl %ecx555      // pop the saved pc address into ecx556 557      0x89, 0x4c, 0x24, 0x08,558      // offset 16 -- movl %ecx, 0x8(%esp)559 560      // ....561 562      0x83, 0xec, 0x08,563      // offset 20 -- subl $0x8, %esp564 565      0x50,566      // offset 23 -- pushl %eax567 568      0xff, 0x74, 0x24, 0x20,569      // offset 24 -- pushl 0x20(%esp)570 571      0xe8, 0x8c, 0x00, 0x00, 0x00,572      // offset 28 -- calll puts573 574      0x83, 0xc4, 0x10,575      // offset 33 -- addl $0x10, %esp576      // get esp back to the value it was before the577      // alignment & argument saves for the puts call578 579      0x43,580      // offset 36 -- incl %ebx581 582      // ....583 584      0x81, 0xc4, 0x6c, 0x38, 0x00, 0x00,585      // offset 37 -- addl $0x386c, %esp586 587      0x5e,588      // offset 43 -- popl %esi589 590      0x5f,591      // offset 44 -- popl %edi592 593      0x5b,594      // offset 45 -- popl %ebx595 596      0x5d,597      // offset 46 -- popl %ebp598 599      0xc3,600      // offset 47 -- retl601 602      0xe8, 0x12, 0x34, 0x56, 0x78,603      // offset 48 -- calll __stack_chk_fail604  };605 606  AddressRange sample_range(0x1000, sizeof(data));607 608  UnwindPlan unwind_plan(eRegisterKindLLDB);609  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(610      data, sizeof(data), sample_range, unwind_plan));611 612  // Unwind rules should look like613  //614  //   0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]615  //   1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]616  //   2: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]617  //   3: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0618  //   eip=[CFA-4]619  //   4: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]620  //   esp=CFA+0 eip=[CFA-4]621  //  10: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]622  //  esp=CFA+0 eip=[CFA-4]623  //  15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]624  //  esp=CFA+0 eip=[CFA-4]625  //  16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]626  //  esp=CFA+0 eip=[CFA-4]627  //628  //  ....629  //630  //  23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]631  //  esp=CFA+0 eip=[CFA-4]632  //  24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]633  //  esp=CFA+0 eip=[CFA-4]634  //  28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]635  //  esp=CFA+0 eip=[CFA-4]636  //  36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]637  //  esp=CFA+0 eip=[CFA-4]638  //639  //  .....640  //641  //  37: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]642  //  esp=CFA+0 eip=[CFA-4]643  //  43: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]644  //  esp=CFA+0 eip=[CFA-4]645  //  44: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0646  //  eip=[CFA-4]647  //  45: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]648  //  46: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]649  //  47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]650  //  48: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]651  //  esp=CFA+0 eip=[CFA-4]652 653  UnwindPlan::Row::AbstractRegisterLocation regloc;654  const UnwindPlan::Row *row;655 656  // Check that we get the CFA correct for the pic base setup sequence657 658  // CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]659  // esp=CFA+0 eip=[CFA-4]660  row = unwind_plan.GetRowForFunctionOffset(10);661  EXPECT_EQ(10, row->GetOffset());662  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);663  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);664  EXPECT_EQ(14464, row->GetCFAValue().GetOffset());665 666  // 15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]667  // esp=CFA+0 eip=[CFA-4]668  row = unwind_plan.GetRowForFunctionOffset(15);669  EXPECT_EQ(15, row->GetOffset());670  EXPECT_EQ(14468, row->GetCFAValue().GetOffset());671 672  // 16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]673  // esp=CFA+0 eip=[CFA-4]674  row = unwind_plan.GetRowForFunctionOffset(16);675  EXPECT_EQ(16, row->GetOffset());676  EXPECT_EQ(14464, row->GetCFAValue().GetOffset());677 678  // Check that the row for offset 16 has the registers saved that we expect679 680  EXPECT_TRUE(row->GetRegisterInfo(k_eip, regloc));681  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());682  EXPECT_EQ(-4, regloc.GetOffset());683 684  EXPECT_TRUE(row->GetRegisterInfo(k_ebp, regloc));685  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());686  EXPECT_EQ(-8, regloc.GetOffset());687 688  EXPECT_TRUE(row->GetRegisterInfo(k_ebx, regloc));689  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());690  EXPECT_EQ(-12, regloc.GetOffset());691 692  EXPECT_TRUE(row->GetRegisterInfo(k_edi, regloc));693  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());694  EXPECT_EQ(-16, regloc.GetOffset());695 696  EXPECT_TRUE(row->GetRegisterInfo(k_esi, regloc));697  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());698  EXPECT_EQ(-20, regloc.GetOffset());699 700  //701  // Check the pushing & popping around the call printf instruction702 703  // 23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]704  // esp=CFA+0 eip=[CFA-4]705  row = unwind_plan.GetRowForFunctionOffset(23);706  EXPECT_EQ(23, row->GetOffset());707  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);708  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);709  EXPECT_EQ(14472, row->GetCFAValue().GetOffset());710 711  // 24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]712  // esp=CFA+0 eip=[CFA-4]713  row = unwind_plan.GetRowForFunctionOffset(24);714  EXPECT_EQ(24, row->GetOffset());715  EXPECT_EQ(14476, row->GetCFAValue().GetOffset());716 717  // 28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]718  // esp=CFA+0 eip=[CFA-4]719  row = unwind_plan.GetRowForFunctionOffset(28);720  EXPECT_EQ(28, row->GetOffset());721  EXPECT_EQ(14480, row->GetCFAValue().GetOffset());722 723  // 36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]724  // esp=CFA+0 eip=[CFA-4]725  row = unwind_plan.GetRowForFunctionOffset(36);726  EXPECT_EQ(36, row->GetOffset());727  EXPECT_EQ(14464, row->GetCFAValue().GetOffset());728 729  // Check that the epilogue gets us back to the original unwind state730 731  //  47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]732  row = unwind_plan.GetRowForFunctionOffset(47);733  EXPECT_EQ(47, row->GetOffset());734  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);735  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);736  EXPECT_EQ(4, row->GetCFAValue().GetOffset());737 738  EXPECT_TRUE(row->GetRegisterInfo(k_eip, regloc));739  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());740  EXPECT_EQ(-4, regloc.GetOffset());741 742  EXPECT_TRUE(row->GetRegisterInfo(k_esp, regloc));743  EXPECT_TRUE(regloc.IsCFAPlusOffset());744  EXPECT_EQ(0, regloc.GetOffset());745 746  // Check that no unexpected registers were saved747 748  EXPECT_FALSE(row->GetRegisterInfo(k_eax, regloc));749  EXPECT_FALSE(row->GetRegisterInfo(k_ebx, regloc));750  EXPECT_FALSE(row->GetRegisterInfo(k_ecx, regloc));751  EXPECT_FALSE(row->GetRegisterInfo(k_edx, regloc));752  EXPECT_FALSE(row->GetRegisterInfo(k_esi, regloc));753  EXPECT_FALSE(row->GetRegisterInfo(k_edi, regloc));754  EXPECT_FALSE(row->GetRegisterInfo(k_ebp, regloc));755}756 757TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessSmallStackFrame) {758  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();759 760  // this source file:761  // #include <stdio.h>762  // int main () {763  //    puts ("HI");764  // }765  //766  // compiled 'clang -fomit-frame-pointer' for x86_64-apple-macosx767 768  uint8_t data[] = {769      0x50,770      // offset 0  -- pushq %rax771 772      0x48, 0x8d, 0x3d, 0x32, 0x00, 0x00, 0x00,773      // offset 1 -- leaq 0x32(%rip), %rdi ; "HI"774 775      0xe8, 0x0b, 0x00, 0x00, 0x00,776      // offset 8 -- callq 0x100000f58 ; puts777 778      0x31, 0xc9,779      // offset 13 -- xorl %ecx, %ecx780 781      0x89, 0x44, 0x24, 0x04,782      // offset 15 -- movl %eax, 0x4(%rsp)783 784      0x89, 0xc8,785      // offset 19 -- movl %ecx, %eax786 787      0x59,788      // offset 21 -- popq %rcx789 790      0xc3791      // offset 22 -- retq792  };793 794  AddressRange sample_range(0x1000, sizeof(data));795 796  UnwindPlan unwind_plan(eRegisterKindLLDB);797  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(798      data, sizeof(data), sample_range, unwind_plan));799 800  // Unwind rules should look like801  //     0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]802  //     1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]803  //    22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]804 805  UnwindPlan::Row::AbstractRegisterLocation regloc;806 807  // grab the Row for when the prologue has finished executing:808  //     1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]809 810  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(13);811 812  EXPECT_EQ(1, row->GetOffset());813  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);814  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);815  EXPECT_EQ(16, row->GetCFAValue().GetOffset());816 817  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));818  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());819  EXPECT_EQ(-8, regloc.GetOffset());820 821  // none of these were spilled822 823  EXPECT_FALSE(row->GetRegisterInfo(k_rax, regloc));824  EXPECT_FALSE(row->GetRegisterInfo(k_rbx, regloc));825  EXPECT_FALSE(row->GetRegisterInfo(k_rcx, regloc));826  EXPECT_FALSE(row->GetRegisterInfo(k_rdx, regloc));827  EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));828  EXPECT_FALSE(row->GetRegisterInfo(k_rsi, regloc));829  EXPECT_FALSE(row->GetRegisterInfo(k_rdi, regloc));830  EXPECT_FALSE(row->GetRegisterInfo(k_r8, regloc));831  EXPECT_FALSE(row->GetRegisterInfo(k_r9, regloc));832  EXPECT_FALSE(row->GetRegisterInfo(k_r10, regloc));833  EXPECT_FALSE(row->GetRegisterInfo(k_r11, regloc));834  EXPECT_FALSE(row->GetRegisterInfo(k_r12, regloc));835  EXPECT_FALSE(row->GetRegisterInfo(k_r13, regloc));836  EXPECT_FALSE(row->GetRegisterInfo(k_r14, regloc));837  EXPECT_FALSE(row->GetRegisterInfo(k_r15, regloc));838 839  // grab the Row for when the epilogue has finished executing:840  //     22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]841 842  row = unwind_plan.GetRowForFunctionOffset(22);843 844  EXPECT_EQ(22, row->GetOffset());845  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);846  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);847  EXPECT_EQ(8, row->GetCFAValue().GetOffset());848 849  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));850  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());851  EXPECT_EQ(-8, regloc.GetOffset());852}853 854TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessSmallStackFrame) {855  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();856 857  // this source file:858  // #include <stdio.h>859  // int main () {860  //    puts ("HI");861  // }862  //863  // compiled 'clang -arch i386 -fomit-frame-pointer' for i386-apple-macosx864 865  uint8_t data[] = {866      0x83, 0xec, 0x0c,867      // offset 0 -- subl $0xc, %esp868 869      0xe8, 0x00, 0x00, 0x00, 0x00,870      // offset 3 -- calll 0 {call the next instruction, to put the pc on871      // the stack}872 873      0x58,874      // offset 8 -- popl %eax {pop the saved pc value off stack, into eax}875 876      0x8d, 0x80, 0x3a, 0x00, 0x00, 0x00,877      // offset 9 -- leal 0x3a(%eax),%eax878 879      0x89, 0x04, 0x24,880      // offset 15 -- movl %eax, (%esp)881 882      0xe8, 0x0d, 0x00, 0x00, 0x00,883      // offset 18 -- calll 0x1f94 (puts)884 885      0x31, 0xc9,886      // offset 23 -- xorl %ecx, %ecx887 888      0x89, 0x44, 0x24, 0x08,889      // offset 25 -- movl %eax, 0x8(%esp)890 891      0x89, 0xc8,892      // offset 29 -- movl %ecx, %eax893 894      0x83, 0xc4, 0x0c,895      // offset 31 -- addl $0xc, %esp896 897      0xc3898      // offset 34 -- retl899  };900 901  AddressRange sample_range(0x1000, sizeof(data));902 903  UnwindPlan unwind_plan(eRegisterKindLLDB);904  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(905      data, sizeof(data), sample_range, unwind_plan));906 907  // Unwind rules should look like908  // row[0]:    0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]909  // row[1]:    3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]910  // row[2]:    8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4]911  // row[3]:    9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]912  // row[4]:   34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]913 914  UnwindPlan::Row::AbstractRegisterLocation regloc;915 916  // Check unwind state before we set up the picbase register917  //      3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]918 919  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(3);920 921  EXPECT_EQ(3, row->GetOffset());922  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);923  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);924  EXPECT_EQ(16, row->GetCFAValue().GetOffset());925 926  // Check unwind state after we call the next instruction927  // 8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4]928 929  row = unwind_plan.GetRowForFunctionOffset(8);930  EXPECT_EQ(8, row->GetOffset());931  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);932  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);933  EXPECT_EQ(20, row->GetCFAValue().GetOffset());934 935  // Check unwind state after we pop the pic base value off the stack936  // row[3]:    9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]937 938  row = unwind_plan.GetRowForFunctionOffset(9);939  EXPECT_EQ(9, row->GetOffset());940  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);941  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);942  EXPECT_EQ(16, row->GetCFAValue().GetOffset());943 944  // Check that no unexpected registers were saved945 946  EXPECT_FALSE(row->GetRegisterInfo(k_eax, regloc));947  EXPECT_FALSE(row->GetRegisterInfo(k_ebx, regloc));948  EXPECT_FALSE(row->GetRegisterInfo(k_ecx, regloc));949  EXPECT_FALSE(row->GetRegisterInfo(k_edx, regloc));950  EXPECT_FALSE(row->GetRegisterInfo(k_esi, regloc));951  EXPECT_FALSE(row->GetRegisterInfo(k_edi, regloc));952  EXPECT_FALSE(row->GetRegisterInfo(k_ebp, regloc));953 954  // verify that we get back to the original unwind state before the ret955  //  34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]956 957  row = unwind_plan.GetRowForFunctionOffset(34);958  EXPECT_EQ(34, row->GetOffset());959  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);960  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);961  EXPECT_EQ(4, row->GetCFAValue().GetOffset());962}963 964TEST_F(Testx86AssemblyInspectionEngine, TestPushRBP) {965  UnwindPlan::Row::AbstractRegisterLocation regloc;966  const UnwindPlan::Row *row;967 968  uint8_t data[] = {969      0x55, // pushq %rbp970      0x90  // nop971  };972 973  AddressRange sample_range(0x1000, sizeof(data));974  UnwindPlan unwind_plan(eRegisterKindLLDB);975 976  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();977  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(978      data, sizeof(data), sample_range, unwind_plan));979 980  row = unwind_plan.GetRowForFunctionOffset(1);981 982  EXPECT_EQ(1, row->GetOffset());983  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);984  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);985  EXPECT_EQ(16, row->GetCFAValue().GetOffset());986 987  EXPECT_TRUE(row->GetRegisterInfo(k_rbp, regloc));988  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());989  EXPECT_EQ(-16, regloc.GetOffset());990 991  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();992  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(993      data, sizeof(data), sample_range, unwind_plan));994 995  row = unwind_plan.GetRowForFunctionOffset(1);996 997  EXPECT_EQ(1, row->GetOffset());998  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);999  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1000  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1001 1002  EXPECT_TRUE(row->GetRegisterInfo(k_rbp, regloc));1003  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1004  EXPECT_EQ(-8, regloc.GetOffset());1005}1006 1007TEST_F(Testx86AssemblyInspectionEngine, TestPushImm) {1008  UnwindPlan::Row::AbstractRegisterLocation regloc;1009  const UnwindPlan::Row *row;1010 1011  uint8_t data[] = {1012      0x68, 0xff, 0xff, 0x01, 0x69, // pushq $0x6901ffff1013      0x6a, 0x7d,                   // pushl $0x7d1014      0x90                          // nop1015  };1016 1017  AddressRange sample_range(0x1000, sizeof(data));1018  UnwindPlan unwind_plan(eRegisterKindLLDB);1019 1020  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1021  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1022      data, sizeof(data), sample_range, unwind_plan));1023 1024  row = unwind_plan.GetRowForFunctionOffset(5);1025  EXPECT_EQ(5, row->GetOffset());1026  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1027  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1028  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1029 1030  row = unwind_plan.GetRowForFunctionOffset(7);1031  EXPECT_EQ(7, row->GetOffset());1032  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1033  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1034  EXPECT_EQ(24, row->GetCFAValue().GetOffset());1035 1036  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1037  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1038      data, sizeof(data), sample_range, unwind_plan));1039 1040  row = unwind_plan.GetRowForFunctionOffset(5);1041  EXPECT_EQ(5, row->GetOffset());1042  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1043  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1044  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1045 1046  row = unwind_plan.GetRowForFunctionOffset(7);1047  EXPECT_EQ(7, row->GetOffset());1048  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1049  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1050  EXPECT_EQ(12, row->GetCFAValue().GetOffset());1051}1052 1053// We treat 'pushq $0' / 'pushl $0' specially - this shows up1054// in the first function called in a new thread and it needs to1055// put a 0 as the saved pc.  We pretend it didn't change the CFA.1056TEST_F(Testx86AssemblyInspectionEngine, TestPush0) {1057  UnwindPlan::Row::AbstractRegisterLocation regloc;1058  const UnwindPlan::Row *row;1059 1060  uint8_t data[] = {1061      0x6a, 0x00, // pushq $01062      0x90        // nop1063  };1064 1065  AddressRange sample_range(0x1000, sizeof(data));1066  UnwindPlan unwind_plan(eRegisterKindLLDB);1067 1068  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1069  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1070      data, sizeof(data), sample_range, unwind_plan));1071 1072  row = unwind_plan.GetRowForFunctionOffset(2);1073 1074  // We're verifying that no row was created for the 'pushq $0'1075  EXPECT_EQ(0, row->GetOffset());1076 1077  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1078  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1079      data, sizeof(data), sample_range, unwind_plan));1080 1081  row = unwind_plan.GetRowForFunctionOffset(2);1082 1083  // We're verifying that no row was created for the 'pushq $0'1084  EXPECT_EQ(0, row->GetOffset());1085}1086 1087TEST_F(Testx86AssemblyInspectionEngine, TestPushExtended) {1088  UnwindPlan::Row::AbstractRegisterLocation regloc;1089  const UnwindPlan::Row *row;1090 1091  uint8_t data[] = {1092      0xff, 0x74, 0x24, 0x20,             // pushl 0x20(%esp)1093      0xff, 0xb6, 0xce, 0x01, 0xf0, 0x00, // pushl  0xf001ce(%esi)1094      0xff, 0x30,                         // pushl  (%eax)1095      0x90                                // nop1096  };1097 1098  AddressRange sample_range(0x1000, sizeof(data));1099  UnwindPlan unwind_plan(eRegisterKindLLDB);1100 1101  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1102  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1103      data, sizeof(data), sample_range, unwind_plan));1104 1105  row = unwind_plan.GetRowForFunctionOffset(4);1106 1107  EXPECT_EQ(4, row->GetOffset());1108  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1109  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1110  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1111 1112  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1113  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1114      data, sizeof(data), sample_range, unwind_plan));1115 1116  row = unwind_plan.GetRowForFunctionOffset(4);1117  EXPECT_EQ(4, row->GetOffset());1118  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1119  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1120  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1121 1122  row = unwind_plan.GetRowForFunctionOffset(10);1123  EXPECT_EQ(10, row->GetOffset());1124  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1125  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1126  EXPECT_EQ(12, row->GetCFAValue().GetOffset());1127 1128  row = unwind_plan.GetRowForFunctionOffset(12);1129  EXPECT_EQ(12, row->GetOffset());1130  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1131  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1132  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1133}1134 1135TEST_F(Testx86AssemblyInspectionEngine, TestPushR15) {1136  UnwindPlan::Row::AbstractRegisterLocation regloc;1137  const UnwindPlan::Row *row;1138 1139  uint8_t data[] = {1140      0x41, 0x57, // pushq %r151141      0x90        // nop1142  };1143 1144  AddressRange sample_range(0x1000, sizeof(data));1145  UnwindPlan unwind_plan(eRegisterKindLLDB);1146 1147  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1148  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1149      data, sizeof(data), sample_range, unwind_plan));1150 1151  row = unwind_plan.GetRowForFunctionOffset(2);1152 1153  EXPECT_EQ(2, row->GetOffset());1154  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1155  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1156  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1157 1158  EXPECT_TRUE(row->GetRegisterInfo(k_r15, regloc));1159  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1160  EXPECT_EQ(-16, regloc.GetOffset());1161}1162 1163TEST_F(Testx86AssemblyInspectionEngine, TestPushR14) {1164  UnwindPlan::Row::AbstractRegisterLocation regloc;1165  const UnwindPlan::Row *row;1166 1167  uint8_t data[] = {1168      0x41, 0x56, // pushq %r141169      0x90        // nop1170  };1171 1172  AddressRange sample_range(0x1000, sizeof(data));1173  UnwindPlan unwind_plan(eRegisterKindLLDB);1174 1175  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1176  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1177      data, sizeof(data), sample_range, unwind_plan));1178 1179  row = unwind_plan.GetRowForFunctionOffset(2);1180 1181  EXPECT_EQ(2, row->GetOffset());1182  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1183  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1184  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1185 1186  EXPECT_TRUE(row->GetRegisterInfo(k_r14, regloc));1187  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1188  EXPECT_EQ(-16, regloc.GetOffset());1189}1190 1191TEST_F(Testx86AssemblyInspectionEngine, TestPushR13) {1192  UnwindPlan::Row::AbstractRegisterLocation regloc;1193  const UnwindPlan::Row *row;1194 1195  uint8_t data[] = {1196      0x41, 0x55, // pushq %r131197      0x90        // nop1198  };1199 1200  AddressRange sample_range(0x1000, sizeof(data));1201  UnwindPlan unwind_plan(eRegisterKindLLDB);1202 1203  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1204  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1205      data, sizeof(data), sample_range, unwind_plan));1206 1207  row = unwind_plan.GetRowForFunctionOffset(2);1208 1209  EXPECT_EQ(2, row->GetOffset());1210  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1211  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1212  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1213 1214  EXPECT_TRUE(row->GetRegisterInfo(k_r13, regloc));1215  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1216  EXPECT_EQ(-16, regloc.GetOffset());1217}1218 1219TEST_F(Testx86AssemblyInspectionEngine, TestPushR12) {1220  UnwindPlan::Row::AbstractRegisterLocation regloc;1221  const UnwindPlan::Row *row;1222 1223  uint8_t data[] = {1224      0x41, 0x54, // pushq %r131225      0x90        // nop1226  };1227 1228  AddressRange sample_range(0x1000, sizeof(data));1229  UnwindPlan unwind_plan(eRegisterKindLLDB);1230 1231  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1232  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1233      data, sizeof(data), sample_range, unwind_plan));1234 1235  row = unwind_plan.GetRowForFunctionOffset(2);1236 1237  EXPECT_EQ(2, row->GetOffset());1238  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1239  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1240  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1241 1242  EXPECT_TRUE(row->GetRegisterInfo(k_r12, regloc));1243  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1244  EXPECT_EQ(-16, regloc.GetOffset());1245}1246 1247TEST_F(Testx86AssemblyInspectionEngine, TestPushRBX) {1248  UnwindPlan::Row::AbstractRegisterLocation regloc;1249  const UnwindPlan::Row *row;1250 1251  uint8_t data[] = {1252      0x53, // pushq %rbx1253      0x90  // nop1254  };1255 1256  AddressRange sample_range(0x1000, sizeof(data));1257  UnwindPlan unwind_plan(eRegisterKindLLDB);1258 1259  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1260  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1261      data, sizeof(data), sample_range, unwind_plan));1262 1263  row = unwind_plan.GetRowForFunctionOffset(1);1264 1265  EXPECT_EQ(1, row->GetOffset());1266  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1267  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1268  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1269 1270  EXPECT_TRUE(row->GetRegisterInfo(k_rbx, regloc));1271  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1272  EXPECT_EQ(-16, regloc.GetOffset());1273}1274 1275// The ABI is hardcoded in x86AssemblyInspectionEngine such that1276// eax, ecx, edx are all considered volatile and push/pops of them are1277// not tracked (except to keep track of stack pointer movement)1278TEST_F(Testx86AssemblyInspectionEngine, TestPushEAX) {1279  UnwindPlan::Row::AbstractRegisterLocation regloc;1280  const UnwindPlan::Row *row;1281  AddressRange sample_range;1282  UnwindPlan unwind_plan(eRegisterKindLLDB);1283  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1284 1285  uint8_t data[] = {1286      0x50, // pushl %eax1287      0x90  // nop1288  };1289 1290  sample_range = AddressRange(0x1000, sizeof(data));1291 1292  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1293      data, sizeof(data), sample_range, unwind_plan));1294 1295  row = unwind_plan.GetRowForFunctionOffset(1);1296  EXPECT_EQ(1, row->GetOffset());1297  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1298  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1299  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1300 1301  EXPECT_FALSE(row->GetRegisterInfo(k_eax, regloc));1302}1303 1304// The ABI is hardcoded in x86AssemblyInspectionEngine such that1305// eax, ecx, edx are all considered volatile and push/pops of them are1306// not tracked (except to keep track of stack pointer movement)1307TEST_F(Testx86AssemblyInspectionEngine, TestPushECX) {1308  UnwindPlan::Row::AbstractRegisterLocation regloc;1309  const UnwindPlan::Row *row;1310  AddressRange sample_range;1311  UnwindPlan unwind_plan(eRegisterKindLLDB);1312  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1313 1314  uint8_t data[] = {1315      0x51, // pushl %ecx1316      0x90  // nop1317  };1318 1319  sample_range = AddressRange(0x1000, sizeof(data));1320 1321  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1322      data, sizeof(data), sample_range, unwind_plan));1323 1324  row = unwind_plan.GetRowForFunctionOffset(1);1325  EXPECT_EQ(1, row->GetOffset());1326  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1327  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1328  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1329 1330  EXPECT_FALSE(row->GetRegisterInfo(k_ecx, regloc));1331}1332 1333// The ABI is hardcoded in x86AssemblyInspectionEngine such that1334// eax, ecx, edx are all considered volatile and push/pops of them are1335// not tracked (except to keep track of stack pointer movement)1336TEST_F(Testx86AssemblyInspectionEngine, TestPushEDX) {1337  UnwindPlan::Row::AbstractRegisterLocation regloc;1338  const UnwindPlan::Row *row;1339  AddressRange sample_range;1340  UnwindPlan unwind_plan(eRegisterKindLLDB);1341  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1342 1343  uint8_t data[] = {1344      0x52, // pushl %edx1345      0x90  // nop1346  };1347 1348  sample_range = AddressRange(0x1000, sizeof(data));1349 1350  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1351      data, sizeof(data), sample_range, unwind_plan));1352 1353  row = unwind_plan.GetRowForFunctionOffset(1);1354  EXPECT_EQ(1, row->GetOffset());1355  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1356  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1357  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1358 1359  EXPECT_FALSE(row->GetRegisterInfo(k_edx, regloc));1360}1361 1362TEST_F(Testx86AssemblyInspectionEngine, TestPushEBX) {1363  UnwindPlan::Row::AbstractRegisterLocation regloc;1364  const UnwindPlan::Row *row;1365  AddressRange sample_range;1366  UnwindPlan unwind_plan(eRegisterKindLLDB);1367  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1368 1369  uint8_t data[] = {1370      0x53, // pushl %ebx1371      0x90  // nop1372  };1373 1374  sample_range = AddressRange(0x1000, sizeof(data));1375 1376  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1377      data, sizeof(data), sample_range, unwind_plan));1378 1379  row = unwind_plan.GetRowForFunctionOffset(1);1380  EXPECT_EQ(1, row->GetOffset());1381  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1382  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1383  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1384 1385  EXPECT_TRUE(row->GetRegisterInfo(k_ebx, regloc));1386  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1387  EXPECT_EQ(-8, regloc.GetOffset());1388}1389 1390TEST_F(Testx86AssemblyInspectionEngine, TestPushEBP) {1391  UnwindPlan::Row::AbstractRegisterLocation regloc;1392  const UnwindPlan::Row *row;1393  AddressRange sample_range;1394  UnwindPlan unwind_plan(eRegisterKindLLDB);1395  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1396 1397  uint8_t data[] = {1398      0x55, // pushl %ebp1399      0x90  // nop1400  };1401 1402  sample_range = AddressRange(0x1000, sizeof(data));1403 1404  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1405      data, sizeof(data), sample_range, unwind_plan));1406 1407  row = unwind_plan.GetRowForFunctionOffset(1);1408  EXPECT_EQ(1, row->GetOffset());1409  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1410  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1411  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1412 1413  EXPECT_TRUE(row->GetRegisterInfo(k_ebp, regloc));1414  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1415  EXPECT_EQ(-8, regloc.GetOffset());1416}1417 1418TEST_F(Testx86AssemblyInspectionEngine, TestPushRBPWithREX) {1419  UnwindPlan::Row::AbstractRegisterLocation regloc;1420  const UnwindPlan::Row *row;1421 1422  uint8_t data[] = {1423      0x40, 0x55, // pushq %rbp1424      0x90  // nop1425  };1426 1427  AddressRange sample_range(0x1000, sizeof(data));1428  UnwindPlan unwind_plan(eRegisterKindLLDB);1429 1430  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1431  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1432      data, sizeof(data), sample_range, unwind_plan));1433 1434  row = unwind_plan.GetRowForFunctionOffset(2);1435 1436  EXPECT_EQ(2, row->GetOffset());1437  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1438  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1439  EXPECT_EQ(16, row->GetCFAValue().GetOffset());1440 1441  EXPECT_TRUE(row->GetRegisterInfo(k_rbp, regloc));1442  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1443  EXPECT_EQ(-16, regloc.GetOffset());1444}1445 1446TEST_F(Testx86AssemblyInspectionEngine, TestPushESI) {1447  UnwindPlan::Row::AbstractRegisterLocation regloc;1448  const UnwindPlan::Row *row;1449  AddressRange sample_range;1450  UnwindPlan unwind_plan(eRegisterKindLLDB);1451  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1452 1453  uint8_t data[] = {1454      0x56, // pushl %esi1455      0x90  // nop1456  };1457 1458  sample_range = AddressRange(0x1000, sizeof(data));1459 1460  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1461      data, sizeof(data), sample_range, unwind_plan));1462 1463  row = unwind_plan.GetRowForFunctionOffset(1);1464  EXPECT_EQ(1, row->GetOffset());1465  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1466  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1467  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1468 1469  EXPECT_TRUE(row->GetRegisterInfo(k_esi, regloc));1470  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1471  EXPECT_EQ(-8, regloc.GetOffset());1472}1473 1474TEST_F(Testx86AssemblyInspectionEngine, TestPushEDI) {1475  UnwindPlan::Row::AbstractRegisterLocation regloc;1476  const UnwindPlan::Row *row;1477  AddressRange sample_range;1478  UnwindPlan unwind_plan(eRegisterKindLLDB);1479  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1480 1481  uint8_t data[] = {1482      0x57, // pushl %edi1483      0x90  // nop1484  };1485 1486  sample_range = AddressRange(0x1000, sizeof(data));1487 1488  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1489      data, sizeof(data), sample_range, unwind_plan));1490 1491  row = unwind_plan.GetRowForFunctionOffset(1);1492  EXPECT_EQ(1, row->GetOffset());1493  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);1494  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1495  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1496 1497  EXPECT_TRUE(row->GetRegisterInfo(k_edi, regloc));1498  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());1499  EXPECT_EQ(-8, regloc.GetOffset());1500}1501 1502TEST_F(Testx86AssemblyInspectionEngine, TestMovRSPtoRBP) {1503  UnwindPlan::Row::AbstractRegisterLocation regloc;1504  const UnwindPlan::Row *row;1505 1506  uint8_t data64_1[] = {1507      0x48, 0x8b, 0xec, // movq %rsp, %rbp1508      0x90              // nop1509  };1510 1511  AddressRange sample_range(0x1000, sizeof(data64_1));1512  UnwindPlan unwind_plan(eRegisterKindLLDB);1513 1514  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1515  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1516      data64_1, sizeof(data64_1), sample_range, unwind_plan));1517 1518  row = unwind_plan.GetRowForFunctionOffset(3);1519 1520  EXPECT_EQ(3, row->GetOffset());1521  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);1522  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1523  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1524 1525  uint8_t data64_2[] = {1526      0x48, 0x89, 0xe5, // movq %rsp, %rbp1527      0x90              // nop1528  };1529 1530  sample_range = AddressRange(0x1000, sizeof(data64_2));1531  unwind_plan.Clear();1532  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1533      data64_2, sizeof(data64_2), sample_range, unwind_plan));1534 1535  row = unwind_plan.GetRowForFunctionOffset(3);1536  EXPECT_EQ(3, row->GetOffset());1537  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);1538  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1539  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1540 1541  uint8_t data32_1[] = {1542      0x8b, 0xec, // movl %rsp, %rbp1543      0x90        // nop1544  };1545 1546  sample_range = AddressRange(0x1000, sizeof(data32_1));1547  unwind_plan.Clear();1548  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1549      data32_1, sizeof(data32_1), sample_range, unwind_plan));1550 1551  row = unwind_plan.GetRowForFunctionOffset(2);1552  EXPECT_EQ(2, row->GetOffset());1553  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_ebp);1554  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1555  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1556 1557  uint8_t data32_2[] = {1558      0x89, 0xe5, // movl %rsp, %rbp1559      0x90        // nop1560  };1561 1562  sample_range = AddressRange(0x1000, sizeof(data32_2));1563  unwind_plan.Clear();1564  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1565      data32_2, sizeof(data32_2), sample_range, unwind_plan));1566 1567  row = unwind_plan.GetRowForFunctionOffset(2);1568  EXPECT_EQ(2, row->GetOffset());1569  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_ebp);1570  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1571  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1572}1573 1574TEST_F(Testx86AssemblyInspectionEngine, TestSubRSP) {1575  UnwindPlan::Row::AbstractRegisterLocation regloc;1576  const UnwindPlan::Row *row;1577  AddressRange sample_range;1578  UnwindPlan unwind_plan(eRegisterKindLLDB);1579  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1580 1581  uint8_t data1[] = {1582      0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $0x100, $rsp1583      0x90                                      // nop1584  };1585 1586  sample_range = AddressRange(0x1000, sizeof(data1));1587 1588  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1589      data1, sizeof(data1), sample_range, unwind_plan));1590 1591  row = unwind_plan.GetRowForFunctionOffset(7);1592  EXPECT_EQ(7, row->GetOffset());1593  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1594  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1595  EXPECT_EQ(264, row->GetCFAValue().GetOffset());1596 1597  uint8_t data2[] = {1598      0x48, 0x83, 0xec, 0x10, // subq $0x10, %rsp1599      0x90                    // nop1600  };1601 1602  sample_range = AddressRange(0x1000, sizeof(data2));1603 1604  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1605      data2, sizeof(data2), sample_range, unwind_plan));1606 1607  row = unwind_plan.GetRowForFunctionOffset(4);1608  EXPECT_EQ(4, row->GetOffset());1609  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1610  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1611  EXPECT_EQ(24, row->GetCFAValue().GetOffset());1612}1613 1614TEST_F(Testx86AssemblyInspectionEngine, TestSubESP) {1615  UnwindPlan::Row::AbstractRegisterLocation regloc;1616  const UnwindPlan::Row *row;1617  AddressRange sample_range;1618  UnwindPlan unwind_plan(eRegisterKindLLDB);1619  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1620 1621  uint8_t data1[] = {1622      0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subl $0x100, %esp1623      0x90                                // nop1624  };1625 1626  sample_range = AddressRange(0x1000, sizeof(data1));1627 1628  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1629      data1, sizeof(data1), sample_range, unwind_plan));1630 1631  row = unwind_plan.GetRowForFunctionOffset(6);1632  EXPECT_EQ(6, row->GetOffset());1633  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1634  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1635  EXPECT_EQ(260, row->GetCFAValue().GetOffset());1636 1637  uint8_t data2[] = {1638      0x83, 0xec, 0x10, // subq $0x10, %esp1639      0x90              // nop1640  };1641 1642  sample_range = AddressRange(0x1000, sizeof(data2));1643 1644  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1645      data2, sizeof(data2), sample_range, unwind_plan));1646 1647  row = unwind_plan.GetRowForFunctionOffset(3);1648  EXPECT_EQ(3, row->GetOffset());1649  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1650  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1651  EXPECT_EQ(20, row->GetCFAValue().GetOffset());1652}1653 1654TEST_F(Testx86AssemblyInspectionEngine, TestAddRSP) {1655  UnwindPlan::Row::AbstractRegisterLocation regloc;1656  const UnwindPlan::Row *row;1657  AddressRange sample_range;1658  UnwindPlan unwind_plan(eRegisterKindLLDB);1659  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();1660 1661  uint8_t data1[] = {1662      0x48, 0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addq $0x100, %rsp1663      0x90                                      // nop1664  };1665 1666  sample_range = AddressRange(0x1000, sizeof(data1));1667 1668  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1669      data1, sizeof(data1), sample_range, unwind_plan));1670 1671  row = unwind_plan.GetRowForFunctionOffset(7);1672  EXPECT_EQ(7, row->GetOffset());1673  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1674  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1675  EXPECT_EQ(8 - 256, row->GetCFAValue().GetOffset());1676 1677  uint8_t data2[] = {1678      0x48, 0x83, 0xc4, 0x10, // addq $0x10, %rsp1679      0x90                    // nop1680  };1681 1682  sample_range = AddressRange(0x1000, sizeof(data2));1683 1684  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(1685      data2, sizeof(data2), sample_range, unwind_plan));1686 1687  row = unwind_plan.GetRowForFunctionOffset(4);1688  EXPECT_EQ(4, row->GetOffset());1689  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1690  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1691  EXPECT_EQ(8 - 16, row->GetCFAValue().GetOffset());1692}1693 1694TEST_F(Testx86AssemblyInspectionEngine, TestAddESP) {1695  UnwindPlan::Row::AbstractRegisterLocation regloc;1696  const UnwindPlan::Row *row;1697  AddressRange sample_range;1698  UnwindPlan unwind_plan(eRegisterKindLLDB);1699  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();1700 1701  uint8_t data1[] = {1702      0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addl $0x100, %esp1703      0x90                                // nop1704  };1705 1706  sample_range = AddressRange(0x1000, sizeof(data1));1707 1708  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1709      data1, sizeof(data1), sample_range, unwind_plan));1710 1711  row = unwind_plan.GetRowForFunctionOffset(6);1712  EXPECT_EQ(6, row->GetOffset());1713  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1714  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1715  EXPECT_EQ(4 - 256, row->GetCFAValue().GetOffset());1716 1717  uint8_t data2[] = {1718      0x83, 0xc4, 0x10, // addq $0x10, %esp1719      0x90              // nop1720  };1721 1722  sample_range = AddressRange(0x1000, sizeof(data2));1723 1724  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(1725      data2, sizeof(data2), sample_range, unwind_plan));1726 1727  row = unwind_plan.GetRowForFunctionOffset(3);1728  EXPECT_EQ(3, row->GetOffset());1729  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1730  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1731  EXPECT_EQ(4 - 16, row->GetCFAValue().GetOffset());1732}1733 1734TEST_F(Testx86AssemblyInspectionEngine, TestLEA_RSP_Pattern) {1735  UnwindPlan::Row::AbstractRegisterLocation regloc;1736  const UnwindPlan::Row *row;1737  AddressRange sample_range;1738  UnwindPlan unwind_plan(eRegisterKindLLDB);1739  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1740 1741  uint8_t data[] = {1742      0x8d, 0x64, 0x24, 0x10, // lea rsp, [rsp + 0x10]1743      0x90                    // nop1744  };1745 1746  sample_range = AddressRange(0x1000, sizeof(data));1747 1748  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1749      data, sizeof(data), sample_range, unwind_plan));1750 1751  row = unwind_plan.GetRowForFunctionOffset(0);1752  EXPECT_EQ(0, row->GetOffset());1753  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1754  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1755  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1756}1757 1758TEST_F(Testx86AssemblyInspectionEngine, TestPopRBX) {1759  UnwindPlan::Row::AbstractRegisterLocation regloc;1760  const UnwindPlan::Row *row;1761  AddressRange sample_range;1762  UnwindPlan unwind_plan(eRegisterKindLLDB);1763  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1764 1765  uint8_t data[] = {1766      0x53, // pushq %rbx1767      0x5b, // popq %rbx1768      0x90  // nop1769  };1770 1771  sample_range = AddressRange(0x1000, sizeof(data));1772 1773  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1774      data, sizeof(data), sample_range, unwind_plan));1775 1776  row = unwind_plan.GetRowForFunctionOffset(2);1777  EXPECT_EQ(2, row->GetOffset());1778  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1779  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1780  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1781  EXPECT_FALSE(row->GetRegisterInfo(k_rbx, regloc));1782}1783 1784TEST_F(Testx86AssemblyInspectionEngine, TestPopRBP) {1785  UnwindPlan::Row::AbstractRegisterLocation regloc;1786  const UnwindPlan::Row *row;1787  AddressRange sample_range;1788  UnwindPlan unwind_plan(eRegisterKindLLDB);1789  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1790 1791  uint8_t data[] = {1792      0x55, // pushq %rbp1793      0x5d, // popq %rbp1794      0x90  // nop1795  };1796 1797  sample_range = AddressRange(0x1000, sizeof(data));1798 1799  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1800      data, sizeof(data), sample_range, unwind_plan));1801 1802  row = unwind_plan.GetRowForFunctionOffset(2);1803  EXPECT_EQ(2, row->GetOffset());1804  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1805  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1806  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1807  EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));1808}1809 1810TEST_F(Testx86AssemblyInspectionEngine, TestPopR12) {1811  UnwindPlan::Row::AbstractRegisterLocation regloc;1812  const UnwindPlan::Row *row;1813  AddressRange sample_range;1814  UnwindPlan unwind_plan(eRegisterKindLLDB);1815  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1816 1817  uint8_t data[] = {1818      0x41, 0x54, // pushq %r121819      0x41, 0x5c, // popq %r121820      0x90        // nop1821  };1822 1823  sample_range = AddressRange(0x1000, sizeof(data));1824 1825  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1826      data, sizeof(data), sample_range, unwind_plan));1827 1828  row = unwind_plan.GetRowForFunctionOffset(4);1829  EXPECT_EQ(4, row->GetOffset());1830  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1831  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1832  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1833  EXPECT_FALSE(row->GetRegisterInfo(k_r12, regloc));1834}1835 1836TEST_F(Testx86AssemblyInspectionEngine, TestPopR13) {1837  UnwindPlan::Row::AbstractRegisterLocation regloc;1838  const UnwindPlan::Row *row;1839  AddressRange sample_range;1840  UnwindPlan unwind_plan(eRegisterKindLLDB);1841  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1842 1843  uint8_t data[] = {1844      0x41, 0x55, // pushq %r131845      0x41, 0x5d, // popq %r131846      0x90        // nop1847  };1848 1849  sample_range = AddressRange(0x1000, sizeof(data));1850 1851  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1852      data, sizeof(data), sample_range, unwind_plan));1853 1854  row = unwind_plan.GetRowForFunctionOffset(4);1855  EXPECT_EQ(4, row->GetOffset());1856  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1857  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1858  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1859  EXPECT_FALSE(row->GetRegisterInfo(k_r13, regloc));1860}1861 1862TEST_F(Testx86AssemblyInspectionEngine, TestPopR14) {1863  UnwindPlan::Row::AbstractRegisterLocation regloc;1864  const UnwindPlan::Row *row;1865  AddressRange sample_range;1866  UnwindPlan unwind_plan(eRegisterKindLLDB);1867  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1868 1869  uint8_t data[] = {1870      0x41, 0x56, // pushq %r141871      0x41, 0x5e, // popq %r141872      0x90        // nop1873  };1874 1875  sample_range = AddressRange(0x1000, sizeof(data));1876 1877  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1878      data, sizeof(data), sample_range, unwind_plan));1879 1880  row = unwind_plan.GetRowForFunctionOffset(4);1881  EXPECT_EQ(4, row->GetOffset());1882  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1883  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1884  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1885  EXPECT_FALSE(row->GetRegisterInfo(k_r14, regloc));1886}1887 1888TEST_F(Testx86AssemblyInspectionEngine, TestPopR15) {1889  UnwindPlan::Row::AbstractRegisterLocation regloc;1890  const UnwindPlan::Row *row;1891  AddressRange sample_range;1892  UnwindPlan unwind_plan(eRegisterKindLLDB);1893  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1894 1895  uint8_t data[] = {1896      0x41, 0x57, // pushq %r151897      0x41, 0x5f, // popq %r151898      0x90        // nop1899  };1900 1901  sample_range = AddressRange(0x1000, sizeof(data));1902 1903  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1904      data, sizeof(data), sample_range, unwind_plan));1905 1906  row = unwind_plan.GetRowForFunctionOffset(4);1907  EXPECT_EQ(4, row->GetOffset());1908  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1909  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1910  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1911  EXPECT_FALSE(row->GetRegisterInfo(k_r15, regloc));1912}1913 1914TEST_F(Testx86AssemblyInspectionEngine, TestPopEBX) {1915  UnwindPlan::Row::AbstractRegisterLocation regloc;1916  const UnwindPlan::Row *row;1917  AddressRange sample_range;1918  UnwindPlan unwind_plan(eRegisterKindLLDB);1919  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();1920 1921  uint8_t data[] = {1922      0x53, // pushl %ebx1923      0x5b, // popl %ebx1924      0x90  // nop1925  };1926 1927  sample_range = AddressRange(0x1000, sizeof(data));1928 1929  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1930      data, sizeof(data), sample_range, unwind_plan));1931 1932  row = unwind_plan.GetRowForFunctionOffset(2);1933  EXPECT_EQ(2, row->GetOffset());1934  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1935  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1936  EXPECT_EQ(4, row->GetCFAValue().GetOffset());1937  EXPECT_FALSE(row->GetRegisterInfo(k_ebx, regloc));1938}1939 1940TEST_F(Testx86AssemblyInspectionEngine, TestPopEBP) {1941  UnwindPlan::Row::AbstractRegisterLocation regloc;1942  const UnwindPlan::Row *row;1943  AddressRange sample_range;1944  UnwindPlan unwind_plan(eRegisterKindLLDB);1945  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();1946 1947  uint8_t data[] = {1948      0x55, // pushl %ebp1949      0x5d, // popl %ebp1950      0x90  // nop1951  };1952 1953  sample_range = AddressRange(0x1000, sizeof(data));1954 1955  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1956      data, sizeof(data), sample_range, unwind_plan));1957 1958  row = unwind_plan.GetRowForFunctionOffset(2);1959  EXPECT_EQ(2, row->GetOffset());1960  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1961  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1962  EXPECT_EQ(4, row->GetCFAValue().GetOffset());1963  EXPECT_FALSE(row->GetRegisterInfo(k_ebp, regloc));1964}1965 1966TEST_F(Testx86AssemblyInspectionEngine, TestPopRBPWithREX) {1967  UnwindPlan::Row::AbstractRegisterLocation regloc;1968  const UnwindPlan::Row *row;1969  AddressRange sample_range;1970  UnwindPlan unwind_plan(eRegisterKindLLDB);1971  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();1972 1973  uint8_t data[] = {1974      0x40, 0x55, // pushq %rbp1975      0x40, 0x5d, // popq %rbp1976      0x90        // nop1977  };1978 1979  sample_range = AddressRange(0x1000, sizeof(data));1980 1981  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(1982      data, sizeof(data), sample_range, unwind_plan));1983 1984  row = unwind_plan.GetRowForFunctionOffset(4);1985  EXPECT_EQ(4, row->GetOffset());1986  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);1987  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);1988  EXPECT_EQ(8, row->GetCFAValue().GetOffset());1989  EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));1990}1991 1992TEST_F(Testx86AssemblyInspectionEngine, TestPopESI) {1993  UnwindPlan::Row::AbstractRegisterLocation regloc;1994  const UnwindPlan::Row *row;1995  AddressRange sample_range;1996  UnwindPlan unwind_plan(eRegisterKindLLDB);1997  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();1998 1999  uint8_t data[] = {2000      0x56, // pushl %esi2001      0x5e, // popl %esi2002      0x90  // nop2003  };2004 2005  sample_range = AddressRange(0x1000, sizeof(data));2006 2007  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(2008      data, sizeof(data), sample_range, unwind_plan));2009 2010  row = unwind_plan.GetRowForFunctionOffset(2);2011  EXPECT_EQ(2, row->GetOffset());2012  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2013  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2014  EXPECT_EQ(4, row->GetCFAValue().GetOffset());2015  EXPECT_FALSE(row->GetRegisterInfo(k_esi, regloc));2016}2017 2018TEST_F(Testx86AssemblyInspectionEngine, TestPopEDI) {2019  UnwindPlan::Row::AbstractRegisterLocation regloc;2020  const UnwindPlan::Row *row;2021  AddressRange sample_range;2022  UnwindPlan unwind_plan(eRegisterKindLLDB);2023  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();2024 2025  uint8_t data[] = {2026      0x57, // pushl %edi2027      0x5f, // popl %edi2028      0x90  // nop2029  };2030 2031  sample_range = AddressRange(0x1000, sizeof(data));2032 2033  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(2034      data, sizeof(data), sample_range, unwind_plan));2035 2036  row = unwind_plan.GetRowForFunctionOffset(2);2037  EXPECT_EQ(2, row->GetOffset());2038  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2039  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2040  EXPECT_EQ(4, row->GetCFAValue().GetOffset());2041  EXPECT_FALSE(row->GetRegisterInfo(k_edi, regloc));2042}2043 2044// We don't track these registers, but make sure the CFA address is updated2045// if we're defining the CFA in term of esp.2046TEST_F(Testx86AssemblyInspectionEngine, Testi386IgnoredRegisters) {2047  UnwindPlan::Row::AbstractRegisterLocation regloc;2048  const UnwindPlan::Row *row;2049  AddressRange sample_range;2050  UnwindPlan unwind_plan(eRegisterKindLLDB);2051  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();2052 2053  uint8_t data[] = {2054      0x0e, // push cs2055      0x16, // push ss2056      0x1e, // push ds2057      0x06, // push es2058 2059      0x07, // pop es2060      0x1f, // pop ds2061      0x17, // pop ss2062 2063      0x90 // nop2064  };2065 2066  sample_range = AddressRange(0x1000, sizeof(data));2067 2068  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(2069      data, sizeof(data), sample_range, unwind_plan));2070 2071  row = unwind_plan.GetRowForFunctionOffset(4);2072  EXPECT_EQ(4, row->GetOffset());2073  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2074  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2075  EXPECT_EQ(20, row->GetCFAValue().GetOffset());2076 2077  row = unwind_plan.GetRowForFunctionOffset(7);2078  EXPECT_EQ(7, row->GetOffset());2079  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2080  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2081  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2082}2083 2084TEST_F(Testx86AssemblyInspectionEngine, TestLEAVE) {2085  UnwindPlan::Row::AbstractRegisterLocation regloc;2086  const UnwindPlan::Row *row;2087  AddressRange sample_range;2088  UnwindPlan unwind_plan(eRegisterKindLLDB);2089  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2090  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2091 2092  uint8_t data[] = {2093      0x55, // push %rbp/ebp2094      0xc9, // leave2095      0x90  // nop2096  };2097 2098  sample_range = AddressRange(0x1000, sizeof(data));2099 2100  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(2101      data, sizeof(data), sample_range, unwind_plan));2102 2103  row = unwind_plan.GetRowForFunctionOffset(2);2104  EXPECT_EQ(2, row->GetOffset());2105  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2106  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2107  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2108  EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));2109 2110  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(2111      data, sizeof(data), sample_range, unwind_plan));2112 2113  row = unwind_plan.GetRowForFunctionOffset(2);2114  EXPECT_EQ(2, row->GetOffset());2115  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2116  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2117  EXPECT_EQ(4, row->GetCFAValue().GetOffset());2118  EXPECT_FALSE(row->GetRegisterInfo(k_ebp, regloc));2119}2120 2121// In i386, which lacks pc-relative addressing, a common code sequence2122// is to call the next instruction (i.e. call imm32, value of 0) which2123// pushes the addr of the next insn on the stack, and then pop that value2124// into a register (the "pic base" register).2125TEST_F(Testx86AssemblyInspectionEngine, TestCALLNextInsn) {2126  UnwindPlan::Row::AbstractRegisterLocation regloc;2127  const UnwindPlan::Row *row;2128  AddressRange sample_range;2129  UnwindPlan unwind_plan(eRegisterKindLLDB);2130  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2131 2132  uint8_t data[] = {2133      0xe8, 0x00, 0x00, 0x00, 0x00, // call 02134      0x90                          // nop2135  };2136 2137  sample_range = AddressRange(0x1000, sizeof(data));2138 2139  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(2140      data, sizeof(data), sample_range, unwind_plan));2141 2142  row = unwind_plan.GetRowForFunctionOffset(5);2143  EXPECT_EQ(5, row->GetOffset());2144  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2145  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2146  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2147  EXPECT_FALSE(row->GetRegisterInfo(k_ebp, regloc));2148}2149 2150TEST_F(Testx86AssemblyInspectionEngine, TestSpillRegToStackViaMOVx86_64) {2151  UnwindPlan::Row::AbstractRegisterLocation regloc;2152  const UnwindPlan::Row *row;2153  AddressRange sample_range;2154  UnwindPlan unwind_plan(eRegisterKindLLDB);2155  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2156 2157  uint8_t data[] = {2158      0x55,                                     // pushq %rbp2159      0x48, 0x89, 0xe5,                         // movq %rsp, %rbp2160      0x4c, 0x89, 0x75, 0xc0,                   // movq   %r14, -0x40(%rbp)2161      0x4c, 0x89, 0xbd, 0x28, 0xfa, 0xff, 0xff, // movq   %r15, -0x5d8(%rbp)2162      0x48, 0x89, 0x5d, 0xb8,                   // movq %rbx, -0x48(%rbp)2163      0x90                                      // nop2164  };2165 2166  sample_range = AddressRange(0x1000, sizeof(data));2167 2168  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(2169      data, sizeof(data), sample_range, unwind_plan));2170 2171  row = unwind_plan.GetRowForFunctionOffset(19);2172  EXPECT_EQ(19, row->GetOffset());2173  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2174  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2175 2176  EXPECT_TRUE(row->GetRegisterInfo(k_r14, regloc));2177  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2178  EXPECT_EQ(-80, regloc.GetOffset());2179 2180  EXPECT_TRUE(row->GetRegisterInfo(k_r15, regloc));2181  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2182  EXPECT_EQ(-1512, regloc.GetOffset());2183 2184  EXPECT_TRUE(row->GetRegisterInfo(k_rbx, regloc));2185  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2186  EXPECT_EQ(-88, regloc.GetOffset());2187}2188 2189TEST_F(Testx86AssemblyInspectionEngine, TestSpillRegToStackViaMOVi386) {2190  UnwindPlan::Row::AbstractRegisterLocation regloc;2191  const UnwindPlan::Row *row;2192  AddressRange sample_range;2193  UnwindPlan unwind_plan(eRegisterKindLLDB);2194  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2195 2196  uint8_t data[] = {2197      0x55,                               // pushl %ebp2198      0x89, 0xe5,                         // movl %esp, %ebp2199      0x89, 0x9d, 0xb0, 0xfe, 0xff, 0xff, // movl %ebx, -0x150(%ebp)2200      0x89, 0x75, 0xe0,                   // movl %esi, -0x20(%ebp)2201      0x90                                // nop2202  };2203 2204  sample_range = AddressRange(0x1000, sizeof(data));2205 2206  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(2207      data, sizeof(data), sample_range, unwind_plan));2208 2209  row = unwind_plan.GetRowForFunctionOffset(12);2210  EXPECT_EQ(12, row->GetOffset());2211  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2212  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2213 2214  EXPECT_TRUE(row->GetRegisterInfo(k_ebx, regloc));2215  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2216  EXPECT_EQ(-344, regloc.GetOffset());2217 2218  EXPECT_TRUE(row->GetRegisterInfo(k_esi, regloc));2219  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2220  EXPECT_EQ(-40, regloc.GetOffset());2221}2222 2223TEST_F(Testx86AssemblyInspectionEngine, TestSpArithx86_64Augmented) {2224  UnwindPlan::Row::AbstractRegisterLocation regloc;2225  AddressRange sample_range;2226  UnwindPlan unwind_plan(eRegisterKindLLDB);2227  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2228 2229  uint8_t data[] = {2230      0x55,             // pushq %rbp2231      0x48, 0x89, 0xe5, // movq %rsp, %rbp2232 2233      // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite2234      // has a bug where it can't augment a function that is just2235      // prologue+epilogue - it needs at least one other instruction2236      // in between.2237 2238      0x90,                            // nop2239      0x48, 0x81, 0xec, 0x88, 0, 0, 0, // subq   $0x88, %rsp2240      0x90,                            // nop2241      0x48, 0x81, 0xc4, 0x88, 0, 0, 0, // addq   $0x88, %rsp2242 2243      0x5d, // popq %rbp2244      0xc3  // retq2245  };2246 2247  sample_range = AddressRange(0x1000, sizeof(data));2248 2249  unwind_plan.SetSourceName("unit testing hand-created unwind plan");2250  unwind_plan.SetPlanValidAddressRanges({sample_range});2251  unwind_plan.SetRegisterKind(eRegisterKindLLDB);2252 2253  {2254    UnwindPlan::Row row;2255 2256    // Describe offset 02257    row.SetOffset(0);2258    row.GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 8);2259    regloc.SetAtCFAPlusOffset(-8);2260    row.SetRegisterInfo(k_rip, regloc);2261    unwind_plan.AppendRow(row);2262 2263    // Describe offset 12264    row.SetOffset(1);2265    row.GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 16);2266    regloc.SetAtCFAPlusOffset(-16);2267    row.SetRegisterInfo(k_rbp, regloc);2268    unwind_plan.AppendRow(row);2269 2270    // Describe offset 42271    row.SetOffset(4);2272    row.GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 16);2273    unwind_plan.AppendRow(row);2274  }2275 2276  RegisterContextSP reg_ctx_sp;2277  EXPECT_TRUE(engine64->AugmentUnwindPlanFromCallSite(2278      data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp));2279 2280  // Before we touch the stack pointer, we should still refer to the2281  // row from after the prologue.2282  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(5);2283  EXPECT_EQ(4, row->GetOffset());2284 2285  // Check the first stack pointer update.2286  row = unwind_plan.GetRowForFunctionOffset(12);2287  EXPECT_EQ(12, row->GetOffset());2288  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2289  EXPECT_EQ(152, row->GetCFAValue().GetOffset());2290 2291  // After the nop, we should still refer to the same row.2292  row = unwind_plan.GetRowForFunctionOffset(13);2293  EXPECT_EQ(12, row->GetOffset());2294 2295  // Check that the second stack pointer update is reflected in the2296  // unwind plan.2297  row = unwind_plan.GetRowForFunctionOffset(20);2298  EXPECT_EQ(20, row->GetOffset());2299  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2300  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2301}2302 2303TEST_F(Testx86AssemblyInspectionEngine, TestSimplex86_64Augmented) {2304  UnwindPlan::Row::AbstractRegisterLocation regloc;2305  AddressRange sample_range;2306  UnwindPlan unwind_plan(eRegisterKindLLDB);2307  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2308 2309  uint8_t data[] = {2310      0x55,             // pushq %rbp2311      0x48, 0x89, 0xe5, // movq %rsp, %rbp2312 2313      // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite2314      // has a bug where it can't augment a function that is just2315      // prologue+epilogue - it needs at least one other instruction2316      // in between.2317      0x90, // nop2318 2319      0x5d, // popq %rbp2320      0xc3  // retq2321  };2322 2323  sample_range = AddressRange(0x1000, sizeof(data));2324 2325  unwind_plan.SetSourceName("unit testing hand-created unwind plan");2326  unwind_plan.SetPlanValidAddressRanges({sample_range});2327  unwind_plan.SetRegisterKind(eRegisterKindLLDB);2328 2329  {2330    UnwindPlan::Row row;2331 2332    // Describe offset 02333    row.SetOffset(0);2334    row.GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 8);2335    regloc.SetAtCFAPlusOffset(-8);2336    row.SetRegisterInfo(k_rip, regloc);2337    unwind_plan.AppendRow(row);2338 2339    // Describe offset 12340    row.SetOffset(1);2341    row.GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 16);2342    regloc.SetAtCFAPlusOffset(-16);2343    row.SetRegisterInfo(k_rbp, regloc);2344    unwind_plan.AppendRow(row);2345 2346    // Describe offset 42347    row.SetOffset(4);2348    row.GetCFAValue().SetIsRegisterPlusOffset(k_rbp, 16);2349    unwind_plan.AppendRow(row);2350  }2351 2352  RegisterContextSP reg_ctx_sp;2353  EXPECT_TRUE(engine64->AugmentUnwindPlanFromCallSite(2354      data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp));2355 2356  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(6);2357  EXPECT_EQ(6, row->GetOffset());2358  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2359  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2360 2361  // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite2362  // doesn't track register restores (pop'ing a reg value back from2363  // the stack) - it was just written to make stepping work correctly.2364  // Technically we should be able to do the following test, but it2365  // won't work today - the unwind plan will still say that the caller's2366  // rbp is on the stack.2367  // EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));2368}2369 2370TEST_F(Testx86AssemblyInspectionEngine, TestSimplei386ugmented) {2371  UnwindPlan::Row::AbstractRegisterLocation regloc;2372  AddressRange sample_range;2373  UnwindPlan unwind_plan(eRegisterKindLLDB);2374  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2375 2376  uint8_t data[] = {2377      0x55,       // pushl %ebp2378      0x89, 0xe5, // movl %esp, %ebp2379 2380      // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite2381      // has a bug where it can't augment a function that is just2382      // prologue+epilogue - it needs at least one other instruction2383      // in between.2384      0x90, // nop2385 2386      0x5d, // popl %ebp2387      0xc3  // retl2388  };2389 2390  sample_range = AddressRange(0x1000, sizeof(data));2391 2392  unwind_plan.SetSourceName("unit testing hand-created unwind plan");2393  unwind_plan.SetPlanValidAddressRanges({sample_range});2394  unwind_plan.SetRegisterKind(eRegisterKindLLDB);2395 2396  {2397    UnwindPlan::Row row;2398 2399    // Describe offset 02400    row.SetOffset(0);2401    row.GetCFAValue().SetIsRegisterPlusOffset(k_esp, 4);2402    regloc.SetAtCFAPlusOffset(-4);2403    row.SetRegisterInfo(k_eip, regloc);2404    unwind_plan.AppendRow(row);2405 2406    // Describe offset 12407    row.SetOffset(1);2408    row.GetCFAValue().SetIsRegisterPlusOffset(k_esp, 8);2409    regloc.SetAtCFAPlusOffset(-8);2410    row.SetRegisterInfo(k_ebp, regloc);2411    unwind_plan.AppendRow(row);2412 2413    // Describe offset 32414    row.SetOffset(3);2415    row.GetCFAValue().SetIsRegisterPlusOffset(k_ebp, 8);2416    unwind_plan.AppendRow(row);2417  }2418 2419  RegisterContextSP reg_ctx_sp;2420  EXPECT_TRUE(engine32->AugmentUnwindPlanFromCallSite(2421      data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp));2422 2423  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(5);2424  EXPECT_EQ(5, row->GetOffset());2425  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);2426  EXPECT_EQ(4, row->GetCFAValue().GetOffset());2427 2428  // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite2429  // doesn't track register restores (pop'ing a reg value back from2430  // the stack) - it was just written to make stepping work correctly.2431  // Technically we should be able to do the following test, but it2432  // won't work today - the unwind plan will still say that the caller's2433  // ebp is on the stack.2434  // EXPECT_FALSE(row->GetRegisterInfo(k_ebp, regloc));2435}2436 2437// Check that the i386 disassembler disassembles past an opcode that2438// is only valid in 32-bit mode (non-long mode), and the x86_64 disassembler2439// stops2440// disassembling at that point (long-mode).2441TEST_F(Testx86AssemblyInspectionEngine, Test32BitOnlyInstruction) {2442  UnwindPlan::Row::AbstractRegisterLocation regloc;2443  const UnwindPlan::Row *row;2444  AddressRange sample_range;2445  UnwindPlan unwind_plan(eRegisterKindLLDB);2446  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2447  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2448 2449  uint8_t data[] = {2450      0x43, // incl $ebx --- an invalid opcode in 64-bit mode2451      0x55, // pushl %ebp2452      0x90  // nop2453  };2454 2455  sample_range = AddressRange(0x1000, sizeof(data));2456 2457  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(2458      data, sizeof(data), sample_range, unwind_plan));2459 2460  row = unwind_plan.GetRowForFunctionOffset(2);2461  EXPECT_EQ(2, row->GetOffset());2462  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);2463  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2464  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2465 2466  EXPECT_TRUE(row->GetRegisterInfo(k_ebp, regloc));2467  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2468  EXPECT_EQ(-8, regloc.GetOffset());2469 2470  unwind_plan.Clear();2471 2472  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(2473      data, sizeof(data), sample_range, unwind_plan));2474 2475  row = unwind_plan.GetRowForFunctionOffset(2);2476  EXPECT_EQ(0, row->GetOffset());2477  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2478  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2479  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2480 2481  EXPECT_FALSE(row->GetRegisterInfo(k_rbp, regloc));2482}2483 2484TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign8BitDisp_i386) {2485  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();2486 2487  uint8_t data[] = {2488      0x55,             // pushl %ebp2489      0x89, 0xe5,       // movl %esp, %ebp2490      0x53,             // pushl %ebx2491      0x83, 0xe4, 0xf0, // andl $-16, %esp2492      0x83, 0xec, 0x10, // subl $16, %esp2493      0x8d, 0x65, 0xfc, // leal -4(%ebp), %esp2494      0x5b,             // popl %ebx2495      0x5d,             // popl %ebp2496      0xc3,             // retl2497  };2498 2499  AddressRange sample_range(0x1000, sizeof(data));2500  UnwindPlan plan(eRegisterKindLLDB);2501  ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),2502                                                           sample_range, plan));2503 2504  UnwindPlan::Row::FAValue esp_plus_4, esp_plus_8, ebp_plus_8;2505  esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);2506  esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);2507  ebp_plus_8.SetIsRegisterPlusOffset(k_ebp, 8);2508 2509  EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(0)->GetCFAValue());2510  EXPECT_EQ(esp_plus_8, plan.GetRowForFunctionOffset(1)->GetCFAValue());2511  for (size_t i = 3; i < sizeof(data) - 2; ++i)2512    EXPECT_EQ(ebp_plus_8, plan.GetRowForFunctionOffset(i)->GetCFAValue())2513        << "i: " << i;2514  EXPECT_EQ(esp_plus_4,2515            plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());2516}2517 2518TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) {2519  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();2520 2521  uint8_t data[] = {2522      0x55,                                     // pushq %rbp2523      0x48, 0x89, 0xe5,                         // movq %rsp, %rbp2524      0x53,                                     // pushl %rbx2525      0x48, 0x83, 0xe4, 0xf0,                   // andq $-16, %rsp2526      0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $256, %rsp2527      0x48, 0x8d, 0x65, 0xf8,                   // leaq -8(%rbp), %rsp2528      0x5b,                                     // popq %rbx2529      0x5d,                                     // popq %rbp2530      0xc3,                                     // retq2531  };2532 2533  AddressRange sample_range(0x1000, sizeof(data));2534  UnwindPlan plan(eRegisterKindLLDB);2535  ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),2536                                                           sample_range, plan));2537 2538  UnwindPlan::Row::FAValue rsp_plus_8, rsp_plus_16, rbp_plus_16;2539  rsp_plus_8.SetIsRegisterPlusOffset(k_rsp, 8);2540  rsp_plus_16.SetIsRegisterPlusOffset(k_rsp, 16);2541  rbp_plus_16.SetIsRegisterPlusOffset(k_rbp, 16);2542 2543  EXPECT_EQ(rsp_plus_8, plan.GetRowForFunctionOffset(0)->GetCFAValue());2544  EXPECT_EQ(rsp_plus_16, plan.GetRowForFunctionOffset(1)->GetCFAValue());2545  for (size_t i = 4; i < sizeof(data) - 2; ++i)2546    EXPECT_EQ(rbp_plus_16, plan.GetRowForFunctionOffset(i)->GetCFAValue())2547        << "i: " << i;2548  EXPECT_EQ(rsp_plus_8,2549            plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());2550}2551 2552TEST_F(Testx86AssemblyInspectionEngine, TestStackRealignMSVC_i386) {2553  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();2554 2555  uint8_t data[] = {2556      0x53,                               // offset 00 -- pushl %ebx2557      0x8b, 0xdc,                         // offset 01 -- movl %esp, %ebx2558      0x83, 0xec, 0x08,                   // offset 03 -- subl $8, %esp2559      0x81, 0xe4, 0x00, 0xff, 0xff, 0xff, // offset 06 -- andl $-256, %esp2560      0x83, 0xc4, 0x04,                   // offset 12 -- addl $4, %esp2561      0x55,                               // offset 15 -- pushl %ebp2562      0x8b, 0xec,                         // offset 16 -- movl %esp, %ebp2563      0x81, 0xec, 0x00, 0x02, 0x00, 0x00, // offset 18 -- subl $512, %esp2564      0x89, 0x7d, 0xfc,                   // offset 24 -- movl %edi, -4(%ebp)2565      0x8b, 0xe5,                         // offset 27 -- movl %ebp, %esp2566      0x5d,                               // offset 29 -- popl %ebp2567      0x8b, 0xe3,                         // offset 30 -- movl %ebx, %esp2568      0x5b,                               // offset 32 -- popl %ebx2569      0xc3                                // offset 33 -- retl2570  };2571 2572  AddressRange sample_range(0x1000, sizeof(data));2573  UnwindPlan plan(eRegisterKindLLDB);2574  ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),2575                                                           sample_range, plan));2576 2577  UnwindPlan::Row::FAValue esp_minus_4, esp_plus_0, esp_plus_4, esp_plus_8,2578      ebx_plus_8, ebp_plus_0;2579  esp_minus_4.SetIsRegisterPlusOffset(k_esp, -4);2580  esp_plus_0.SetIsRegisterPlusOffset(k_esp, 0);2581  esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);2582  esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);2583  ebx_plus_8.SetIsRegisterPlusOffset(k_ebx, 8);2584  ebp_plus_0.SetIsRegisterPlusOffset(k_ebp, 0);2585 2586  // Test CFA2587  EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(0)->GetCFAValue());2588  EXPECT_EQ(esp_plus_8, plan.GetRowForFunctionOffset(1)->GetCFAValue());2589  for (size_t i = 3; i < 33; ++i)2590    EXPECT_EQ(ebx_plus_8, plan.GetRowForFunctionOffset(i)->GetCFAValue())2591        << "i: " << i;2592  EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(33)->GetCFAValue());2593 2594  // Test AFA2595  EXPECT_EQ(esp_plus_0, plan.GetRowForFunctionOffset(12)->GetAFAValue());2596  EXPECT_EQ(esp_minus_4, plan.GetRowForFunctionOffset(15)->GetAFAValue());2597  EXPECT_EQ(esp_plus_0, plan.GetRowForFunctionOffset(16)->GetAFAValue());2598  for (size_t i = 18; i < 30; ++i)2599    EXPECT_EQ(ebp_plus_0, plan.GetRowForFunctionOffset(i)->GetAFAValue())2600        << "i: " << i;2601  EXPECT_EQ(esp_minus_4, plan.GetRowForFunctionOffset(30)->GetAFAValue());2602 2603  // Test saved register2604  UnwindPlan::Row::AbstractRegisterLocation reg_loc;2605  EXPECT_TRUE(2606      plan.GetRowForFunctionOffset(27)->GetRegisterInfo(k_edi, reg_loc));2607  EXPECT_TRUE(reg_loc.IsAtAFAPlusOffset());2608  EXPECT_EQ(-4, reg_loc.GetOffset());2609}2610 2611// Give the disassembler random bytes to test that it doesn't exceed2612// the bounds of the array when run under clang's address sanitizer.2613TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) {2614  AddressRange sample_range;2615  UnwindPlan unwind_plan(eRegisterKindLLDB);2616  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2617  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2618 2619  uint8_t data[] = {2620      0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,2621      0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };2622 2623  sample_range = AddressRange(0x1000, sizeof(data));2624 2625  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(2626      data, sizeof(data), sample_range, unwind_plan));2627 2628  unwind_plan.Clear();2629 2630  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(2631      data, sizeof(data), sample_range, unwind_plan));2632 2633}2634 2635TEST_F(Testx86AssemblyInspectionEngine, TestReturnDetect) {2636  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();2637 2638  // Single fragment with all four return forms.2639  // We want to verify that the unwind state is reset after each ret.2640  uint8_t data[] = {2641      0x55,             // offset  0 -- pushq %rbp2642      0x48, 0x89, 0xe5, // offset  1 -- movq %rsp, %rbp2643      0x31, 0xc0,       // offset  4 -- xorl %eax, %eax2644      0x5d,             // offset  6 -- popq %rbp2645      0xc3,             // offset  7 -- retq2646      0x31, 0xc0,       // offset  8 -- xorl %eax, %eax2647      0x5d,             // offset 10 -- popq %rbp2648      0xcb,             // offset 11 -- retf2649      0x31, 0xc0,       // offset 12 -- xorl %eax, %eax2650      0x5d,             // offset 14 -- popq %rbp2651      0xc2, 0x22, 0x11, // offset 15 -- retq 0x11222652      0x31, 0xc0,       // offset 18 -- xorl %eax, %eax2653      0x5d,             // offset 20 -- popq %rbp2654      0xca, 0x44, 0x33, // offset 21 -- retf 0x33442655      0x31, 0xc0,       // offset 24 -- xorl %eax, %eax2656  };2657 2658  AddressRange sample_range(0x1000, sizeof(data));2659 2660  UnwindPlan unwind_plan(eRegisterKindLLDB);2661  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(2662      data, sizeof(data), sample_range, unwind_plan));2663 2664  // Expect following unwind rows:2665  //  0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2666  //  1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2667  //  4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2668  //  7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2669  //  8: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2670  // 11: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2671  // 12: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2672  // 15: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2673  // 18: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2674  // 21: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2675  // 24: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2676 2677  EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_rsp);2678  EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==2679              eLazyBoolYes);2680  EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);2681 2682  UnwindPlan::Row::AbstractRegisterLocation regloc;2683 2684  //  0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2685  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(0);2686  EXPECT_EQ(0, row->GetOffset());2687  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2688  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2689  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2690 2691  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2692  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2693  EXPECT_EQ(-8, regloc.GetOffset());2694 2695  //  1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2696  row = unwind_plan.GetRowForFunctionOffset(1);2697  EXPECT_EQ(1, row->GetOffset());2698  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2699  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2700  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2701 2702  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2703  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2704  EXPECT_EQ(-8, regloc.GetOffset());2705 2706  //  4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2707  row = unwind_plan.GetRowForFunctionOffset(4);2708  EXPECT_EQ(4, row->GetOffset());2709  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2710  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2711  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2712 2713  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2714  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2715  EXPECT_EQ(-8, regloc.GetOffset());2716 2717  //  7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2718  row = unwind_plan.GetRowForFunctionOffset(7);2719  EXPECT_EQ(7, row->GetOffset());2720  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2721  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2722  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2723 2724  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2725  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2726  EXPECT_EQ(-8, regloc.GetOffset());2727 2728  //  8: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2729  row = unwind_plan.GetRowForFunctionOffset(8);2730  EXPECT_EQ(8, row->GetOffset());2731  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2732  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2733  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2734 2735  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2736  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2737  EXPECT_EQ(-8, regloc.GetOffset());2738 2739  // 11: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2740  row = unwind_plan.GetRowForFunctionOffset(11);2741  EXPECT_EQ(11, row->GetOffset());2742  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2743  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2744  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2745 2746  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2747  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2748  EXPECT_EQ(-8, regloc.GetOffset());2749 2750  // 12: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2751  row = unwind_plan.GetRowForFunctionOffset(12);2752  EXPECT_EQ(12, row->GetOffset());2753  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2754  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2755  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2756 2757  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2758  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2759  EXPECT_EQ(-8, regloc.GetOffset());2760 2761  // 15: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2762  row = unwind_plan.GetRowForFunctionOffset(15);2763  EXPECT_EQ(15, row->GetOffset());2764  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2765  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2766  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2767 2768  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2769  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2770  EXPECT_EQ(-8, regloc.GetOffset());2771 2772  // 18: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2773  row = unwind_plan.GetRowForFunctionOffset(18);2774  EXPECT_EQ(18, row->GetOffset());2775  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2776  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2777  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2778 2779  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2780  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2781  EXPECT_EQ(-8, regloc.GetOffset());2782 2783  // 21: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2784  row = unwind_plan.GetRowForFunctionOffset(21);2785  EXPECT_EQ(21, row->GetOffset());2786  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2787  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2788  EXPECT_EQ(8, row->GetCFAValue().GetOffset());2789 2790  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2791  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2792  EXPECT_EQ(-8, regloc.GetOffset());2793 2794  // 24: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]2795  row = unwind_plan.GetRowForFunctionOffset(24);2796  EXPECT_EQ(24, row->GetOffset());2797  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2798  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2799  EXPECT_EQ(16, row->GetCFAValue().GetOffset());2800 2801  EXPECT_TRUE(row->GetRegisterInfo(k_rip, regloc));2802  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());2803  EXPECT_EQ(-8, regloc.GetOffset());2804}2805 2806 2807// Test mid-function epilogues - the unwind state post-prologue2808// should be re-instated.2809 2810TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyMidFunctionEpilogues) {2811  AddressRange sample_range;2812  UnwindPlan unwind_plan(eRegisterKindLLDB);2813  std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();2814  std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();2815 2816  uint8_t data[] = {2817    0x55,                   // <+0>: pushq %rbp2818    0x48, 0x89, 0xe5,       // <+1>: movq %rsp, %rbp2819    0x48, 0x83, 0xec, 0x70, // <+4>: subq $0x70, %rsp2820    0x90,                   // <+8>: nop               // prologue set up2821 2822    0x74, 0x7,              // <+9>: je 7 <+18>2823    0x48, 0x83, 0xc4, 0x70, // <+11>: addq $0x70, %rsp2824    0x5d,                   // <+15>: popq %rbp2825    0xff, 0xe0,             // <+16>: jmpq *%rax      // epilogue completed2826 2827    0x90,                   // <+18>: nop             // prologue setup back2828 2829    0x74, 0x8,              // <+19>: je 7 <+28>2830    0x48, 0x83, 0xc4, 0x70, // <+21>: addq $0x70, %rsp2831    0x5d,                   // <+25>: popq %rbp2832    0x90,                   // <+26>: nop           // mid-epilogue non-epilogue2833    0xc3,                   // <+27>: retq            // epilogue completed2834 2835    0x90,                   // <+28>: nop             // prologue setup back2836 2837    0x48, 0x83, 0xc4, 0x70, // <+29>: addq $0x70, %rsp2838    0x5d,                   // <+33>: popq %rbp2839    0xc3,                   // <+34>: retq            // epilogue completed2840 2841  };2842 2843  sample_range = AddressRange(0x1000, sizeof(data));2844 2845  int wordsize = 4;2846  EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(2847      data, sizeof(data), sample_range, unwind_plan));2848 2849  // Check that we've unwound the stack after the first mid-function epilogue2850  // row:   CFA=esp +4 => esp=CFA+0 eip=[CFA-4]2851  const UnwindPlan::Row *row = unwind_plan.GetRowForFunctionOffset(16);2852  EXPECT_EQ(16, row->GetOffset());2853  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);2854  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2855  EXPECT_EQ(wordsize, row->GetCFAValue().GetOffset());2856 2857  // Check that we've reinstated the stack frame setup 2858  // unwind instructions after a jmpq *%eax2859  // row:   CFA=ebp +8 => esp=CFA+0 eip=[CFA-8]2860  row = unwind_plan.GetRowForFunctionOffset(18);2861  EXPECT_EQ(18, row->GetOffset());2862  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_ebp);2863  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2864  EXPECT_EQ(wordsize * 2, row->GetCFAValue().GetOffset());2865 2866  // Check that we've reinstated the stack frame setup 2867  // unwind instructions after a mid-function retq2868  // row:   CFA=ebp +8 => esp=CFA+0 eip=[CFA-8]2869  row = unwind_plan.GetRowForFunctionOffset(28);2870  EXPECT_EQ(28, row->GetOffset());2871  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_ebp);2872  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2873  EXPECT_EQ(wordsize * 2, row->GetCFAValue().GetOffset());2874 2875  // After last instruction in the function, verify that2876  // the stack frame has been unwound2877  // row:   CFA=esp +4 => esp=CFA+0 eip=[CFA-4]2878  row = unwind_plan.GetRowForFunctionOffset(34);2879  EXPECT_EQ(34, row->GetOffset());2880  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_esp);2881  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2882  EXPECT_EQ(wordsize, row->GetCFAValue().GetOffset());2883 2884  unwind_plan.Clear();2885 2886  wordsize = 8;2887  EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(2888      data, sizeof(data), sample_range, unwind_plan));2889 2890  // Check that we've unwound the stack after the first mid-function epilogue2891  // row:   CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]2892  row = unwind_plan.GetRowForFunctionOffset(16);2893  EXPECT_EQ(16, row->GetOffset());2894  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2895  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2896  EXPECT_EQ(wordsize, row->GetCFAValue().GetOffset());2897 2898  // Check that we've reinstated the stack frame setup 2899  // unwind instructions after a jmpq *%eax2900  // row:   CFA=rbp+16 => rsp=CFA+0 rip=[CFA-16]2901  row = unwind_plan.GetRowForFunctionOffset(18);2902  EXPECT_EQ(18, row->GetOffset());2903  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2904  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2905  EXPECT_EQ(wordsize * 2, row->GetCFAValue().GetOffset());2906 2907  // Check that we've reinstated the stack frame setup 2908  // unwind instructions after a mid-function retq2909  // row:   CFA=rbp+16 => rsp=CFA+0 rip=[CFA-16]2910  row = unwind_plan.GetRowForFunctionOffset(28);2911  EXPECT_EQ(28, row->GetOffset());2912  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rbp);2913  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2914  EXPECT_EQ(wordsize * 2, row->GetCFAValue().GetOffset());2915 2916  // After last instruction in the function, verify that2917  // the stack frame has been unwound2918  // row:   CFA=rsp +8 => esp=CFA+0 rip=[CFA-8]2919  row = unwind_plan.GetRowForFunctionOffset(34);2920  EXPECT_EQ(34, row->GetOffset());2921  EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == k_rsp);2922  EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);2923  EXPECT_EQ(wordsize, row->GetCFAValue().GetOffset());2924}2925