diff options
| author | Justin Hibbits <jrh29@alumni.cwru.edu> | 2014-11-12 15:14:03 +0000 | 
|---|---|---|
| committer | Justin Hibbits <jrh29@alumni.cwru.edu> | 2014-11-12 15:14:03 +0000 | 
| commit | 43bcdbde4a4e6f821e5749758d864c0da915462f (patch) | |
| tree | 0b7d32066a229fb1c05009143acb44d0c21c6117 /lldb/source/Plugins/Process | |
| parent | 3cba1c267d65ae4408f3bd8a02166e743a904bd8 (diff) | |
| download | bcm5719-llvm-43bcdbde4a4e6f821e5749758d864c0da915462f.tar.gz bcm5719-llvm-43bcdbde4a4e6f821e5749758d864c0da915462f.zip  | |
Add an alternative CFA type.
Summary:
PowerPC handles the stack chain with the current stack pointer being a pointer
to the backchain (CFA).  LLDB currently has no way of handling this, so this
adds a "CFA is dereferenced from a register" type.
Discussed with Jason Molenda, who also provided the initial patch for this.
Reviewers: jasonmolenda
Reviewed By: jasonmolenda
Subscribers: emaste, lldb-commits
Differential Revision: http://reviews.llvm.org/D6182
llvm-svn: 221788
Diffstat (limited to 'lldb/source/Plugins/Process')
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 67 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h | 4 | 
2 files changed, 46 insertions, 25 deletions
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 ();  | 

