[Lldb-commits] [lldb] r283847 - Add a first unit test for the arm64 instruction profiled unwind

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 10 19:24:01 PDT 2016


Author: jmolenda
Date: Mon Oct 10 21:24:00 2016
New Revision: 283847

URL: http://llvm.org/viewvc/llvm-project?rev=283847&view=rev
Log:
Add a first unit test for the arm64 instruction profiled unwind
plan generator.

Fix a small bug in EmulateInstructionARM64::GetFramePointerRegister
which was returning the stack pointer reg instead of fp, prevented
the unwinder from recognizing the switch to using the fp in a
function. (<rdar://problem/28663117>)

Add a new eContextRestoreStackPointer context hint so that the arm64
emulator can flag when the frame pointer value is copied back in to
the stack pointer and that should be used to compute the canonical
frame address again in an epilogue sequence.  (<rdar://problem/28704862>)

Small changes to UnwindAssemblyInstEmulation to have a method we can
call without a live process/thread/etc for unit tests.

<rdar://problem/28663117> 
<rdar://problem/28704862> 
<rdar://problem/28509178> 

Added:
    lldb/trunk/unittests/UnwindAssembly/InstEmulation/
    lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt
    lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp
Modified:
    lldb/trunk/include/lldb/Core/EmulateInstruction.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
    lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
    lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
    lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt

Modified: lldb/trunk/include/lldb/Core/EmulateInstruction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/EmulateInstruction.h?rev=283847&r1=283846&r2=283847&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/EmulateInstruction.h (original)
+++ lldb/trunk/include/lldb/Core/EmulateInstruction.h Mon Oct 10 21:24:00 2016
@@ -111,6 +111,10 @@ public:
     // Adjust the frame pointer for the current frame
     eContextSetFramePointer,
 
+    // Typically in an epilogue sequence.  Copy the frame pointer back
+    // into the stack pointer, use SP for CFA calculations again.
+    eContextRestoreStackPointer,
+
     // Add or subtract a value from a base address register (other than SP)
     eContextAdjustBaseRegister,
 

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=283847&r1=283846&r2=283847&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Oct 10 21:24:00 2016
@@ -916,6 +916,7 @@
 		AF20F76A1AF18F9000751A6E /* ABISysV_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F7681AF18F9000751A6E /* ABISysV_arm64.cpp */; };
 		AF20F7701AF1902900751A6E /* RegisterContextLinux_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F76E1AF1902900751A6E /* RegisterContextLinux_arm64.cpp */; };
 		AF23B4DB19009C66003E2A58 /* FreeBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */; };
+		AF248A4D1DA71C77000B814D /* TestArm64InstEmulation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF248A4C1DA71C77000B814D /* TestArm64InstEmulation.cpp */; };
 		AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */; };
 		AF25AB26188F685C0030DEC3 /* AppleGetQueuesHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF25AB24188F685C0030DEC3 /* AppleGetQueuesHandler.cpp */; };
 		AF26703A1852D01E00B6CC36 /* Queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2670381852D01E00B6CC36 /* Queue.cpp */; };
