[Lldb-commits] [lldb] r345577 - [x86] Fix issues with a realigned stack in MSVC compiled applications

Aleksandr Urakov via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 30 03:07:08 PDT 2018


Author: aleksandr.urakov
Date: Tue Oct 30 03:07:08 2018
New Revision: 345577

URL: http://llvm.org/viewvc/llvm-project?rev=345577&view=rev
Log:
[x86] Fix issues with a realigned stack in MSVC compiled applications

Summary:
This patch fixes issues with a stack realignment.

MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
  the saved return address (or to the first parameter on the stack) introduces
  AFA (Aligned Frame Address) which points to the position of the stack pointer
  right after realignment. AFA is used for access to registers saved after the
  realignment (see the test);

Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
  char c;
};

void foo(int foo_arg) {
  OverAligned oa_foo = { 1 };
  auto aaa_foo = 1234;
}

void bar(int bar_arg) {
  OverAligned oa_bar = { 2 };
  auto aaa_bar = 5678;
  foo(1111);
}

int main() {
  bar(2222);
  return 0;
}
```
and here is the `bar` disassembly:
```
push    ebx
mov     ebx, esp
sub     esp, 8
and     esp, -100h
add     esp, 4
push    ebp
mov     ebp, [ebx+4]
mov     [esp+4], ebp
mov     ebp, esp
sub     esp, 200h
mov     byte ptr [ebp-200h], 2
mov     dword ptr [ebp-4], 5678
push    1111            ; foo_arg
call    j_?foo@@YAXH at Z  ; foo(int)
add     esp, 4
mov     esp, ebp
pop     ebp
mov     esp, ebx
pop     ebx
retn
```

Reviewers: labath, zturner, jasonmolenda, stella.stamenova

Reviewed By: jasonmolenda

Subscribers: abidh, lldb-commits

Tags: #lldb

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

Modified:
    lldb/trunk/include/lldb/Symbol/UnwindPlan.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
    lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
    lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
    lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
    lldb/trunk/source/Symbol/UnwindPlan.cpp
    lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp

Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Tue Oct 30 03:07:08 2018
@@ -28,14 +28,22 @@ namespace lldb_private {
 // The UnwindPlan object specifies how to unwind out of a function - where this
 // function saves the caller's register values before modifying them (for non-
 // volatile aka saved registers) and how to find this frame's Canonical Frame
-// Address (CFA).
+// Address (CFA) or Aligned Frame Address (AFA).
 
+// CFA is a DWARF's Canonical Frame Address.
 // Most commonly, registers are saved on the stack, offset some bytes from the
 // Canonical Frame Address, or CFA, which is the starting address of this
 // function's stack frame (the CFA is same as the eh_frame's CFA, whatever that
 // may be on a given architecture). The CFA address for the stack frame does
 // not change during the lifetime of the function.
 
+// AFA is an artificially introduced Aligned Frame Address.
+// It is used only for stack frames with realignment (e.g. when some of the
+// locals has an alignment requirement higher than the stack alignment right
+// after the function call). It is used to access register values saved on the
+// stack after the realignment (and so they are inaccessible through the CFA).
+// AFA usually equals the stack pointer value right after the realignment.
+
 // Internally, the UnwindPlan is structured as a vector of register locations
 // organized by code address in the function, showing which registers have been
 // saved at that point and where they are saved. It can be thought of as the
@@ -61,6 +69,8 @@ public:
         same,              // reg is unchanged
         atCFAPlusOffset,   // reg = deref(CFA + offset)
         isCFAPlusOffset,   // reg = CFA + offset
+        atAFAPlusOffset,   // reg = deref(AFA + offset)
+        isAFAPlusOffset,   // reg = AFA + offset
         inOtherRegister,   // reg = other reg
         atDWARFExpression, // reg = deref(eval(dwarf_expr))
         isDWARFExpression  // reg = eval(dwarf_expr)
@@ -90,6 +100,10 @@ public:
 
       bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
 
+      bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; }
+
+      bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; }
+
       bool IsInOtherRegister() const { return m_type == inOtherRegister; }
 
       bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
@@ -106,6 +120,16 @@ public:
         m_location.offset = offset;
       }
 
+      void SetAtAFAPlusOffset(int32_t offset) {
+        m_type = atAFAPlusOffset;
+        m_location.offset = offset;
+      }
+
+      void SetIsAFAPlusOffset(int32_t offset) {
+        m_type = isAFAPlusOffset;
+        m_location.offset = offset;
+      }
+
       void SetInRegister(uint32_t reg_num) {
         m_type = inOtherRegister;
         m_location.reg_num = reg_num;
@@ -120,9 +144,16 @@ public:
       RestoreType GetLocationType() const { return m_type; }
 
       int32_t GetOffset() const {
-        if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
+        switch(m_type)
+        {
+        case atCFAPlusOffset:
+        case isCFAPlusOffset:
+        case atAFAPlusOffset:
+        case isAFAPlusOffset:
           return m_location.offset;
-        return 0;
+        default:
+          return 0;
+        }
       }
 
       void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
@@ -169,20 +200,20 @@ public:
       } m_location;
     };
 
-    class CFAValue {
+    class FAValue {
     public:
       enum ValueType {
         unspecified,            // not specified
-        isRegisterPlusOffset,   // CFA = register + offset
-        isRegisterDereferenced, // CFA = [reg]
-        isDWARFExpression       // CFA = eval(dwarf_expr)
+        isRegisterPlusOffset,   // FA = register + offset
+        isRegisterDereferenced, // FA = [reg]
+        isDWARFExpression       // FA = eval(dwarf_expr)
       };
 
-      CFAValue() : m_type(unspecified), m_value() {}
+      FAValue() : m_type(unspecified), m_value() {}
 
-      bool operator==(const CFAValue &rhs) const;
+      bool operator==(const FAValue &rhs) const;
 
-      bool operator!=(const CFAValue &rhs) const { return !(*this == rhs); }
+      bool operator!=(const FAValue &rhs) const { return !(*this == rhs); }
 
       void SetUnspecified() { m_type = unspecified; }
 
@@ -279,7 +310,7 @@ public:
           uint16_t length;
         } expr;
       } m_value;
-    }; // class CFAValue
+    }; // class FAValue
 
   public:
     Row();
@@ -302,7 +333,9 @@ public:
 
     void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
 
-    CFAValue &GetCFAValue() { return m_cfa_value; }
+    FAValue &GetCFAValue() { return m_cfa_value; }
+
+    FAValue &GetAFAValue() { return m_afa_value; }
 
     bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
                                               bool can_replace);
@@ -329,7 +362,8 @@ public:
     typedef std::map<uint32_t, RegisterLocation> collection;
     lldb::addr_t m_offset; // Offset into the function for this row
 
-    CFAValue m_cfa_value;
+    FAValue m_cfa_value;
+    FAValue m_afa_value;
     collection m_register_locations;
   }; // class Row
 

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Tue Oct 30 03:07:08 2018
@@ -54,7 +54,8 @@ RegisterContextLLDB::RegisterContextLLDB
     : RegisterContext(thread, frame_number), m_thread(thread),
       m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(),
       m_fallback_unwind_plan_sp(), m_all_registers_available(false),
-      m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS), m_start_pc(),
+      m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS),
+      m_afa(LLDB_INVALID_ADDRESS), m_start_pc(),
       m_current_pc(), m_current_offset(0), m_current_offset_backed_up_one(0),
       m_sym_ctx(sym_ctx), m_sym_ctx_valid(false), m_frame_number(frame_number),
       m_registers(), m_parent_unwind(unwind_lldb) {
@@ -228,7 +229,7 @@ void RegisterContextLLDB::InitializeZero
     return;
   }
 
-  if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) {
+  if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
     // Try the fall back unwind plan since the
     // full unwind plan failed.
     FuncUnwindersSP func_unwinders_sp;
@@ -256,12 +257,14 @@ void RegisterContextLLDB::InitializeZero
       m_frame_type = eNotAValidFrame;
       return;
     }
-  }
+  } else
+    ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
 
   UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
-               " using %s UnwindPlan",
+               " afa is 0x%" PRIx64 " using %s UnwindPlan",
                (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
                (uint64_t)m_cfa,
+               (uint64_t)m_afa,
                m_full_unwind_plan_sp->GetSourceName().GetCString());
 }
 
@@ -379,7 +382,7 @@ void RegisterContextLLDB::InitializeNonZ
       RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
       UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
       if (row.get()) {
-        if (!ReadCFAValueForRow(row_register_kind, row, m_cfa)) {
+        if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) {
           UnwindLogMsg("failed to get cfa value");
           if (m_frame_type != eSkipFrame) // don't override eSkipFrame
           {
@@ -388,6 +391,8 @@ void RegisterContextLLDB::InitializeNonZ
           return;
         }
 
+        ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa);
+
         // A couple of sanity checks..
         if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) {
           UnwindLogMsg("could not find a valid cfa address");
@@ -420,7 +425,8 @@ void RegisterContextLLDB::InitializeNonZ
         }
       }
 
-      UnwindLogMsg("initialized frame cfa is 0x%" PRIx64, (uint64_t)m_cfa);
+      UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
+                   (uint64_t)m_cfa, (uint64_t)m_afa);
       return;
     }
     m_frame_type = eNotAValidFrame;
@@ -584,13 +590,15 @@ void RegisterContextLLDB::InitializeNonZ
     return;
   }
 
-  if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) {
+  if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
     UnwindLogMsg("failed to get cfa");
     m_frame_type = eNotAValidFrame;
     return;
   }
 
-  UnwindLogMsg("m_cfa = 0x%" PRIx64, m_cfa);
+  ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
+
+  UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
 
   if (CheckIfLoopingStack()) {
     TryFallbackUnwindPlan();
@@ -603,9 +611,10 @@ void RegisterContextLLDB::InitializeNonZ
   }
 
   UnwindLogMsg("initialized frame current pc is 0x%" PRIx64
-               " cfa is 0x%" PRIx64,
+               " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
                (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
-               (uint64_t)m_cfa);
+               (uint64_t)m_cfa,
+               (uint64_t)m_afa);
 }
 
 bool RegisterContextLLDB::CheckIfLoopingStack() {
@@ -1314,8 +1323,8 @@ RegisterContextLLDB::SavedLocationForReg
                     unwindplan_regloc)) {
               can_fetch_pc_value = true;
             }
-            if (ReadCFAValueForRow(unwindplan_registerkind, active_row,
-                                   cfa_value)) {
+            if (ReadFrameAddress(unwindplan_registerkind,
+                                 active_row->GetCFAValue(), cfa_value)) {
               can_fetch_cfa = true;
             }
           }
@@ -1444,6 +1453,36 @@ RegisterContextLLDB::SavedLocationForReg
     return UnwindLLDB::RegisterSearchResult::eRegisterFound;
   }
 
+  if (unwindplan_regloc.IsAFAPlusOffset()) {
+    if (m_afa == LLDB_INVALID_ADDRESS)
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+
+    int offset = unwindplan_regloc.GetOffset();
+    regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+    regloc.location.inferred_value = m_afa + offset;
+    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
+    UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus "
+                 "offset %d [value is 0x%" PRIx64 "]",
+                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
+                 regloc.location.inferred_value);
+    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+  }
+
+  if (unwindplan_regloc.IsAtAFAPlusOffset()) {
+    if (m_afa == LLDB_INVALID_ADDRESS)
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+
+    int offset = unwindplan_regloc.GetOffset();
+    regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+    regloc.location.target_memory_location = m_afa + offset;
+    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
+    UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
+                 "AFA plus offset %d [saved at 0x%" PRIx64 "]",
+                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
+                 regloc.location.target_memory_location);
+    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+  }
+
   if (unwindplan_regloc.IsInOtherRegister()) {
     uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
     RegisterNumber row_regnum(m_thread, unwindplan_registerkind,
@@ -1558,7 +1597,6 @@ bool RegisterContextLLDB::TryFallbackUnw
 
   addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
   addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
-  addr_t old_this_frame_cfa_value = m_cfa;
   UnwindLLDB::RegisterLocation regloc;
   if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
                                regloc) ==
@@ -1588,6 +1626,7 @@ bool RegisterContextLLDB::TryFallbackUnw
   // the value of the m_cfa ivar.  Save is down below a bit in 'old_cfa'.
   UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
   addr_t old_cfa = m_cfa;
+  addr_t old_afa = m_afa;
 
   m_registers.clear();
 
@@ -1598,19 +1637,21 @@ bool RegisterContextLLDB::TryFallbackUnw
 
   if (active_row &&
       active_row->GetCFAValue().GetValueType() !=
-          UnwindPlan::Row::CFAValue::unspecified) {
+          UnwindPlan::Row::FAValue::unspecified) {
     addr_t new_cfa;
-    if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(),
-                            active_row, new_cfa) ||
+    if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+                            active_row->GetCFAValue(), new_cfa) ||
         new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
       UnwindLogMsg("failed to get cfa with fallback unwindplan");
       m_fallback_unwind_plan_sp.reset();
       m_full_unwind_plan_sp = original_full_unwind_plan_sp;
-      m_cfa = old_cfa;
       return false;
     }
     m_cfa = new_cfa;
 
+    ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+                     active_row->GetAFAValue(), m_afa);
+
     if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
                                  regloc) ==
         UnwindLLDB::RegisterSearchResult::eRegisterFound) {
@@ -1631,19 +1672,18 @@ bool RegisterContextLLDB::TryFallbackUnw
       m_fallback_unwind_plan_sp.reset();
       m_full_unwind_plan_sp = original_full_unwind_plan_sp;
       m_cfa = old_cfa;
+      m_afa = old_afa;
       return false;
     }
 
-    if (old_caller_pc_value != LLDB_INVALID_ADDRESS) {
-      if (old_caller_pc_value == new_caller_pc_value &&
-          new_cfa == old_this_frame_cfa_value) {
-        UnwindLogMsg("fallback unwind plan got the same values for this frame "
-                     "CFA and caller frame pc, not using");
-        m_fallback_unwind_plan_sp.reset();
-        m_full_unwind_plan_sp = original_full_unwind_plan_sp;
-        m_cfa = old_cfa;
-        return false;
-      }
+    if (old_caller_pc_value == new_caller_pc_value &&
+        m_cfa == old_cfa &&
+        m_afa == old_afa) {
+      UnwindLogMsg("fallback unwind plan got the same values for this frame "
+                   "CFA and caller frame pc, not using");
+      m_fallback_unwind_plan_sp.reset();
+      m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+      return false;
     }
 
     UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' "
@@ -1677,16 +1717,19 @@ bool RegisterContextLLDB::ForceSwitchToF
 
   if (active_row &&
       active_row->GetCFAValue().GetValueType() !=
-          UnwindPlan::Row::CFAValue::unspecified) {
+          UnwindPlan::Row::FAValue::unspecified) {
     addr_t new_cfa;
-    if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(),
-                            active_row, new_cfa) ||
+    if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+                            active_row->GetCFAValue(), new_cfa) ||
         new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
       UnwindLogMsg("failed to get cfa with fallback unwindplan");
       m_fallback_unwind_plan_sp.reset();
       return false;
     }
 
+    ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+                     active_row->GetAFAValue(), m_afa);
+
     m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
     m_fallback_unwind_plan_sp.reset();
 
@@ -1701,18 +1744,18 @@ bool RegisterContextLLDB::ForceSwitchToF
   return false;
 }
 
-bool RegisterContextLLDB::ReadCFAValueForRow(
-    lldb::RegisterKind row_register_kind, const UnwindPlan::RowSP &row,
-    addr_t &cfa_value) {
+bool RegisterContextLLDB::ReadFrameAddress(
+    lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa,
+    addr_t &address) {
   RegisterValue reg_value;
 
-  cfa_value = LLDB_INVALID_ADDRESS;
+  address = LLDB_INVALID_ADDRESS;
   addr_t cfa_reg_contents;
 
-  switch (row->GetCFAValue().GetValueType()) {
-  case UnwindPlan::Row::CFAValue::isRegisterDereferenced: {
+  switch (fa.GetValueType()) {
+  case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
     RegisterNumber cfa_reg(m_thread, row_register_kind,
-                           row->GetCFAValue().GetRegisterNumber());
+                           fa.GetRegisterNumber());
     if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
       const RegisterInfo *reg_info =
           GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
@@ -1721,12 +1764,12 @@ bool RegisterContextLLDB::ReadCFAValueFo
         Status error = ReadRegisterValueFromMemory(
             reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
         if (error.Success()) {
-          cfa_value = reg_value.GetAsUInt64();
+          address = reg_value.GetAsUInt64();
           UnwindLogMsg(
               "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
               ", CFA value is 0x%" PRIx64,
               cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
-              cfa_reg_contents, cfa_value);
+              cfa_reg_contents, address);
           return true;
         } else {
           UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64
@@ -1738,9 +1781,9 @@ bool RegisterContextLLDB::ReadCFAValueFo
     }
     break;
   }
-  case UnwindPlan::Row::CFAValue::isRegisterPlusOffset: {
+  case UnwindPlan::Row::FAValue::isRegisterPlusOffset: {
     RegisterNumber cfa_reg(m_thread, row_register_kind,
-                           row->GetCFAValue().GetRegisterNumber());
+                           fa.GetRegisterNumber());
     if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
       if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
           cfa_reg_contents == 1) {
@@ -1751,35 +1794,35 @@ bool RegisterContextLLDB::ReadCFAValueFo
         cfa_reg_contents = LLDB_INVALID_ADDRESS;
         return false;
       }
-      cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset();
+      address = cfa_reg_contents + fa.GetOffset();
       UnwindLogMsg(
           "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64
           ", offset is %d",
-          cfa_value, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
-          cfa_reg_contents, row->GetCFAValue().GetOffset());
+          address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
+          cfa_reg_contents, fa.GetOffset());
       return true;
     }
     break;
   }
-  case UnwindPlan::Row::CFAValue::isDWARFExpression: {
+  case UnwindPlan::Row::FAValue::isDWARFExpression: {
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
-    DataExtractor dwarfdata(row->GetCFAValue().GetDWARFExpressionBytes(),
-                            row->GetCFAValue().GetDWARFExpressionLength(),
+    DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(),
+                            fa.GetDWARFExpressionLength(),
                             process->GetByteOrder(),
                             process->GetAddressByteSize());
     ModuleSP opcode_ctx;
     DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0,
-                              row->GetCFAValue().GetDWARFExpressionLength());
+                              fa.GetDWARFExpressionLength());
     dwarfexpr.SetRegisterKind(row_register_kind);
     Value result;
     Status error;
     if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
                            &error)) {
-      cfa_value = result.GetScalar().ULongLong();
+      address = result.GetScalar().ULongLong();
 
       UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64,
-                   cfa_value);
+                   address);
       return true;
     }
     UnwindLogMsg("Failed to set CFA value via DWARF expression: %s",

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Tue Oct 30 03:07:08 2018
@@ -192,9 +192,9 @@ private:
 
   bool ReadGPRValue(const RegisterNumber &reg_num, lldb::addr_t &value);
 
-  // Get the CFA register for a given frame.
-  bool ReadCFAValueForRow(lldb::RegisterKind register_kind,
-                          const UnwindPlan::RowSP &row, lldb::addr_t &value);
+  // Get the Frame Address register for a given frame.
+  bool ReadFrameAddress(lldb::RegisterKind register_kind,
+                          UnwindPlan::Row::FAValue &fa, lldb::addr_t &address);
 
   lldb::UnwindPlanSP GetFastUnwindPlanForFrame();
 
@@ -225,6 +225,7 @@ private:
   int m_frame_type;               // enum FrameType
 
   lldb::addr_t m_cfa;
+  lldb::addr_t m_afa;
   lldb_private::Address m_start_pc;
   lldb_private::Address m_current_pc;
 

Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Tue Oct 30 03:07:08 2018
@@ -92,7 +92,7 @@ bool UnwindAssembly_x86::AugmentUnwindPl
   // assembly parsing instead.
 
   if (first_row->GetCFAValue().GetValueType() !=
-          UnwindPlan::Row::CFAValue::isRegisterPlusOffset ||
+          UnwindPlan::Row::FAValue::isRegisterPlusOffset ||
       RegisterNumber(thread, unwind_plan.GetRegisterKind(),
                      first_row->GetCFAValue().GetRegisterNumber()) !=
           sp_regnum ||

Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp Tue Oct 30 03:07:08 2018
@@ -59,6 +59,7 @@ void x86AssemblyInspectionEngine::Initia
     m_machine_ip_regnum = k_machine_eip;
     m_machine_sp_regnum = k_machine_esp;
     m_machine_fp_regnum = k_machine_ebp;
+    m_machine_alt_fp_regnum = k_machine_ebx;
     m_wordsize = 4;
 
     struct lldb_reg_info reginfo;
@@ -84,6 +85,7 @@ void x86AssemblyInspectionEngine::Initia
     m_machine_ip_regnum = k_machine_rip;
     m_machine_sp_regnum = k_machine_rsp;
     m_machine_fp_regnum = k_machine_rbp;
+    m_machine_alt_fp_regnum = k_machine_rbx;
     m_wordsize = 8;
 
     struct lldb_reg_info reginfo;
@@ -135,6 +137,8 @@ void x86AssemblyInspectionEngine::Initia
     m_lldb_sp_regnum = lldb_regno;
   if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
     m_lldb_fp_regnum = lldb_regno;
+  if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
+    m_lldb_alt_fp_regnum = lldb_regno;
   if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
     m_lldb_ip_regnum = lldb_regno;
 
@@ -160,6 +164,7 @@ void x86AssemblyInspectionEngine::Initia
     m_machine_ip_regnum = k_machine_eip;
     m_machine_sp_regnum = k_machine_esp;
     m_machine_fp_regnum = k_machine_ebp;
+    m_machine_alt_fp_regnum = k_machine_ebx;
     m_wordsize = 4;
 
     struct lldb_reg_info reginfo;
@@ -185,6 +190,7 @@ void x86AssemblyInspectionEngine::Initia
     m_machine_ip_regnum = k_machine_rip;
     m_machine_sp_regnum = k_machine_rsp;
     m_machine_fp_regnum = k_machine_rbp;
+    m_machine_alt_fp_regnum = k_machine_rbx;
     m_wordsize = 8;
 
     struct lldb_reg_info reginfo;
@@ -239,6 +245,8 @@ void x86AssemblyInspectionEngine::Initia
     m_lldb_sp_regnum = lldb_regno;
   if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
     m_lldb_fp_regnum = lldb_regno;
+  if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
+    m_lldb_alt_fp_regnum = lldb_regno;
   if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
     m_lldb_ip_regnum = lldb_regno;
 
@@ -387,6 +395,45 @@ bool x86AssemblyInspectionEngine::mov_rs
   return false;
 }
 
+// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
+// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
+bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
+  uint8_t *p = m_cur_insn;
+  if (m_wordsize == 8 && *p == 0x48)
+    p++;
+  if (*(p) == 0x8b && *(p + 1) == 0xdc)
+    return true;
+  if (*(p) == 0x89 && *(p + 1) == 0xe3)
+    return true;
+  return false;
+}
+
+// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
+// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
+bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
+  uint8_t *p = m_cur_insn;
+  if (m_wordsize == 8 && *p == 0x48)
+    p++;
+  if (*(p) == 0x8b && *(p + 1) == 0xe5)
+    return true;
+  if (*(p) == 0x89 && *(p + 1) == 0xec)
+    return true;
+  return false;
+}
+
+// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
+// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
+bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
+  uint8_t *p = m_cur_insn;
+  if (m_wordsize == 8 && *p == 0x48)
+    p++;
+  if (*(p) == 0x8b && *(p + 1) == 0xe3)
+    return true;
+  if (*(p) == 0x89 && *(p + 1) == 0xdc)
+    return true;
+  return false;
+}
+
 // subq $0x20, %rsp
 bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
   uint8_t *p = m_cur_insn;
@@ -476,6 +523,46 @@ bool x86AssemblyInspectionEngine::lea_rb
   return false;
 }
 
+// lea -0x28(%ebx), %esp
+// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
+bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
+  uint8_t *p = m_cur_insn;
+  if (m_wordsize == 8 && *p == 0x48)
+    p++;
+
+  // Check opcode
+  if (*p != 0x8d)
+    return false;
+  ++p;
+
+  // 8 bit displacement
+  if (*p == 0x63) {
+    amount = (int8_t)p[1];
+    return true;
+  }
+
+  // 32 bit displacement
+  if (*p == 0xa3) {
+    amount = (int32_t)extract_4(p + 1);
+    return true;
+  }
+
+  return false;
+}
+
+// and -0xfffffff0, %esp
+// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
+bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
+  uint8_t *p = m_cur_insn;
+  if (m_wordsize == 8 && *p == 0x48)
+    p++;
+
+  if (*p != 0x81 && *p != 0x83)
+    return false;
+
+  return *++p == 0xe4;
+}
+
 // popq %rbx
 // popl %ebx
 bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
@@ -640,7 +727,8 @@ bool x86AssemblyInspectionEngine::GetNon
     return false;
 
   addr_t current_func_text_offset = 0;
-  int current_sp_bytes_offset_from_cfa = 0;
+  int current_sp_bytes_offset_from_fa = 0;
+  bool is_aligned = false;
   UnwindPlan::Row::RegisterLocation initial_regloc;
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
@@ -657,8 +745,8 @@ bool x86AssemblyInspectionEngine::GetNon
   row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
 
   // saved instruction pointer can be found at CFA - wordsize.
-  current_sp_bytes_offset_from_cfa = m_wordsize;
-  initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa);
+  current_sp_bytes_offset_from_fa = m_wordsize;
+  initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
   row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
 
   unwind_plan.AppendRow(row);
@@ -682,6 +770,7 @@ bool x86AssemblyInspectionEngine::GetNon
   UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
   int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
                                                    // epilogue started executed
+  bool prologue_completed_is_aligned;
   std::vector<bool> prologue_completed_saved_registers;
 
   while (current_func_text_offset < size) {
@@ -701,22 +790,59 @@ bool x86AssemblyInspectionEngine::GetNon
       break;
     }
 
-    if (push_rbp_pattern_p()) {
-      current_sp_bytes_offset_from_cfa += m_wordsize;
-      row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
-      UnwindPlan::Row::RegisterLocation regloc;
-      regloc.SetAtCFAPlusOffset(-row->GetCFAValue().GetOffset());
-      row->SetRegisterInfo(m_lldb_fp_regnum, regloc);
-      saved_registers[m_machine_fp_regnum] = true;
-      row_updated = true;
+    auto &cfa_value = row->GetCFAValue();
+    auto &afa_value = row->GetAFAValue();
+    auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
+
+    if (mov_rsp_rbp_pattern_p()) {
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetIsRegisterPlusOffset(
+            m_lldb_fp_regnum, fa_value_ptr->GetOffset());
+        row_updated = true;
+      }
+    }
+
+    else if (mov_rsp_rbx_pattern_p()) {
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetIsRegisterPlusOffset(
+            m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
+        row_updated = true;
+      }
     }
 
-    else if (mov_rsp_rbp_pattern_p()) {
-      row->GetCFAValue().SetIsRegisterPlusOffset(
-          m_lldb_fp_regnum, row->GetCFAValue().GetOffset());
+    else if (and_rsp_pattern_p()) {
+      current_sp_bytes_offset_from_fa = 0;
+      afa_value.SetIsRegisterPlusOffset(
+          m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
+      fa_value_ptr = &afa_value;
+      is_aligned = true;
       row_updated = true;
     }
 
+    else if (mov_rbp_rsp_pattern_p()) {
+      if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
+      {
+        is_aligned = false;
+        fa_value_ptr = &cfa_value;
+        afa_value.SetUnspecified();
+        row_updated = true;
+      }
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
+        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+    }
+
+    else if (mov_rbx_rsp_pattern_p()) {
+      if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
+      {
+        is_aligned = false;
+        fa_value_ptr = &cfa_value;
+        afa_value.SetUnspecified();
+        row_updated = true;
+      }
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
+        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+    }
+
     // This is the start() function (or a pthread equivalent), it starts with a
     // pushl $0x0 which puts the saved pc value of 0 on the stack.  In this
     // case we want to pretend we didn't see a stack movement at all --
@@ -726,12 +852,12 @@ bool x86AssemblyInspectionEngine::GetNon
     }
 
     else if (push_reg_p(machine_regno)) {
-      current_sp_bytes_offset_from_cfa += m_wordsize;
-      // the PUSH instruction has moved the stack pointer - if the CFA is set
+      current_sp_bytes_offset_from_fa += m_wordsize;
+      // the PUSH instruction has moved the stack pointer - if the FA is set
       // in terms of the stack pointer, we need to add a new row of
       // instructions.
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
       // record where non-volatile (callee-saved, spilled) registers are saved
@@ -740,7 +866,10 @@ bool x86AssemblyInspectionEngine::GetNon
           machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
           saved_registers[machine_regno] == false) {
         UnwindPlan::Row::RegisterLocation regloc;
-        regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa);
+        if (is_aligned)
+            regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
+        else
+            regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
         row->SetRegisterInfo(lldb_regno, regloc);
         saved_registers[machine_regno] = true;
         row_updated = true;
@@ -748,7 +877,7 @@ bool x86AssemblyInspectionEngine::GetNon
     }
 
     else if (pop_reg_p(machine_regno)) {
-      current_sp_bytes_offset_from_cfa -= m_wordsize;
+      current_sp_bytes_offset_from_fa -= m_wordsize;
 
       if (nonvolatile_reg_p(machine_regno) &&
           machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
@@ -756,29 +885,29 @@ bool x86AssemblyInspectionEngine::GetNon
         saved_registers[machine_regno] = false;
         row->RemoveRegisterInfo(lldb_regno);
 
-        if (machine_regno == (int)m_machine_fp_regnum) {
-          row->GetCFAValue().SetIsRegisterPlusOffset(
-              m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
+        if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
+          fa_value_ptr->SetIsRegisterPlusOffset(
+              m_lldb_sp_regnum, fa_value_ptr->GetOffset());
         }
 
         in_epilogue = true;
         row_updated = true;
       }
 
-      // the POP instruction has moved the stack pointer - if the CFA is set in
+      // the POP instruction has moved the stack pointer - if the FA is set in
       // terms of the stack pointer, we need to add a new row of instructions.
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetIsRegisterPlusOffset(
-            m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetIsRegisterPlusOffset(
+            m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
     }
 
     else if (pop_misc_reg_p()) {
-      current_sp_bytes_offset_from_cfa -= m_wordsize;
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetIsRegisterPlusOffset(
-            m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
+      current_sp_bytes_offset_from_fa -= m_wordsize;
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetIsRegisterPlusOffset(
+            m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
     }
@@ -787,24 +916,38 @@ bool x86AssemblyInspectionEngine::GetNon
     // off the stack into rbp (restoring the caller's rbp value). It is the
     // opposite of ENTER, or 'push rbp, mov rsp rbp'.
     else if (leave_pattern_p()) {
-      // We're going to copy the value in rbp into rsp, so re-set the sp offset
-      // based on the CFAValue.  Also, adjust it to recognize that we're
-      // popping the saved rbp value off the stack.
-      current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
-      current_sp_bytes_offset_from_cfa -= m_wordsize;
-      row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
-
-      // rbp is restored to the caller's value
-      saved_registers[m_machine_fp_regnum] = false;
-      row->RemoveRegisterInfo(m_lldb_fp_regnum);
-
-      // cfa is now in terms of rsp again.
-      row->GetCFAValue().SetIsRegisterPlusOffset(
-          m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
-      row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      if (saved_registers[m_machine_fp_regnum]) {
+        saved_registers[m_machine_fp_regnum] = false;
+        row->RemoveRegisterInfo(m_lldb_fp_regnum);
+
+        row_updated = true;
+      }
+
+      if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
+      {
+        is_aligned = false;
+        fa_value_ptr = &cfa_value;
+        afa_value.SetUnspecified();
+        row_updated = true;
+      }
+
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
+      {
+        fa_value_ptr->SetIsRegisterPlusOffset(
+            m_lldb_sp_regnum, fa_value_ptr->GetOffset());
+
+        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+      }
+
+      current_sp_bytes_offset_from_fa -= m_wordsize;
+
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetIsRegisterPlusOffset(
+            m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
+        row_updated = true;
+      }
 
       in_epilogue = true;
-      row_updated = true;
     }
 
     else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
@@ -816,12 +959,14 @@ bool x86AssemblyInspectionEngine::GetNon
       UnwindPlan::Row::RegisterLocation regloc;
 
       // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
-      // want to express this as the offset from the CFA.  If the frame base is
-      // rbp (like the above instruction), the CFA offset for rbp is probably
-      // 16.  So we want to say that the value is stored at the CFA address -
+      // want to express this as the offset from the FA.  If the frame base is
+      // rbp (like the above instruction), the FA offset for rbp is probably
+      // 16.  So we want to say that the value is stored at the FA address -
       // 96.
-      regloc.SetAtCFAPlusOffset(
-          -(stack_offset + row->GetCFAValue().GetOffset()));
+      if (is_aligned)
+          regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
+      else
+          regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
 
       row->SetRegisterInfo(lldb_regno, regloc);
 
@@ -829,17 +974,17 @@ bool x86AssemblyInspectionEngine::GetNon
     }
 
     else if (sub_rsp_pattern_p(stack_offset)) {
-      current_sp_bytes_offset_from_cfa += stack_offset;
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      current_sp_bytes_offset_from_fa += stack_offset;
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
     }
 
     else if (add_rsp_pattern_p(stack_offset)) {
-      current_sp_bytes_offset_from_cfa -= stack_offset;
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      current_sp_bytes_offset_from_fa -= stack_offset;
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
       in_epilogue = true;
@@ -847,27 +992,48 @@ bool x86AssemblyInspectionEngine::GetNon
 
     else if (push_extended_pattern_p() || push_imm_pattern_p() ||
              push_misc_reg_p()) {
-      current_sp_bytes_offset_from_cfa += m_wordsize;
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      current_sp_bytes_offset_from_fa += m_wordsize;
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
     }
 
     else if (lea_rsp_pattern_p(stack_offset)) {
-      current_sp_bytes_offset_from_cfa -= stack_offset;
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      current_sp_bytes_offset_from_fa -= stack_offset;
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
       if (stack_offset > 0)
         in_epilogue = true;
     }
 
-    else if (lea_rbp_rsp_pattern_p(stack_offset) &&
-             row->GetCFAValue().GetRegisterNumber() == m_lldb_fp_regnum) {
-      current_sp_bytes_offset_from_cfa =
-          row->GetCFAValue().GetOffset() - stack_offset;
+    else if (lea_rbp_rsp_pattern_p(stack_offset)) {
+      if (is_aligned &&
+          cfa_value.GetRegisterNumber() == m_lldb_fp_regnum) {
+        is_aligned = false;
+        fa_value_ptr = &cfa_value;
+        afa_value.SetUnspecified();
+        row_updated = true;
+      }
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
+        current_sp_bytes_offset_from_fa =
+          fa_value_ptr->GetOffset() - stack_offset;
+      }
+    }
+
+    else if (lea_rbx_rsp_pattern_p(stack_offset)) {
+      if (is_aligned &&
+          cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
+        is_aligned = false;
+        fa_value_ptr = &cfa_value;
+        afa_value.SetUnspecified();
+        row_updated = true;
+      }
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
+        current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
+      }
     }
 
     else if (ret_pattern_p() && prologue_completed_row.get()) {
@@ -877,8 +1043,9 @@ bool x86AssemblyInspectionEngine::GetNon
       UnwindPlan::Row *newrow = new UnwindPlan::Row;
       *newrow = *prologue_completed_row.get();
       row.reset(newrow);
-      current_sp_bytes_offset_from_cfa =
+      current_sp_bytes_offset_from_fa =
           prologue_completed_sp_bytes_offset_from_cfa;
+      is_aligned = prologue_completed_is_aligned;
 
       saved_registers.clear();
       saved_registers.resize(prologue_completed_saved_registers.size(), false);
@@ -896,9 +1063,9 @@ bool x86AssemblyInspectionEngine::GetNon
     // This is used in i386 programs to get the PIC base address for finding
     // global data
     else if (call_next_insn_pattern_p()) {
-      current_sp_bytes_offset_from_cfa += m_wordsize;
-      if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
-        row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+      current_sp_bytes_offset_from_fa += m_wordsize;
+      if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+        fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
         row_updated = true;
       }
     }
@@ -931,7 +1098,8 @@ bool x86AssemblyInspectionEngine::GetNon
     // track of it either way.
     if (in_epilogue == false) {
       prologue_completed_sp_bytes_offset_from_cfa =
-          current_sp_bytes_offset_from_cfa;
+          current_sp_bytes_offset_from_fa;
+      prologue_completed_is_aligned = is_aligned;
     }
 
     m_cur_insn = m_cur_insn + insn_len;

Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h Tue Oct 30 03:07:08 2018
@@ -98,10 +98,15 @@ private:
   bool push_extended_pattern_p();
   bool push_misc_reg_p();
   bool mov_rsp_rbp_pattern_p();
+  bool mov_rsp_rbx_pattern_p();
+  bool mov_rbp_rsp_pattern_p();
+  bool mov_rbx_rsp_pattern_p();
   bool sub_rsp_pattern_p(int &amount);
   bool add_rsp_pattern_p(int &amount);
   bool lea_rsp_pattern_p(int &amount);
   bool lea_rbp_rsp_pattern_p(int &amount);
+  bool lea_rbx_rsp_pattern_p(int &amount);
+  bool and_rsp_pattern_p();
   bool push_reg_p(int &regno);
   bool pop_reg_p(int &regno);
   bool pop_rbp_pattern_p();
@@ -157,9 +162,11 @@ private:
   uint32_t m_machine_ip_regnum;
   uint32_t m_machine_sp_regnum;
   uint32_t m_machine_fp_regnum;
+  uint32_t m_machine_alt_fp_regnum;
   uint32_t m_lldb_ip_regnum;
   uint32_t m_lldb_sp_regnum;
   uint32_t m_lldb_fp_regnum;
+  uint32_t m_lldb_alt_fp_regnum;
 
   typedef std::map<uint32_t, lldb_reg_info> MachineRegnumToNameAndLLDBRegnum;
 

Modified: lldb/trunk/source/Symbol/UnwindPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindPlan.cpp?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindPlan.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindPlan.cpp Tue Oct 30 03:07:08 2018
@@ -29,6 +29,8 @@ operator==(const UnwindPlan::Row::Regist
 
     case atCFAPlusOffset:
     case isCFAPlusOffset:
+    case atAFAPlusOffset:
+    case isAFAPlusOffset:
       return m_location.offset == rhs.m_location.offset;
 
     case inOtherRegister:
@@ -95,6 +97,16 @@ void UnwindPlan::Row::RegisterLocation::
       s.PutChar(']');
   } break;
 
+  case atAFAPlusOffset:
+  case isAFAPlusOffset: {
+    s.PutChar('=');
+    if (m_type == atAFAPlusOffset)
+      s.PutChar('[');
+    s.Printf("AFA%+d", m_location.offset);
+    if (m_type == atAFAPlusOffset)
+      s.PutChar(']');
+  } break;
+
   case inOtherRegister: {
     const RegisterInfo *other_reg_info = nullptr;
     if (unwind_plan)
@@ -125,8 +137,8 @@ static void DumpRegisterName(Stream &s,
     s.Printf("reg(%u)", reg_num);
 }
 
-bool UnwindPlan::Row::CFAValue::
-operator==(const UnwindPlan::Row::CFAValue &rhs) const {
+bool UnwindPlan::Row::FAValue::
+operator==(const UnwindPlan::Row::FAValue &rhs) const {
   if (m_type == rhs.m_type) {
     switch (m_type) {
     case unspecified:
@@ -148,7 +160,7 @@ operator==(const UnwindPlan::Row::CFAVal
   return false;
 }
 
-void UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
+void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
                                      Thread *thread) const {
   switch (m_type) {
   case isRegisterPlusOffset:
@@ -171,6 +183,7 @@ void UnwindPlan::Row::CFAValue::Dump(Str
 
 void UnwindPlan::Row::Clear() {
   m_cfa_value.SetUnspecified();
+  m_afa_value.SetUnspecified();
   m_offset = 0;
   m_register_locations.clear();
 }
@@ -183,6 +196,12 @@ void UnwindPlan::Row::Dump(Stream &s, co
     s.Printf("%4" PRId64 ": CFA=", GetOffset());
 
   m_cfa_value.Dump(s, unwind_plan, thread);
+
+  if (!m_afa_value.IsUnspecified()) {
+    s.Printf(" AFA=");
+    m_afa_value.Dump(s, unwind_plan, thread);
+  }
+
   s.Printf(" => ");
   for (collection::const_iterator idx = m_register_locations.begin();
        idx != m_register_locations.end(); ++idx) {
@@ -194,7 +213,8 @@ void UnwindPlan::Row::Dump(Stream &s, co
   s.EOL();
 }
 
-UnwindPlan::Row::Row() : m_offset(0), m_cfa_value(), m_register_locations() {}
+UnwindPlan::Row::Row()
+    : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
 
 bool UnwindPlan::Row::GetRegisterInfo(
     uint32_t reg_num,
@@ -296,8 +316,10 @@ bool UnwindPlan::Row::SetRegisterLocatio
 }
 
 bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
-  return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
-         m_register_locations == rhs.m_register_locations;
+  return m_offset == rhs.m_offset &&
+      m_cfa_value == rhs.m_cfa_value &&
+      m_afa_value == rhs.m_afa_value &&
+      m_register_locations == rhs.m_register_locations;
 }
 
 void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
@@ -399,7 +421,7 @@ bool UnwindPlan::PlanValidAtAddress(Addr
   // UnwindPlan.
   if (GetRowAtIndex(0).get() == nullptr ||
       GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
-          Row::CFAValue::unspecified) {
+          Row::FAValue::unspecified) {
     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
     if (log) {
       StreamString s;

Modified: lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp?rev=345577&r1=345576&r2=345577&view=diff
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp (original)
+++ lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp Tue Oct 30 03:07:08 2018
@@ -133,7 +133,7 @@ std::unique_ptr<x86AssemblyInspectionEng
 
 namespace lldb_private {
 static std::ostream &operator<<(std::ostream &OS,
-                                const UnwindPlan::Row::CFAValue &CFA) {
+                                const UnwindPlan::Row::FAValue &CFA) {
   StreamString S;
   CFA.Dump(S, nullptr, nullptr);
   return OS << S.GetData();
@@ -2368,7 +2368,7 @@ TEST_F(Testx86AssemblyInspectionEngine,
   ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
                                                            sample_range, plan));
 
-  UnwindPlan::Row::CFAValue esp_plus_4, esp_plus_8, ebp_plus_8;
+  UnwindPlan::Row::FAValue esp_plus_4, esp_plus_8, ebp_plus_8;
   esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);
   esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);
   ebp_plus_8.SetIsRegisterPlusOffset(k_ebp, 8);
@@ -2402,7 +2402,7 @@ TEST_F(Testx86AssemblyInspectionEngine,
   ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
                                                            sample_range, plan));
 
-  UnwindPlan::Row::CFAValue rsp_plus_8, rsp_plus_16, rbp_plus_16;
+  UnwindPlan::Row::FAValue rsp_plus_8, rsp_plus_16, rbp_plus_16;
   rsp_plus_8.SetIsRegisterPlusOffset(k_rsp, 8);
   rsp_plus_16.SetIsRegisterPlusOffset(k_rsp, 16);
   rbp_plus_16.SetIsRegisterPlusOffset(k_rbp, 16);
@@ -2416,6 +2416,65 @@ TEST_F(Testx86AssemblyInspectionEngine,
             plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());
 }
 
+TEST_F(Testx86AssemblyInspectionEngine, TestStackRealignMSVC_i386) {
+  std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
+
+  uint8_t data[] = {
+      0x53,                               // offset 00 -- pushl %ebx
+      0x8b, 0xdc,                         // offset 01 -- movl %esp, %ebx
+      0x83, 0xec, 0x08,                   // offset 03 -- subl $8, %esp
+      0x81, 0xe4, 0x00, 0xff, 0xff, 0xff, // offset 06 -- andl $-256, %esp
+      0x83, 0xc4, 0x04,                   // offset 12 -- addl $4, %esp
+      0x55,                               // offset 15 -- pushl %ebp
+      0x8b, 0xec,                         // offset 16 -- movl %esp, %ebp
+      0x81, 0xec, 0x00, 0x02, 0x00, 0x00, // offset 18 -- subl $512, %esp
+      0x89, 0x7d, 0xfc,                   // offset 24 -- movl %edi, -4(%ebp)
+      0x8b, 0xe5,                         // offset 27 -- movl %ebp, %esp
+      0x5d,                               // offset 29 -- popl %ebp
+      0x8b, 0xe3,                         // offset 30 -- movl %ebx, %esp
+      0x5b,                               // offset 32 -- popl %ebx
+      0xc3                                // offset 33 -- retl
+  };
+
+  AddressRange sample_range(0x1000, sizeof(data));
+  UnwindPlan plan(eRegisterKindLLDB);
+  ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
+                                                           sample_range, plan));
+
+  UnwindPlan::Row::FAValue esp_minus_4, esp_plus_0, esp_plus_4, esp_plus_8,
+      ebx_plus_8, ebp_plus_0;
+  esp_minus_4.SetIsRegisterPlusOffset(k_esp, -4);
+  esp_plus_0.SetIsRegisterPlusOffset(k_esp, 0);
+  esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);
+  esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);
+  ebx_plus_8.SetIsRegisterPlusOffset(k_ebx, 8);
+  ebp_plus_0.SetIsRegisterPlusOffset(k_ebp, 0);
+
+  // Test CFA
+  EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(0)->GetCFAValue());
+  EXPECT_EQ(esp_plus_8, plan.GetRowForFunctionOffset(1)->GetCFAValue());
+  for (size_t i = 3; i < 33; ++i)
+    EXPECT_EQ(ebx_plus_8, plan.GetRowForFunctionOffset(i)->GetCFAValue())
+        << "i: " << i;
+  EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(33)->GetCFAValue());
+
+  // Test AFA
+  EXPECT_EQ(esp_plus_0, plan.GetRowForFunctionOffset(12)->GetAFAValue());
+  EXPECT_EQ(esp_minus_4, plan.GetRowForFunctionOffset(15)->GetAFAValue());
+  EXPECT_EQ(esp_plus_0, plan.GetRowForFunctionOffset(16)->GetAFAValue());
+  for (size_t i = 18; i < 30; ++i)
+    EXPECT_EQ(ebp_plus_0, plan.GetRowForFunctionOffset(i)->GetAFAValue())
+        << "i: " << i;
+  EXPECT_EQ(esp_minus_4, plan.GetRowForFunctionOffset(30)->GetAFAValue());
+
+  // Test saved register
+  UnwindPlan::Row::RegisterLocation reg_loc;
+  EXPECT_TRUE(
+      plan.GetRowForFunctionOffset(27)->GetRegisterInfo(k_edi, reg_loc));
+  EXPECT_TRUE(reg_loc.IsAtAFAPlusOffset());
+  EXPECT_EQ(-4, reg_loc.GetOffset());
+}
+
 // Give the disassembler random bytes to test that it doesn't exceed
 // the bounds of the array when run under clang's address sanitizer.
 TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) {




More information about the lldb-commits mailing list