[Lldb-commits] [lldb] 4b2b8b9 - Re-land Unwind past an interrupt handler correctly on arm or at pc==0

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 25 14:58:28 PST 2020


Author: Jason Molenda
Date: 2020-02-25T14:58:20-08:00
New Revision: 4b2b8b96db2837a95e8c3ceca3f31ac5641ca001

URL: https://github.com/llvm/llvm-project/commit/4b2b8b96db2837a95e8c3ceca3f31ac5641ca001
DIFF: https://github.com/llvm/llvm-project/commit/4b2b8b96db2837a95e8c3ceca3f31ac5641ca001.diff

LOG: Re-land Unwind past an interrupt handler correctly on arm or at pc==0

Updated the patch to only fetch $pc on a Return Address-using
target only if we're in a trap frame *and* if there is a saved
location for $pc in the trap frame's unwind rules.  If not,
we fall back to fetching the Return Address register (eg $lr).

Original commit msg:

    Unwind past an interrupt handler correctly on arm or at pc==0

    Fix RegisterContextLLDB::InitializeNonZerothFrame so that it
    will fetch a FullUnwindPlan instead of falling back to the
    architectural default unwind plan -- GetFullUnwindPlan knows
    how to spot a jmp 0x0 that results in a fault, which may be
    the case when we see a trap handler on the stack.

    Fix RegisterContextLLDB::SavedLocationForRegister so that when
    the pc value is requested from a trap handler frame, where we
    have a complete register context available to us, don't provide
    the Return Address register (lr) instead of the pc.  We have
    an actual pc value here, and it's pointing to the instruction
    that faulted.

    Differential revision: https://reviews.llvm.org/D75007
    <rdar://problem/59416588>

Added: 
    

Modified: 
    lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 56dd273c25b7..2c5f82eb2af0 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -328,9 +328,13 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
 
   // If we don't have a Module for some reason, we're not going to find
   // symbol/function information - just stick in some reasonable defaults and
-  // hope we can unwind past this frame.
+  // hope we can unwind past this frame.  If we're above a trap handler,
+  // we may be at a bogus address because we jumped through a bogus function
+  // pointer and trapped, so don't force the arch default unwind plan in that 
+  // case.
   ModuleSP pc_module_sp(m_current_pc.GetModule());
-  if (!m_current_pc.IsValid() || !pc_module_sp) {
+  if ((!m_current_pc.IsValid() || !pc_module_sp) &&
+      above_trap_handler == false) {
     UnwindLogMsg("using architectural default unwind method");
 
     // Test the pc value to see if we know it's in an unmapped/non-executable
@@ -1206,15 +1210,28 @@ RegisterContextLLDB::SavedLocationForRegister(
       if (pc_regnum.IsValid() && pc_regnum == regnum &&
           m_full_unwind_plan_sp->GetReturnAddressRegister() !=
               LLDB_INVALID_REGNUM) {
-
-        return_address_reg.init(
-            m_thread, m_full_unwind_plan_sp->GetRegisterKind(),
-            m_full_unwind_plan_sp->GetReturnAddressRegister());
-        regnum = return_address_reg;
-        UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a "
-                     "RA reg; getting %s (%d) instead",
-                     return_address_reg.GetName(),
-                     return_address_reg.GetAsKind(eRegisterKindLLDB));
+        // If this is a trap handler frame, we should have access to
+        // the complete register context when the interrupt/async 
+        // signal was received, we should fetch the actual saved $pc
+        // value instead of the Return Address register.
+        // If $pc is not available, fall back to the RA reg.
+        UnwindPlan::Row::RegisterLocation scratch;
+        if (m_frame_type == eTrapHandlerFrame &&
+            active_row->GetRegisterInfo 
+              (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
+          UnwindLogMsg("Providing pc register instead of rewriting to "
+                       "RA reg because this is a trap handler and there is "
+                       "a location for the saved pc register value.");
+        } else {
+          return_address_reg.init(
+              m_thread, m_full_unwind_plan_sp->GetRegisterKind(),
+              m_full_unwind_plan_sp->GetReturnAddressRegister());
+          regnum = return_address_reg;
+          UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a "
+                       "RA reg; getting %s (%d) instead",
+                       return_address_reg.GetName(),
+                       return_address_reg.GetAsKind(eRegisterKindLLDB));
+        }
       } else {
         if (regnum.GetAsKind(unwindplan_registerkind) == LLDB_INVALID_REGNUM) {
           if (unwindplan_registerkind == eRegisterKindGeneric) {


        


More information about the lldb-commits mailing list