@@ -2922,6 +2923,7 @@
 		AF20F76F1AF1902900751A6E /* RegisterContextLinux_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_arm64.h; path = Utility/RegisterContextLinux_arm64.h; sourceTree = "<group>"; };
 		AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FreeBSDSignals.cpp; path = Utility/FreeBSDSignals.cpp; sourceTree = "<group>"; };
 		AF23B4DA19009C66003E2A58 /* FreeBSDSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeBSDSignals.h; path = Utility/FreeBSDSignals.h; sourceTree = "<group>"; };
+		AF248A4C1DA71C77000B814D /* TestArm64InstEmulation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestArm64InstEmulation.cpp; path = UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp; sourceTree = "<group>"; };
 		AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformDarwinKernel.cpp; sourceTree = "<group>"; };
 		AF254E30170CCC33007AE5C9 /* PlatformDarwinKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformDarwinKernel.h; sourceTree = "<group>"; };
 		AF25AB24188F685C0030DEC3 /* AppleGetQueuesHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetQueuesHandler.cpp; sourceTree = "<group>"; };
@@ -6252,6 +6254,14 @@
 			name = "SysV-arm64";
 			sourceTree = "<group>";
 		};
+		AF248A4B1DA71C67000B814D /* InstEmulation */ = {
+			isa = PBXGroup;
+			children = (
+				AF248A4C1DA71C77000B814D /* TestArm64InstEmulation.cpp */,
+			);
+			name = InstEmulation;
+			sourceTree = "<group>";
+		};
 		AF2BCA6518C7EFDE005B4526 /* JITLoader */ = {
 			isa = PBXGroup;
 			children = (
@@ -6301,7 +6311,7 @@
 		AFEC5FD31D94F9130076A480 /* UnwindAssembly */ = {
 			isa = PBXGroup;
 			children = (
-				AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */,
+				AF248A4B1DA71C67000B814D /* InstEmulation */,
 				AFEC5FD41D94F9270076A480 /* x86 */,
 			);
 			name = UnwindAssembly;
@@ -6310,6 +6320,7 @@
 		AFEC5FD41D94F9270076A480 /* x86 */ = {
 			isa = PBXGroup;
 			children = (
+				AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */,
 			);
 			name = x86;
 			sourceTree = "<group>";
@@ -6911,6 +6922,7 @@
 				23CB15351D66DA9300EDDDE1 /* UriParserTest.cpp in Sources */,
 				23CB15361D66DA9300EDDDE1 /* FileSpecTest.cpp in Sources */,
 				23E2E5251D90373D006F38BB /* ArchSpecTest.cpp in Sources */,
+				AF248A4D1DA71C77000B814D /* TestArm64InstEmulation.cpp in Sources */,
 				23CB15371D66DA9300EDDDE1 /* PythonTestSuite.cpp in Sources */,
 				23E2E5291D9037D9006F38BB /* SymbolFilePDBTests.cpp in Sources */,
 				23E2E5321D903832006F38BB /* BreakpointIDTest.cpp in Sources */,

Modified: lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp?rev=283847&r1=283846&r2=283847&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp (original)
+++ lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp Mon Oct 10 21:24:00 2016
@@ -497,7 +497,7 @@ uint32_t EmulateInstructionARM64::GetFra
   if (m_arch.GetTriple().isAndroid())
     return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
 
-  return arm64_dwarf::sp;
+  return arm64_dwarf::fp;
 }
 
 bool EmulateInstructionARM64::UsingAArch32() {
@@ -693,8 +693,13 @@ bool EmulateInstructionARM64::EmulateADD
   if (arm64_dwarf::GetRegisterInfo(n, reg_info_Rn))
     context.SetRegisterPlusOffset(reg_info_Rn, imm);
 
-  if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) &&
-      d == arm64_dwarf::sp && !setflags) {
+  if (n == GetFramePointerRegisterNumber() && d == arm64_dwarf::sp &&
+      !setflags) {
+    // 'mov sp, fp' - common epilogue instruction, CFA is now in terms
+    // of the stack pointer, instead of frame pointer.
+    context.type = EmulateInstruction::eContextRestoreStackPointer;
+  } else if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) &&
+             d == arm64_dwarf::sp && !setflags) {
     context.type = EmulateInstruction::eContextAdjustStackPointer;
   } else if (d == GetFramePointerRegisterNumber() && n == arm64_dwarf::sp &&
              !setflags) {

Modified: lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp?rev=283847&r1=283846&r2=283847&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp Mon Oct 10 21:24:00 2016
@@ -34,6 +34,27 @@ using namespace lldb_private;
 
 bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
     AddressRange &range, Thread &thread, UnwindPlan &unwind_plan) {
+  std::vector<uint8_t> function_text(range.GetByteSize());
+  ProcessSP process_sp(thread.GetProcess());
+  if (process_sp) {
+    Error error;
+    const bool prefer_file_cache = true;
+    if (process_sp->GetTarget().ReadMemory(
+            range.GetBaseAddress(), prefer_file_cache, function_text.data(),
+            range.GetByteSize(), error) != range.GetByteSize()) {
+      return false;
+    }
+  }
+  return GetNonCallSiteUnwindPlanFromAssembly(
+      range, function_text.data(), function_text.size(), unwind_plan);
+}
+
+bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
+    AddressRange &range, uint8_t *opcode_data, size_t opcode_size,
+    UnwindPlan &unwind_plan) {
+  if (opcode_data == nullptr || opcode_size == 0)
+    return false;
+
   if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid() &&
       m_inst_emulator_ap.get()) {
 
@@ -46,18 +67,16 @@ bool UnwindAssemblyInstEmulation::GetNon
     if (unwind_plan.GetRowCount() == 0)
       return false;
 
-    ExecutionContext exe_ctx;
-    thread.CalculateExecutionContext(exe_ctx);
     const bool prefer_file_cache = true;
-    DisassemblerSP disasm_sp(Disassembler::DisassembleRange(
-        m_arch, NULL, NULL, exe_ctx, range, prefer_file_cache));
+    DisassemblerSP disasm_sp(Disassembler::DisassembleBytes(
+        m_arch, NULL, NULL, range.GetBaseAddress(), opcode_data, opcode_size,
+        99999, prefer_file_cache));
 
     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
 
     if (disasm_sp) {
 
       m_range_ptr = ⦥
-      m_thread_ptr = &thread;
       m_unwind_plan_ptr = &unwind_plan;
 
       const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
@@ -154,8 +173,8 @@ bool UnwindAssemblyInstEmulation::GetNon
               m_register_values = it->second.second;
             }
 
-            m_inst_emulator_ap->SetInstruction(
-                inst->GetOpcode(), inst->GetAddress(), exe_ctx.GetTargetPtr());
+            m_inst_emulator_ap->SetInstruction(inst->GetOpcode(),
+                                               inst->GetAddress(), nullptr);
 
             if (last_condition !=
                 m_inst_emulator_ap->GetInstructionCondition()) {
@@ -253,11 +272,10 @@ bool UnwindAssemblyInstEmulation::GetNon
 
     if (log && log->GetVerbose()) {
       StreamString strm;
-      lldb::addr_t base_addr =
-          range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get());
+      lldb::addr_t base_addr = range.GetBaseAddress().GetFileAddress();
       strm.Printf("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):",
                   base_addr, base_addr + range.GetByteSize());
-      unwind_plan.Dump(strm, &thread, base_addr);
+      unwind_plan.Dump(strm, nullptr, base_addr);
       log->PutCString(strm.GetData());
     }
     return unwind_plan.GetRowCount() > 0;
@@ -613,6 +631,19 @@ bool UnwindAssemblyInstEmulation::WriteR
       m_cfa_reg_info = *reg_info;
       const uint32_t cfa_reg_num =
           reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
+      assert(cfa_reg_num != LLDB_INVALID_REGNUM);
+      m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
+          cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64());
+      m_curr_row_modified = true;
+    }
+    break;
+
+  case EmulateInstruction::eContextRestoreStackPointer:
+    if (m_fp_is_cfa) {
+      m_fp_is_cfa = false;
+      m_cfa_reg_info = *reg_info;
+      const uint32_t cfa_reg_num =
+          reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
       assert(cfa_reg_num != LLDB_INVALID_REGNUM);
       m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
           cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64());

