summaryrefslogtreecommitdiffstats
path: root/lldb/source/Symbol/UnwindPlan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol/UnwindPlan.cpp')
-rw-r--r--lldb/source/Symbol/UnwindPlan.cpp967
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 &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;
}
-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;
}
-
OpenPOWER on IntegriCloud