diff options
Diffstat (limited to 'lldb/source')
6 files changed, 375 insertions, 134 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index e943c3dc1c9..3a1f2fb37b7 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -54,7 +54,8 @@ RegisterContextLLDB::RegisterContextLLDB(Thread &thread,      : 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::InitializeZerothFrame() {      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::InitializeZerothFrame() {        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::InitializeNonZerothFrame() {        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::InitializeNonZerothFrame() {            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::InitializeNonZerothFrame() {          }        } -      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::InitializeNonZerothFrame() {      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::InitializeNonZerothFrame() {    }    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::SavedLocationForRegister(                      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::SavedLocationForRegister(      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::TryFallbackUnwindPlan() {    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::TryFallbackUnwindPlan() {    // 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::TryFallbackUnwindPlan() {    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::TryFallbackUnwindPlan() {        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::ForceSwitchToFallbackUnwindPlan() {    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::ForceSwitchToFallbackUnwindPlan() {    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::ReadCFAValueForRow(          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::ReadCFAValueForRow(      }      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::ReadCFAValueForRow(          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", diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h index 7e9e77dcf06..d436bc1890c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -192,9 +192,9 @@ private:    bool ReadGPRValue(const RegisterNumber ®_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; diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index 327d0b0e4f7..9295a095353 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -92,7 +92,7 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(    // 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 || diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 10a56980594..eb1989895af 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -59,6 +59,7 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP ®_ctx) {      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::Initialize(RegisterContextSP ®_ctx) {      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::Initialize(RegisterContextSP ®_ctx) {      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::Initialize(      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::Initialize(      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::Initialize(      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_rsp_rbp_pattern_p() {    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_rbp_rsp_pattern_p(int &amount) {    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 ®no) { @@ -640,7 +727,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(      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::GetNonCallSiteUnwindPlanFromAssembly(    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::GetNonCallSiteUnwindPlanFromAssembly(    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::GetNonCallSiteUnwindPlanFromAssembly(        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_rbp_pattern_p()) { -      row->GetCFAValue().SetIsRegisterPlusOffset( -          m_lldb_fp_regnum, row->GetCFAValue().GetOffset()); +    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 (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::GetNonCallSiteUnwindPlanFromAssembly(      }      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::GetNonCallSiteUnwindPlanFromAssembly(            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::GetNonCallSiteUnwindPlanFromAssembly(      }      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::GetNonCallSiteUnwindPlanFromAssembly(          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::GetNonCallSiteUnwindPlanFromAssembly(      // 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::GetNonCallSiteUnwindPlanFromAssembly(        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::GetNonCallSiteUnwindPlanFromAssembly(      }      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::GetNonCallSiteUnwindPlanFromAssembly(      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::GetNonCallSiteUnwindPlanFromAssembly(        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::GetNonCallSiteUnwindPlanFromAssembly(      // 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::GetNonCallSiteUnwindPlanFromAssembly(      // 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; diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h index cec9803c8a4..e02b510ba1f 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h +++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h @@ -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 ®no);    bool pop_reg_p(int ®no);    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; diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index 23ca1324ab0..0f8d9bf7e5a 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -29,6 +29,8 @@ operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {      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::Dump(Stream &s,        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, const UnwindPlan *unwind_plan,      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::CFAValue &rhs) const {    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(Stream &s, const UnwindPlan *unwind_plan,  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, const UnwindPlan *unwind_plan,      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, const UnwindPlan *unwind_plan,    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::SetRegisterLocationToSame(uint32_t reg_num,  }  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(Address 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;  | 

