DavidSpickett updated this revision to Diff 382590.
DavidSpickett added a comment.

Use generic register names and don't set type to DWARF.

Pass triple instead of machine and use isAArch64.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D112069/new/

https://reviews.llvm.org/D112069

Files:
  lldb/include/lldb/Target/Platform.h
  lldb/source/API/SBFrame.cpp
  lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
  lldb/source/Plugins/Platform/Linux/PlatformLinux.h
  lldb/source/Target/RegisterContextUnwind.cpp
  lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py

Index: lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py
===================================================================
--- lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py
+++ lldb/test/API/functionalities/signal/handle-abrt/TestHandleAbort.py
@@ -7,7 +7,21 @@
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
-
+from collections import namedtuple
+
+# Since frames internally point to ExecutionContextRef which itself points
+# to something else, we can't make a deep copy of them from Python.
+# Instead save what we care about for comparison purposes.
+# Ignoring the frame ID because what is frame 0 in the first catch will
+# be frame 2 in the handler backtrace.
+class FrameInfo(namedtuple('FrameInfo', ['sp', 'fp', 'function_name'])):
+    # So assert failures are more readable
+    def __repr__(self):
+        return "SP: 0x{:x} FP: 0x{:x} Fn: {}".format(
+            self.sp, self.fp, self.function_name)
+
+def make_frame_info(frame):
+    return FrameInfo(frame.GetSP(), frame.GetFP(), frame.GetDisplayFunctionName())
 
 class HandleAbortTestCase(TestBase):
 
@@ -16,8 +30,6 @@
     NO_DEBUG_INFO_TESTCASE = True
 
     @skipIfWindows  # signals do not exist on Windows
