[Lldb-commits] [lldb] r374246 - Set eRegisterKindEHFrame register numbers for 32 bit ARM register contexts in minidumps

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Wed Oct 9 15:16:12 PDT 2019


Author: gclayton
Date: Wed Oct  9 15:16:12 2019
New Revision: 374246

URL: http://llvm.org/viewvc/llvm-project?rev=374246&view=rev
Log:
Set eRegisterKindEHFrame register numbers for 32 bit ARM register contexts in minidumps

Stack unwinding was sometimes failing when trying to unwind stacks in 32 bit ARM. I discovered this was because the EH frame register numbers were not set. This patch fixes this issue and adds a unit test to verify this doesn't regress.

Differential Revision: https://reviews.llvm.org/D68088

Modified:
    lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
    lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
    lldb/trunk/unittests/Process/minidump/RegisterContextMinidumpTest.cpp

Modified: lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp?rev=374246&r1=374245&r2=374246&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp Wed Oct  9 15:16:12 2019
@@ -9,6 +9,7 @@
 #include "RegisterContextMinidump_ARM.h"
 
 #include "Utility/ARM_DWARF_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
 #include "lldb/Utility/RegisterValue.h"
 #include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/LLDBAssert.h"
@@ -29,14 +30,14 @@ using namespace minidump;
 #define DEF_R(i)                                                               \
   {                                                                            \
     "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex,          \
-        {dwarf_r##i, dwarf_r##i, INV, INV, reg_r##i},                          \
+        {ehframe_r##i, dwarf_r##i, INV, INV, reg_r##i},                          \
         nullptr, nullptr, nullptr, 0    \
   }
 
 #define DEF_R_ARG(i, n)                                                        \
   {                                                                            \
     "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex,         \
-        {dwarf_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \
+        {ehframe_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \
         nullptr, nullptr, nullptr, 0                                           \
   }
 
@@ -173,7 +174,7 @@ static RegisterInfo g_reg_info_apple_fp
     OFFSET(r) + 7 * 4,
     eEncodingUint,
     eFormatHex,
-    {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
+    {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
     nullptr,
     nullptr,
     nullptr,
@@ -186,7 +187,7 @@ static RegisterInfo g_reg_info_fp = {
     OFFSET(r) + 11 * 4,
     eEncodingUint,
     eFormatHex,
-    {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
+    {ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
     nullptr,
     nullptr,
     nullptr,
@@ -213,7 +214,7 @@ static RegisterInfo g_reg_infos[] = {
      OFFSET(r) + 13 * 4,
      eEncodingUint,
      eFormatHex,
-     {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
+     {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
      nullptr,
      nullptr,
      nullptr,
@@ -224,7 +225,7 @@ static RegisterInfo g_reg_infos[] = {
      OFFSET(r) + 14 * 4,
      eEncodingUint,
      eFormatHex,
-     {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
+     {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
      nullptr,
      nullptr,
      nullptr,
@@ -235,7 +236,7 @@ static RegisterInfo g_reg_infos[] = {
      OFFSET(r) + 15 * 4,
      eEncodingUint,
      eFormatHex,
-     {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
+     {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
      nullptr,
      nullptr,
      nullptr,
@@ -246,7 +247,7 @@ static RegisterInfo g_reg_infos[] = {
      OFFSET(cpsr),
      eEncodingUint,
      eFormatHex,
-     {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
+     {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
      nullptr,
      nullptr,
      nullptr,
@@ -476,12 +477,22 @@ RegisterContextMinidump_ARM::RegisterCon
   lldbassert(k_num_regs == k_num_reg_infos);
 }
 
-size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; }
+size_t RegisterContextMinidump_ARM::GetRegisterCountStatic() {
+  return k_num_regs;
+}
+
+// Used for unit testing so we can verify register info is filled in for
+// all register flavors (DWARF, EH Frame, generic, etc).
+size_t RegisterContextMinidump_ARM::GetRegisterCount() {
+  return GetRegisterCountStatic();
+}
 
+// Used for unit testing so we can verify register info is filled in.
 const RegisterInfo *
-RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
+RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(size_t reg,
+                                                          bool apple) {
   if (reg < k_num_reg_infos) {
-    if (m_apple) {
+    if (apple) {
       if (reg == reg_r7)
         return &g_reg_info_apple_fp;
     } else {
@@ -493,6 +504,11 @@ RegisterContextMinidump_ARM::GetRegister
   return nullptr;
 }
 
+const RegisterInfo *
+RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
+  return GetRegisterInfoAtIndexStatic(reg, m_apple);
+}
+
 size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {
   return k_num_reg_sets;
 }

Modified: lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h?rev=374246&r1=374245&r2=374246&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h (original)
+++ lldb/trunk/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h Wed Oct  9 15:16:12 2019
@@ -38,6 +38,12 @@ public:
     // Do nothing... registers are always valid...
   }
 
+  // Used for unit testing.
+  static size_t GetRegisterCountStatic();
+  // Used for unit testing.
+  static const lldb_private::RegisterInfo *
+  GetRegisterInfoAtIndexStatic(size_t reg, bool apple);
+
   size_t GetRegisterCount() override;
 
   const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;

Modified: lldb/trunk/unittests/Process/minidump/RegisterContextMinidumpTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/RegisterContextMinidumpTest.cpp?rev=374246&r1=374245&r2=374246&view=diff
==============================================================================
--- lldb/trunk/unittests/Process/minidump/RegisterContextMinidumpTest.cpp (original)
+++ lldb/trunk/unittests/Process/minidump/RegisterContextMinidumpTest.cpp Wed Oct  9 15:16:12 2019
@@ -10,7 +10,9 @@
 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_32.h"
 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
+#include "Plugins/Process/minidump/RegisterContextMinidump_ARM.h"
 #include "lldb/Utility/DataBuffer.h"
+#include "llvm/ADT/StringRef.h"
 #include "gtest/gtest.h"
 
 using namespace lldb_private;
@@ -143,3 +145,56 @@ TEST(RegisterContextMinidump, ConvertMin
   EXPECT_EQ(Context.ds, reg64(*Buf, Info[lldb_ds_x86_64]));
   EXPECT_EQ(Context.es, reg64(*Buf, Info[lldb_es_x86_64]));
 }
+
+static void TestARMRegInfo(const lldb_private::RegisterInfo *info) {
+  // Make sure we have valid register numbers for eRegisterKindEHFrame and
+  // eRegisterKindDWARF for GPR registers r0-r15 so that we can unwind
+  // correctly when using this information.
+  llvm::StringRef name(info->name);
+  llvm::StringRef alt_name(info->alt_name);
+  if (name.startswith("r") || alt_name.startswith("r")) {
+    EXPECT_NE(info->kinds[lldb::eRegisterKindEHFrame], LLDB_INVALID_REGNUM);
+    EXPECT_NE(info->kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);
+  }
+  // Verify generic register are set correctly
+  if (name == "r0")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_ARG1);
+  else if (name == "r1")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_ARG2);
+  else if (name == "r2")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_ARG3);
+  else if (name == "r3")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_ARG4);
+  else if (name == "sp")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_SP);
+  else if (name == "fp")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_FP);
+  else if (name == "lr")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_RA);
+  else if (name == "pc")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_PC);
+  else if (name == "cpsr")
+    EXPECT_EQ(info->kinds[lldb::eRegisterKindGeneric],
+              (uint32_t)LLDB_REGNUM_GENERIC_FLAGS);
+}
+
+TEST(RegisterContextMinidump, CheckRegisterContextMinidump_ARM) {
+  size_t num_regs = RegisterContextMinidump_ARM::GetRegisterCountStatic();
+  const lldb_private::RegisterInfo *reg_info;
+  for (size_t reg=0; reg<num_regs; ++reg) {
+    reg_info = RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(reg,
+                                                                         true);
+    TestARMRegInfo(reg_info);
+    reg_info = RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(reg,
+                                                                         false);
+    TestARMRegInfo(reg_info);
+  }
+}




More information about the lldb-commits mailing list