Modified: lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h?rev=283847&r1=283846&r2=283847&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h Mon Oct 10 21:24:00 2016
@@ -29,6 +29,11 @@ public:
       lldb_private::UnwindPlan &unwind_plan) override;
 
   bool
+  GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange &func,
+                                       uint8_t *opcode_data, size_t opcode_size,
+                                       lldb_private::UnwindPlan &unwind_plan);
+
+  bool
   AugmentUnwindPlanFromCallSite(lldb_private::AddressRange &func,
                                 lldb_private::Thread &thread,
                                 lldb_private::UnwindPlan &unwind_plan) override;
@@ -67,8 +72,8 @@ private:
   UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch,
                               lldb_private::EmulateInstruction *inst_emulator)
       : UnwindAssembly(arch), m_inst_emulator_ap(inst_emulator),
-        m_range_ptr(NULL), m_thread_ptr(NULL), m_unwind_plan_ptr(NULL),
-        m_curr_row(), m_cfa_reg_info(), m_fp_is_cfa(false), m_register_values(),
+        m_range_ptr(NULL), m_unwind_plan_ptr(NULL), m_curr_row(),
+        m_cfa_reg_info(), m_fp_is_cfa(false), m_register_values(),
         m_pushed_regs(), m_curr_row_modified(false),
         m_forward_branch_offset(0) {
     if (m_inst_emulator_ap.get()) {
@@ -130,7 +135,6 @@ private:
 
   std::unique_ptr<lldb_private::EmulateInstruction> m_inst_emulator_ap;
   lldb_private::AddressRange *m_range_ptr;
-  lldb_private::Thread *m_thread_ptr;
   lldb_private::UnwindPlan *m_unwind_plan_ptr;
   lldb_private::UnwindPlan::RowSP m_curr_row;
   typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap;

Modified: lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt?rev=283847&r1=283846&r2=283847&view=diff
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt (original)
+++ lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt Mon Oct 10 21:24:00 2016
@@ -1 +1,2 @@
 add_subdirectory(x86)
+add_subdirectory(InstEmulation)

Added: lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt?rev=283847&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt (added)
+++ lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt Mon Oct 10 21:24:00 2016
@@ -0,0 +1 @@
+add_lldb_unittest(InstEmulationTests TestArm64InstEmulation.cpp)

Added: lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp?rev=283847&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp (added)
+++ lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp Mon Oct 10 21:24:00 2016
@@ -0,0 +1,166 @@
+//===-- TestArm64InstEmulation.cpp ------------------------------------*- C++
+//-*-===//
+
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include <vector>
+
+#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
+#include "Utility/ARM64_DWARF_Registers.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/UnwindAssembly.h"
+
+#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
+#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
+#include "llvm/Support/TargetSelect.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class TestArm64InstEmulation : public testing::Test {
+public:
+  //  static void SetUpTestCase() { }
+
+  //  static void TearDownTestCase() { }
+
+  //  virtual void SetUp() override { }
+
+  //  virtual void TearDown() override { }
+
+protected:
+};
+
+static void init() {
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllAsmPrinters();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllDisassemblers();
+  DisassemblerLLVMC::Initialize();
+  EmulateInstructionARM64::Initialize();
+}
+
+static void terminate() {
+  DisassemblerLLVMC::Terminate();
+  EmulateInstructionARM64::Terminate();
+}
+
+TEST_F(TestArm64InstEmulation, TestSimpleFunction) {
+
+  init();
+
+  ArchSpec arch("arm64-apple-ios10", nullptr);
+  UnwindAssemblyInstEmulation *engine =
+      static_cast<UnwindAssemblyInstEmulation *>(
+          UnwindAssemblyInstEmulation::CreateInstance(arch));
+  EXPECT_TRUE(engine != nullptr);
+  if (engine == nullptr)
+    return;
+
+  UnwindPlan::RowSP row_sp;
+  AddressRange sample_range;
+  UnwindPlan unwind_plan(eRegisterKindLLDB);
+  UnwindPlan::Row::RegisterLocation regloc;
+
+  // 'int main() { }' compiled for arm64-apple-macosx with clang
+  uint8_t data[] = {
+      0xfd, 0x7b, 0xbf, 0xa9, // 0xa9bf7bfd :  stp x29, x30, [sp, #-0x10]!
+      0xfd, 0x03, 0x00, 0x91, // 0x910003fd :  mov x29, sp
+      0xff, 0x43, 0x00, 0xd1, // 0xd10043ff :  sub sp, sp, #0x10
+
+      0xbf, 0x03, 0x00, 0x91, // 0x910003bf :  mov sp, x29
+      0xfd, 0x7b, 0xc1, 0xa8, // 0xa8c17bfd :  ldp x29, x30, [sp], #16
+      0xc0, 0x03, 0x5f, 0xd6, // 0xd65f03c0 :  ret
+  };
+
+  // UnwindPlan we expect:
+
+  // row[0]:    0: CFA=sp +0 =>
+  // row[1]:    4: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
+  // row[2]:    8: CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
+  // row[2]:   16: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
+  // row[3]:   20: CFA=sp +0 => fp= <same> lr= <same>
+
+  // But this is missing the setup of the frame pointer register (x29) and
+  // restore of the same.  This is a bug in the instruction profiler --
+  // it won't work if we have a stack frame with a variable length array, or
+  // an alloca style call where the stack frame size is not fixed.  We need
+  // to recognize the setup of the frame pointer register.
+
+  sample_range = AddressRange(0x1000, sizeof(data));
+
+  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+      sample_range, data, sizeof(data), unwind_plan));
+
+  // CFA=sp +0
+  row_sp = unwind_plan.GetRowForFunctionOffset(0);
+  EXPECT_EQ(0, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+  // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
+  row_sp = unwind_plan.GetRowForFunctionOffset(4);
+  EXPECT_EQ(4, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-16, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-8, regloc.GetOffset());
+
+  // CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
+  row_sp = unwind_plan.GetRowForFunctionOffset(8);
+  EXPECT_EQ(8, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-16, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-8, regloc.GetOffset());
+
+  // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
+  row_sp = unwind_plan.GetRowForFunctionOffset(16);
+  EXPECT_EQ(16, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-16, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-8, regloc.GetOffset());
+
+  // CFA=sp +0 => fp= <same> lr= <same>
+  row_sp = unwind_plan.GetRowForFunctionOffset(20);
+  EXPECT_EQ(20, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+  terminate();
+}




More information about the lldb-commits mailing list