diff options
| -rw-r--r-- | lldb/include/lldb/Symbol/UnwindPlan.h | 65 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 67 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h | 4 | ||||
| -rw-r--r-- | lldb/source/Symbol/UnwindPlan.cpp | 27 | 
4 files changed, 115 insertions, 48 deletions
diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h index e1b146fe219..820e682acbd 100644 --- a/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/lldb/include/lldb/Symbol/UnwindPlan.h @@ -58,13 +58,13 @@ public:                      atDWARFExpression,  // reg = deref(eval(dwarf_expr))                      isDWARFExpression   // reg = eval(dwarf_expr)                  }; -     +              RegisterLocation() :                   m_type(unspecified),                   m_location()               {              } -     +              bool              operator == (const RegisterLocation& rhs) const; @@ -242,6 +242,7 @@ public:          Row (const UnwindPlan::Row& rhs) :               m_offset             (rhs.m_offset), +            m_cfa_type           (rhs.m_cfa_type),              m_cfa_reg_num        (rhs.m_cfa_reg_num),              m_cfa_offset         (rhs.m_cfa_offset),              m_register_locations (rhs.m_register_locations) @@ -275,12 +276,50 @@ public:              m_offset += offset;          } +        // How we can reconstruct the CFA address for this stack frame, at this location +        enum CFAType +        { +            CFAIsRegisterPlusOffset,   // the CFA value in a register plus (or minus) an offset +            CFAIsRegisterDereferenced  // the address in a register is dereferenced to get CFA value +        }; + +        CFAType +        GetCFAType () const +        { +            return m_cfa_type; +        } + +        void +        SetCFAType (CFAType cfa_type) +        { +            m_cfa_type = cfa_type; +        } + +        // This should be used when GetCFAType() returns CFAIsRegisterPlusOffset          uint32_t          GetCFARegister () const          {              return m_cfa_reg_num;          } +        // This should be used when GetCFAType() is set to CFAIsRegisterPlusOffset +        void +        SetCFARegister (uint32_t reg_num); + +        // This should be used when GetCFAType() returns CFAIsRegisterPlusOffset +        int32_t +        GetCFAOffset () const +        { +            return m_cfa_offset; +        } + +        // This should be used when GetCFAType() is set to CFAIsRegisterPlusOffset +        void +        SetCFAOffset (int32_t offset) +        { +            m_cfa_offset = offset; +        } +          bool          SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num,                                                 int32_t offset,  @@ -309,23 +348,6 @@ public:          SetRegisterLocationToSame (uint32_t reg_num,                                      bool must_replace); - - -        void -        SetCFARegister (uint32_t reg_num); - -        int32_t -        GetCFAOffset () const -        { -            return m_cfa_offset; -        } - -        void -        SetCFAOffset (int32_t offset) -        { -            m_cfa_offset = offset; -        } -          void          Clear (); @@ -335,8 +357,13 @@ public:      protected:          typedef std::map<uint32_t, RegisterLocation> collection;          lldb::addr_t m_offset;      // Offset into the function for this row + +        CFAType m_cfa_type; + +        // If m_cfa_type == CFAIsRegisterPlusOffset, the following ivars are used          uint32_t m_cfa_reg_num;     // The Call Frame Address register number          int32_t  m_cfa_offset;      // The offset from the CFA for this row +          collection m_register_locations;      }; // class Row diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 0bd07f69474..1b479298591 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -232,7 +232,6 @@ RegisterContextLLDB::InitializeZerothFrame()      m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();      UnwindPlan::RowSP active_row; -    int cfa_offset = 0;      lldb::RegisterKind row_register_kind = eRegisterKindGeneric;      if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))      { @@ -254,18 +253,13 @@ RegisterContextLLDB::InitializeZerothFrame()      } -    addr_t cfa_regval = LLDB_INVALID_ADDRESS; -    if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) +    if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))      {          UnwindLogMsg ("could not read CFA register for this frame.");          m_frame_type = eNotAValidFrame;          return;      } -    cfa_offset = active_row->GetCFAOffset (); -    m_cfa = cfa_regval + cfa_offset; - -    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);      UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",              (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),              (uint64_t) m_cfa, @@ -378,14 +372,11 @@ RegisterContextLLDB::InitializeNonZerothFrame()              m_all_registers_available = false;              m_current_offset = -1;              m_current_offset_backed_up_one = -1; -            addr_t cfa_regval = LLDB_INVALID_ADDRESS;              RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();              UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);              if (row.get())              { -                uint32_t cfa_regnum = row->GetCFARegister(); -                int cfa_offset = row->GetCFAOffset(); -                if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval)) +                if (!ReadCFAValueForRow (row_register_kind, row, m_cfa))                  {                      UnwindLogMsg ("failed to get cfa value");                      if (m_frame_type != eSkipFrame)   // don't override eSkipFrame @@ -394,19 +385,18 @@ RegisterContextLLDB::InitializeNonZerothFrame()                      }                      return;                  } -                m_cfa = cfa_regval + cfa_offset;                  // A couple of sanity checks.. -                if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) +                if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1)                  {                      UnwindLogMsg ("could not find a valid cfa address");                      m_frame_type = eNotAValidFrame;                      return;                  } -                // cfa_regval should point into the stack memory; if we can query memory region permissions, +                // m_cfa should point into the stack memory; if we can query memory region permissions,                  // see if the memory is allocated & readable. -                if (process->GetLoadAddressPermissions(cfa_regval, permissions) +                if (process->GetLoadAddressPermissions(m_cfa, permissions)                      && (permissions & ePermissionsReadable) == 0)                  {                      m_frame_type = eNotAValidFrame; @@ -600,8 +590,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()          return;      } -    addr_t cfa_regval = LLDB_INVALID_ADDRESS; -    if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) +    if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))      {          UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());          m_frame_type = eNotAValidFrame; @@ -609,12 +598,11 @@ RegisterContextLLDB::InitializeNonZerothFrame()      }      cfa_offset = active_row->GetCFAOffset (); -    m_cfa = cfa_regval + cfa_offset; -    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset); +    UnwindLogMsg ("m_cfa = 0x%16.16" PRIx64 " (cfa_offset = %i)", m_cfa, cfa_offset);      // A couple of sanity checks.. -    if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) +    if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == (addr_t)cfa_offset || m_cfa == (addr_t)cfa_offset + 1)      {          UnwindLogMsg ("could not find a valid cfa address");          m_frame_type = eNotAValidFrame; @@ -1478,11 +1466,8 @@ RegisterContextLLDB::TryFallbackUnwindPlan ()      {          m_registers.clear();          m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; -        addr_t cfa_regval = LLDB_INVALID_ADDRESS; -        if (ReadGPRValue (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval)) -        { -            m_cfa = cfa_regval + active_row->GetCFAOffset (); -        } +        m_cfa = LLDB_INVALID_ADDRESS; +        ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, m_cfa);          UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.",                         m_fallback_unwind_plan_sp->GetSourceName().GetCString(), @@ -1493,6 +1478,38 @@ RegisterContextLLDB::TryFallbackUnwindPlan ()      return true;  } +bool +RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind, +                                         const UnwindPlan::RowSP &row, +                                         addr_t &value) +{ +    uint32_t cfa_regnum = row->GetCFARegister(); +    RegisterValue reg_value; +    addr_t tmp; + +    value = LLDB_INVALID_ADDRESS; + +    if (ReadGPRValue (row_register_kind, cfa_regnum, value)) +    { +        if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced) +        { +            const RegisterInfo *reg_info = GetRegisterInfoAtIndex(cfa_regnum); +            RegisterValue reg_value; +            tmp = value; +            Error error = ReadRegisterValueFromMemory(reg_info, +                                                      value, +                                                      reg_info->byte_size, +                                                      reg_value); +            value = reg_value.GetAsUInt64(); +            UnwindLogMsg("dereferenced address: 0x%16.16" PRIx64 " yields: %lx", tmp, value); +            return error.Success(); +        } +        value = value + row->GetCFAOffset (); +        return true; +    } +    return false; +} +  // Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that  // this frame called.  e.g.  // diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h index 66d62ac94cc..cf652da2619 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -333,6 +333,10 @@ private:      bool      ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, 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); +      lldb::UnwindPlanSP      GetFastUnwindPlanForFrame (); diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index ff0468e314d..56805401ac8 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -153,6 +153,7 @@ UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_pla  void  UnwindPlan::Row::Clear ()  { +    m_cfa_type = CFAIsRegisterPlusOffset;      m_offset = 0;      m_cfa_reg_num = LLDB_INVALID_REGNUM;      m_cfa_offset = 0; @@ -189,10 +190,11 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread,  }  UnwindPlan::Row::Row() : -    m_offset(0), -    m_cfa_reg_num(LLDB_INVALID_REGNUM), -    m_cfa_offset(0), -    m_register_locations() +    m_offset (0), +    m_cfa_type (CFAIsRegisterPlusOffset), +    m_cfa_reg_num (LLDB_INVALID_REGNUM), +    m_cfa_offset (0), +    m_register_locations ()  {  } @@ -301,6 +303,23 @@ UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const  {      if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset)          return false; + +    if (m_cfa_type != rhs.m_cfa_type) +        return false; + +    if (m_cfa_type == CFAIsRegisterPlusOffset) +    { +        if (m_cfa_reg_num != rhs.m_cfa_reg_num) +            return false; +        if (m_cfa_offset != rhs.m_cfa_offset) +            return false; +    } +    if (m_cfa_type == CFAIsRegisterDereferenced) +    { +        if (m_cfa_reg_num != rhs.m_cfa_reg_num) +            return false; +    } +      return m_register_locations == rhs.m_register_locations;  }  | 

