diff options
Diffstat (limited to 'lldb/source/Symbol/UnwindPlan.cpp')
-rw-r--r-- | lldb/source/Symbol/UnwindPlan.cpp | 967 |
1 files changed, 453 insertions, 514 deletions
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index 18f0cb7b9db..8a20ef8cce2 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -18,558 +18,497 @@ using namespace lldb; using namespace lldb_private; -bool -UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const -{ - if (m_type == rhs.m_type) - { - switch (m_type) - { - case unspecified: - case undefined: - case same: - return true; - - case atCFAPlusOffset: - case isCFAPlusOffset: - return m_location.offset == rhs.m_location.offset; - - case inOtherRegister: - return m_location.reg_num == rhs.m_location.reg_num; - - case atDWARFExpression: - case isDWARFExpression: - if (m_location.expr.length == rhs.m_location.expr.length) - return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length); - break; - } +bool UnwindPlan::Row::RegisterLocation:: +operator==(const UnwindPlan::Row::RegisterLocation &rhs) const { + if (m_type == rhs.m_type) { + switch (m_type) { + case unspecified: + case undefined: + case same: + return true; + + case atCFAPlusOffset: + case isCFAPlusOffset: + return m_location.offset == rhs.m_location.offset; + + case inOtherRegister: + return m_location.reg_num == rhs.m_location.reg_num; + + case atDWARFExpression: + case isDWARFExpression: + if (m_location.expr.length == rhs.m_location.expr.length) + return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes, + m_location.expr.length); + break; } - return false; + } + return false; } -// This function doesn't copy the dwarf expression bytes; they must remain in allocated +// This function doesn't copy the dwarf expression bytes; they must remain in +// allocated // memory for the lifespan of this UnwindPlan object. -void -UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len) -{ - m_type = atDWARFExpression; - m_location.expr.opcodes = opcodes; - m_location.expr.length = len; +void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression( + const uint8_t *opcodes, uint32_t len) { + m_type = atDWARFExpression; + m_location.expr.opcodes = opcodes; + m_location.expr.length = len; } -// This function doesn't copy the dwarf expression bytes; they must remain in allocated +// This function doesn't copy the dwarf expression bytes; they must remain in +// allocated // memory for the lifespan of this UnwindPlan object. -void -UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len) -{ - m_type = isDWARFExpression; - m_location.expr.opcodes = opcodes; - m_location.expr.length = len; -} - -void -UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const -{ - switch (m_type) - { - case unspecified: - if (verbose) - s.PutCString ("=<unspec>"); - else - s.PutCString ("=!"); - break; - case undefined: - if (verbose) - s.PutCString ("=<undef>"); - else - s.PutCString ("=?"); - break; - case same: - s.PutCString ("= <same>"); - break; - - case atCFAPlusOffset: - case isCFAPlusOffset: - { - s.PutChar('='); - if (m_type == atCFAPlusOffset) - s.PutChar('['); - s.Printf ("CFA%+d", m_location.offset); - if (m_type == atCFAPlusOffset) - s.PutChar(']'); - } - break; - - case inOtherRegister: - { - const RegisterInfo *other_reg_info = nullptr; - if (unwind_plan) - other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num); - if (other_reg_info) - s.Printf ("=%s", other_reg_info->name); - else - s.Printf ("=reg(%u)", m_location.reg_num); - } - break; - - case atDWARFExpression: - case isDWARFExpression: - { - s.PutChar('='); - if (m_type == atDWARFExpression) - s.PutCString("[dwarf-expr]"); - else - s.PutCString("dwarf-expr"); - } - break; - - } -} - -static void -DumpRegisterName (Stream &s, const UnwindPlan* unwind_plan, Thread *thread, uint32_t reg_num) { - const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, reg_num); - if (reg_info) - s.PutCString (reg_info->name); +void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression( + const uint8_t *opcodes, uint32_t len) { + m_type = isDWARFExpression; + m_location.expr.opcodes = opcodes; + m_location.expr.length = len; +} + +void UnwindPlan::Row::RegisterLocation::Dump(Stream &s, + const UnwindPlan *unwind_plan, + const UnwindPlan::Row *row, + Thread *thread, + bool verbose) const { + switch (m_type) { + case unspecified: + if (verbose) + s.PutCString("=<unspec>"); else - s.Printf ("reg(%u)", reg_num); -} - -bool -UnwindPlan::Row::CFAValue::operator == (const UnwindPlan::Row::CFAValue& rhs) const -{ - if (m_type == rhs.m_type) - { - switch (m_type) - { - case unspecified: - return true; - - case isRegisterPlusOffset: - return m_value.reg.offset == rhs.m_value.reg.offset; - - case isRegisterDereferenced: - return m_value.reg.reg_num == rhs.m_value.reg.reg_num; - - case isDWARFExpression: - if (m_value.expr.length == rhs.m_value.expr.length) - return !memcmp (m_value.expr.opcodes, rhs.m_value.expr.opcodes, m_value.expr.length); - break; - } - } - return false; -} - -void -UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan* unwind_plan, Thread* thread) const -{ - switch(m_type) { - case isRegisterPlusOffset: - DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); - s.Printf ("%+3d", m_value.reg.offset); - break; - case isRegisterDereferenced: - s.PutChar ('['); - DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); - s.PutChar (']'); - break; - case isDWARFExpression: - s.PutCString ("dwarf-expr"); - break; - default: - s.PutCString ("unspecified"); - break; - } -} - -void -UnwindPlan::Row::Clear () -{ - m_cfa_value.SetUnspecified(); - m_offset = 0; - m_register_locations.clear(); -} - -void -UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const -{ - if (base_addr != LLDB_INVALID_ADDRESS) - s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); + s.PutCString("=!"); + break; + case undefined: + if (verbose) + s.PutCString("=<undef>"); else - s.Printf ("%4" PRId64 ": CFA=", GetOffset()); - - m_cfa_value.Dump(s, unwind_plan, thread); - s.Printf(" => "); - for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx) - { - DumpRegisterName(s, unwind_plan, thread, idx->first); - const bool verbose = false; - idx->second.Dump(s, unwind_plan, this, thread, verbose); - s.PutChar (' '); - } - s.EOL(); -} - -UnwindPlan::Row::Row() : - m_offset (0), - m_cfa_value (), - m_register_locations () -{ -} - -bool -UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const -{ - collection::const_iterator pos = m_register_locations.find(reg_num); - if (pos != m_register_locations.end()) - { - register_location = pos->second; - return true; - } - return false; + s.PutCString("=?"); + break; + case same: + s.PutCString("= <same>"); + break; + + case atCFAPlusOffset: + case isCFAPlusOffset: { + s.PutChar('='); + if (m_type == atCFAPlusOffset) + s.PutChar('['); + s.Printf("CFA%+d", m_location.offset); + if (m_type == atCFAPlusOffset) + s.PutChar(']'); + } break; + + case inOtherRegister: { + const RegisterInfo *other_reg_info = nullptr; + if (unwind_plan) + other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num); + if (other_reg_info) + s.Printf("=%s", other_reg_info->name); + else + s.Printf("=reg(%u)", m_location.reg_num); + } break; + + case atDWARFExpression: + case isDWARFExpression: { + s.PutChar('='); + if (m_type == atDWARFExpression) + s.PutCString("[dwarf-expr]"); + else + s.PutCString("dwarf-expr"); + } break; + } } -void -UnwindPlan::Row::RemoveRegisterInfo (uint32_t reg_num) -{ - collection::const_iterator pos = m_register_locations.find(reg_num); - if (pos != m_register_locations.end()) - { - m_register_locations.erase(pos); - } +static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan, + Thread *thread, uint32_t reg_num) { + const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num); + if (reg_info) + s.PutCString(reg_info->name); + else + s.Printf("reg(%u)", reg_num); } -void -UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location) -{ - m_register_locations[reg_num] = register_location; -} +bool UnwindPlan::Row::CFAValue:: +operator==(const UnwindPlan::Row::CFAValue &rhs) const { + if (m_type == rhs.m_type) { + switch (m_type) { + case unspecified: + return true; -bool -UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetAtCFAPlusOffset(offset); - m_register_locations[reg_num] = reg_loc; - return true; -} + case isRegisterPlusOffset: + return m_value.reg.offset == rhs.m_value.reg.offset; -bool -UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetIsCFAPlusOffset(offset); - m_register_locations[reg_num] = reg_loc; - return true; -} + case isRegisterDereferenced: + return m_value.reg.reg_num == rhs.m_value.reg.reg_num; -bool -UnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) -{ - collection::iterator pos = m_register_locations.find(reg_num); - collection::iterator end = m_register_locations.end(); - - if (pos != end) - { - if (!can_replace) - return false; - if (can_replace_only_if_unspecified && !pos->second.IsUnspecified()) - return false; + case isDWARFExpression: + if (m_value.expr.length == rhs.m_value.expr.length) + return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes, + m_value.expr.length); + break; } - RegisterLocation reg_loc; - reg_loc.SetUndefined(); - m_register_locations[reg_num] = reg_loc; + } + return false; +} + +void UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan *unwind_plan, + Thread *thread) const { + switch (m_type) { + case isRegisterPlusOffset: + DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); + s.Printf("%+3d", m_value.reg.offset); + break; + case isRegisterDereferenced: + s.PutChar('['); + DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); + s.PutChar(']'); + break; + case isDWARFExpression: + s.PutCString("dwarf-expr"); + break; + default: + s.PutCString("unspecified"); + break; + } +} + +void UnwindPlan::Row::Clear() { + m_cfa_value.SetUnspecified(); + m_offset = 0; + m_register_locations.clear(); +} + +void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan, + Thread *thread, addr_t base_addr) const { + if (base_addr != LLDB_INVALID_ADDRESS) + s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); + else + s.Printf("%4" PRId64 ": CFA=", GetOffset()); + + m_cfa_value.Dump(s, unwind_plan, thread); + s.Printf(" => "); + for (collection::const_iterator idx = m_register_locations.begin(); + idx != m_register_locations.end(); ++idx) { + DumpRegisterName(s, unwind_plan, thread, idx->first); + const bool verbose = false; + idx->second.Dump(s, unwind_plan, this, thread, verbose); + s.PutChar(' '); + } + s.EOL(); +} + +UnwindPlan::Row::Row() : m_offset(0), m_cfa_value(), m_register_locations() {} + +bool UnwindPlan::Row::GetRegisterInfo( + uint32_t reg_num, + UnwindPlan::Row::RegisterLocation ®ister_location) const { + collection::const_iterator pos = m_register_locations.find(reg_num); + if (pos != m_register_locations.end()) { + register_location = pos->second; return true; + } + return false; } -bool -UnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetUnspecified(); - m_register_locations[reg_num] = reg_loc; - return true; -} - -bool -UnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num, - uint32_t other_reg_num, - bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetInRegister(other_reg_num); - m_register_locations[reg_num] = reg_loc; - return true; +void UnwindPlan::Row::RemoveRegisterInfo(uint32_t reg_num) { + collection::const_iterator pos = m_register_locations.find(reg_num); + if (pos != m_register_locations.end()) { + m_register_locations.erase(pos); + } } -bool -UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace) -{ - if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetSame(); - m_register_locations[reg_num] = reg_loc; - return true; +void UnwindPlan::Row::SetRegisterInfo( + uint32_t reg_num, + const UnwindPlan::Row::RegisterLocation register_location) { + m_register_locations[reg_num] = register_location; } -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; +bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, + int32_t offset, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetAtCFAPlusOffset(offset); + m_register_locations[reg_num] = reg_loc; + return true; } -void -UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp) -{ - if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset()) - m_row_list.push_back(row_sp); - else - m_row_list.back() = row_sp; +bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, + int32_t offset, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetIsCFAPlusOffset(offset); + m_register_locations[reg_num] = reg_loc; + return true; +} + +bool UnwindPlan::Row::SetRegisterLocationToUndefined( + uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) { + collection::iterator pos = m_register_locations.find(reg_num); + collection::iterator end = m_register_locations.end(); + + if (pos != end) { + if (!can_replace) + return false; + if (can_replace_only_if_unspecified && !pos->second.IsUnspecified()) + return false; + } + RegisterLocation reg_loc; + reg_loc.SetUndefined(); + m_register_locations[reg_num] = reg_loc; + return true; +} + +bool UnwindPlan::Row::SetRegisterLocationToUnspecified(uint32_t reg_num, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetUnspecified(); + m_register_locations[reg_num] = reg_loc; + return true; } -void -UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp, bool replace_existing) -{ - collection::iterator it = m_row_list.begin(); - while (it != m_row_list.end()) { - RowSP row = *it; - if (row->GetOffset() >= row_sp->GetOffset()) - break; - it++; - } - if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset()) - m_row_list.insert(it, row_sp); - else if (replace_existing) - *it = row_sp; +bool UnwindPlan::Row::SetRegisterLocationToRegister(uint32_t reg_num, + uint32_t other_reg_num, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetInRegister(other_reg_num); + m_register_locations[reg_num] = reg_loc; + return true; } -UnwindPlan::RowSP -UnwindPlan::GetRowForFunctionOffset (int offset) const -{ - RowSP row; - if (!m_row_list.empty()) - { - if (offset == -1) - row = m_row_list.back(); +bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num, + bool must_replace) { + if (must_replace && + m_register_locations.find(reg_num) == m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetSame(); + m_register_locations[reg_num] = reg_loc; + return true; +} + +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; +} + +void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) { + if (m_row_list.empty() || + m_row_list.back()->GetOffset() != row_sp->GetOffset()) + m_row_list.push_back(row_sp); + else + m_row_list.back() = row_sp; +} + +void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp, + bool replace_existing) { + collection::iterator it = m_row_list.begin(); + while (it != m_row_list.end()) { + RowSP row = *it; + if (row->GetOffset() >= row_sp->GetOffset()) + break; + it++; + } + if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset()) + m_row_list.insert(it, row_sp); + else if (replace_existing) + *it = row_sp; +} + +UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset(int offset) const { + RowSP row; + if (!m_row_list.empty()) { + if (offset == -1) + row = m_row_list.back(); + else { + collection::const_iterator pos, end = m_row_list.end(); + for (pos = m_row_list.begin(); pos != end; ++pos) { + if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset)) + row = *pos; else - { - collection::const_iterator pos, end = m_row_list.end(); - for (pos = m_row_list.begin(); pos != end; ++pos) - { - if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset)) - row = *pos; - else - break; - } - } - } - return row; -} - -bool -UnwindPlan::IsValidRowIndex (uint32_t idx) const -{ - return idx < m_row_list.size(); -} - -const UnwindPlan::RowSP -UnwindPlan::GetRowAtIndex (uint32_t idx) const -{ - if (idx < m_row_list.size()) - return m_row_list[idx]; - else - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - log->Printf ("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index (number rows is %u)", idx, (uint32_t)m_row_list.size()); - return UnwindPlan::RowSP(); - } -} - -const UnwindPlan::RowSP -UnwindPlan::GetLastRow () const -{ - if (m_row_list.empty()) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - log->Printf ("UnwindPlan::GetLastRow() when rows are empty"); - return UnwindPlan::RowSP(); + break; + } } - return m_row_list.back(); -} - -int -UnwindPlan::GetRowCount () const -{ - return m_row_list.size (); -} - -void -UnwindPlan::SetPlanValidAddressRange (const AddressRange& range) -{ - if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0) - m_plan_valid_address_range = range; -} - -bool -UnwindPlan::PlanValidAtAddress (Address addr) -{ - // If this UnwindPlan has no rows, it is an invalid UnwindPlan. - if (GetRowCount() == 0) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - { - StreamString s; - if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset)) - { - log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s", - m_source_name.GetCString(), s.GetData()); - } - else - { - log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", - m_source_name.GetCString()); - } - } - return false; + } + return row; +} + +bool UnwindPlan::IsValidRowIndex(uint32_t idx) const { + return idx < m_row_list.size(); +} + +const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const { + if (idx < m_row_list.size()) + return m_row_list[idx]; + else { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) + log->Printf("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index " + "(number rows is %u)", + idx, (uint32_t)m_row_list.size()); + return UnwindPlan::RowSP(); + } +} + +const UnwindPlan::RowSP UnwindPlan::GetLastRow() const { + if (m_row_list.empty()) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) + log->Printf("UnwindPlan::GetLastRow() when rows are empty"); + return UnwindPlan::RowSP(); + } + return m_row_list.back(); +} + +int UnwindPlan::GetRowCount() const { return m_row_list.size(); } + +void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) { + if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0) + m_plan_valid_address_range = range; +} + +bool UnwindPlan::PlanValidAtAddress(Address addr) { + // If this UnwindPlan has no rows, it is an invalid UnwindPlan. + if (GetRowCount() == 0) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) { + StreamString s; + if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) { + log->Printf("UnwindPlan is invalid -- no unwind rows for UnwindPlan " + "'%s' at address %s", + m_source_name.GetCString(), s.GetData()); + } else { + log->Printf( + "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", + m_source_name.GetCString()); + } } - - // If the 0th Row of unwind instructions is missing, or if it doesn't provide - // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan. - if (GetRowAtIndex(0).get() == nullptr || - GetRowAtIndex(0)->GetCFAValue().GetValueType() == Row::CFAValue::unspecified) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - { - StreamString s; - if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset)) - { - log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s", - m_source_name.GetCString(), s.GetData()); - } - else - { - log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'", - m_source_name.GetCString()); - } - } - return false; + return false; + } + + // If the 0th Row of unwind instructions is missing, or if it doesn't provide + // a register to use to find the Canonical Frame Address, this is not a valid + // UnwindPlan. + if (GetRowAtIndex(0).get() == nullptr || + GetRowAtIndex(0)->GetCFAValue().GetValueType() == + Row::CFAValue::unspecified) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) { + StreamString s; + if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) { + log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 " + "for UnwindPlan '%s' at address %s", + m_source_name.GetCString(), s.GetData()); + } else { + log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 " + "for UnwindPlan '%s'", + m_source_name.GetCString()); + } } - - if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0) - return true; - - if (!addr.IsValid()) - return true; - - if (m_plan_valid_address_range.ContainsFileAddress (addr)) - return true; - return false; -} + } -void -UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const -{ - if (!m_source_name.IsEmpty()) - { - s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); - } - if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) - { - TargetSP target_sp(thread->CalculateTarget()); - addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get()); - addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get()); - - if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS) - { - s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n", - lsda_load_addr, personality_func_load_addr); - } - } - s.Printf ("This UnwindPlan is sourced from the compiler: "); - switch (m_plan_is_sourced_from_compiler) - { - case eLazyBoolYes: - s.Printf ("yes.\n"); - break; - case eLazyBoolNo: - s.Printf ("no.\n"); - break; - case eLazyBoolCalculate: - s.Printf ("not specified.\n"); - break; - } - s.Printf ("This UnwindPlan is valid at all instruction locations: "); - switch (m_plan_is_valid_at_all_instruction_locations) - { - case eLazyBoolYes: - s.Printf ("yes.\n"); - break; - case eLazyBoolNo: - s.Printf ("no.\n"); - break; - case eLazyBoolCalculate: - s.Printf ("not specified.\n"); - break; - } - if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) - { - s.PutCString ("Address range of this UnwindPlan: "); - TargetSP target_sp(thread->CalculateTarget()); - m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset); - s.EOL(); - } - collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end(); - for (pos = begin; pos != end; ++pos) - { - s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos)); - (*pos)->Dump(s, this, thread, base_addr); - } -} + if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || + m_plan_valid_address_range.GetByteSize() == 0) + return true; -void -UnwindPlan::SetSourceName (const char *source) -{ - m_source_name = ConstString (source); -} + if (!addr.IsValid()) + return true; -ConstString -UnwindPlan::GetSourceName () const -{ - return m_source_name; -} + if (m_plan_valid_address_range.ContainsFileAddress(addr)) + return true; -const RegisterInfo * -UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const -{ - if (thread) - { - RegisterContext *reg_ctx = thread->GetRegisterContext().get(); - if (reg_ctx) - { - uint32_t reg; - if (m_register_kind == eRegisterKindLLDB) - reg = unwind_reg; - else - reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg); - if (reg != LLDB_INVALID_REGNUM) - return reg_ctx->GetRegisterInfoAtIndex (reg); - } + return false; +} + +void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const { + if (!m_source_name.IsEmpty()) { + s.Printf("This UnwindPlan originally sourced from %s\n", + m_source_name.GetCString()); + } + if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) { + TargetSP target_sp(thread->CalculateTarget()); + addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get()); + addr_t personality_func_load_addr = + m_personality_func_addr.GetLoadAddress(target_sp.get()); + + if (lsda_load_addr != LLDB_INVALID_ADDRESS && + personality_func_load_addr != LLDB_INVALID_ADDRESS) { + s.Printf("LSDA address 0x%" PRIx64 + ", personality routine is at address 0x%" PRIx64 "\n", + lsda_load_addr, personality_func_load_addr); + } + } + s.Printf("This UnwindPlan is sourced from the compiler: "); + switch (m_plan_is_sourced_from_compiler) { + case eLazyBoolYes: + s.Printf("yes.\n"); + break; + case eLazyBoolNo: + s.Printf("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf("not specified.\n"); + break; + } + s.Printf("This UnwindPlan is valid at all instruction locations: "); + switch (m_plan_is_valid_at_all_instruction_locations) { + case eLazyBoolYes: + s.Printf("yes.\n"); + break; + case eLazyBoolNo: + s.Printf("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf("not specified.\n"); + break; + } + if (m_plan_valid_address_range.GetBaseAddress().IsValid() && + m_plan_valid_address_range.GetByteSize() > 0) { + s.PutCString("Address range of this UnwindPlan: "); + TargetSP target_sp(thread->CalculateTarget()); + m_plan_valid_address_range.Dump(&s, target_sp.get(), + Address::DumpStyleSectionNameOffset); + s.EOL(); + } + collection::const_iterator pos, begin = m_row_list.begin(), + end = m_row_list.end(); + for (pos = begin; pos != end; ++pos) { + s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos)); + (*pos)->Dump(s, this, thread, base_addr); + } +} + +void UnwindPlan::SetSourceName(const char *source) { + m_source_name = ConstString(source); +} + +ConstString UnwindPlan::GetSourceName() const { return m_source_name; } + +const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread, + uint32_t unwind_reg) const { + if (thread) { + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + if (reg_ctx) { + uint32_t reg; + if (m_register_kind == eRegisterKindLLDB) + reg = unwind_reg; + else + reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind, + unwind_reg); + if (reg != LLDB_INVALID_REGNUM) + return reg_ctx->GetRegisterInfoAtIndex(reg); } - return nullptr; + } + return nullptr; } - |