-    # Fails on Ubuntu Focal
-    @skipIf(archs=["aarch64"], oslist=["linux"])
     @expectedFailureNetBSD
     def test_inferior_handle_sigabrt(self):
         """Inferior calls abort() and handles the resultant SIGABRT.
@@ -47,6 +59,9 @@
         self.assertEqual(thread.GetStopReasonDataAtIndex(0),
                          signo, "The stop signal should be SIGABRT")
 
+        # Save the backtrace frames to compare to the handler backtrace later.
+        signal_frames = [make_frame_info(f) for f in thread.get_thread_frames()]
+
         # Continue to breakpoint in abort handler
         bkpt = target.FindBreakpointByID(
             lldbutil.run_break_set_by_source_regexp(self, "Set a breakpoint here"))
@@ -59,12 +74,20 @@
         self.assertEqual(frame.GetDisplayFunctionName(), "handler", "Unexpected break?")
 
         # Expect that unwinding should find 'abort_caller'
-        foundFoo = False
-        for frame in thread:
+        found_caller = False
+        for frame in thread.get_thread_frames():
             if frame.GetDisplayFunctionName() == "abort_caller":
-                foundFoo = True
+                found_caller = True
+                break
+
+        self.assertTrue(found_caller, "Unwinding did not find func that called abort")
+
+        # The signal handler backtrace has extra frames at the start, remove those
+        handler_frames = thread.get_thread_frames()[-len(signal_frames):]
+        handler_frames = [make_frame_info(f) for f in handler_frames]
 
-        self.assertTrue(foundFoo, "Unwinding did not find func that called abort")
+        # Check that frames present in both backtraces have the same addresses.
+        self.assertEqual(signal_frames, handler_frames, "Common backtrace frames do not match")
 
         # Continue until we exit.
         process.Continue()
Index: lldb/source/Target/RegisterContextUnwind.cpp
===================================================================
--- lldb/source/Target/RegisterContextUnwind.cpp
+++ lldb/source/Target/RegisterContextUnwind.cpp
@@ -900,6 +900,17 @@
   // unwind out of sigtramp.
   if (m_frame_type == eTrapHandlerFrame && process) {
     m_fast_unwind_plan_sp.reset();
+
+    if (m_sym_ctx_valid) {
+      lldb::PlatformSP platform = process->GetTarget().GetPlatform();
+      unwind_plan_sp = platform->GetTrapHandlerUnwindPlan(
+          process->GetTarget().GetArchitecture().GetTriple(),
+          GetSymbolOrFunctionName(m_sym_ctx));
+
+      if (unwind_plan_sp)
+        return unwind_plan_sp;
+    }
+
     unwind_plan_sp =
         func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget());
     if (!unwind_plan_sp)
Index: lldb/source/Plugins/Platform/Linux/PlatformLinux.h
===================================================================
--- lldb/source/Plugins/Platform/Linux/PlatformLinux.h
+++ lldb/source/Plugins/Platform/Linux/PlatformLinux.h
@@ -50,6 +50,9 @@
 
   void CalculateTrapHandlerSymbolNames() override;
 
+  lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
+                                              ConstString name) override;
+
   MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,
                                   lldb::addr_t length, unsigned prot,
                                   unsigned flags, lldb::addr_t fd,
Index: lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
===================================================================
--- lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -17,6 +17,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/FileSpec.h"
@@ -251,6 +252,60 @@
   m_trap_handlers.push_back(ConstString("__restore_rt"));
 }
 
+static lldb::UnwindPlanSP GetAArch64TrapHanlderUnwindPlan(ConstString name) {
+  UnwindPlanSP unwind_plan_sp;
+  if (name != "__kernel_rt_sigreturn")
+    return unwind_plan_sp;
+
+  UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
+  row->SetOffset(0);
+
+  // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
+  //  - 128-byte siginfo struct
+  //  - ucontext struct:
+  //     - 8-byte long (uc_flags)
+  //     - 8-byte pointer (uc_link)
+  //     - 24-byte stack_t
+  //     - 128-byte signal set
+  //     - 8 bytes of padding because sigcontext has 16-byte alignment
+  //     - sigcontext/mcontext_t
+  // [1]
+  // https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c
+  int32_t offset = 128 + 8 + 8 + 24 + 128 + 8;
+  // Then sigcontext[2] is:
+  // - 8 byte fault address
+  // - 31 8 byte registers
+  // - 8 byte sp
+  // - 8 byte pc
+  // [2]
+  // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/sigcontext.h
+  offset += 8 + (31 * 8);
+  row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_SP, offset);
+  // Aka x29
+  row->SetRegisterLocationToAtCFAPlusOffset(LLDB_REGNUM_GENERIC_FP, -16, false);
+  row->SetRegisterLocationToAtCFAPlusOffset(LLDB_REGNUM_GENERIC_SP, 0, false);
+  row->SetRegisterLocationToAtCFAPlusOffset(LLDB_REGNUM_GENERIC_PC, 8, false);
+
+  unwind_plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
+  unwind_plan_sp->AppendRow(row);
+  unwind_plan_sp->SetSourceName("AArch64 Linux sigcontext");
+  unwind_plan_sp->SetSourcedFromCompiler(eLazyBoolYes);
+  // Because sp is the same throughout the function
+  unwind_plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
+  unwind_plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolYes);
+
+  return unwind_plan_sp;
+}
+
+lldb::UnwindPlanSP
+PlatformLinux::GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
+                                        ConstString name) {
+  if (triple.isAArch64())
+    return GetAArch64TrapHanlderUnwindPlan(name);
+
+  return {};
+}
+
 MmapArgList PlatformLinux::GetMmapArgumentList(const ArchSpec &arch,
                                                addr_t addr, addr_t length,
                                                unsigned prot, unsigned flags,
Index: lldb/source/API/SBFrame.cpp
===================================================================
--- lldb/source/API/SBFrame.cpp
+++ lldb/source/API/SBFrame.cpp
@@ -66,7 +66,6 @@
 
 SBFrame::SBFrame(const SBFrame &rhs) : m_opaque_sp() {
   LLDB_RECORD_CONSTRUCTOR(SBFrame, (const lldb::SBFrame &), rhs);
-
   m_opaque_sp = clone(rhs.m_opaque_sp);
 }
 
Index: lldb/include/lldb/Target/Platform.h
===================================================================
--- lldb/include/lldb/Target/Platform.h
+++ lldb/include/lldb/Target/Platform.h
@@ -719,6 +719,24 @@
   ///     A list of symbol names.  The list may be empty.
   virtual const std::vector<ConstString> &GetTrapHandlerSymbolNames();
 
+  /// Try to get a specific unwind plan for a named trap handler.
+  /// The default is not to have specific unwind plans for trap handlers.
+  ///
+  /// \param[in] triple
+  ///     Triple of the current target.
+  ///
+  /// \param[in] name
+  ///     Name of the trap handler function.
+  ///
+  /// \return
+  ///     A specific unwind plan for that trap handler, or an empty
+  ///     shared pointer. The latter means there is no specific plan,
+  ///     unwind as normal.
+  virtual lldb::UnwindPlanSP
+  GetTrapHandlerUnwindPlan(const llvm::Triple &triple, ConstString name) {
+    return {};
+  }
+
   /// Find a support executable that may not live within in the standard
   /// locations related to LLDB.
   ///
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to