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.cpp309
1 files changed, 309 insertions, 0 deletions
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
new file mode 100644
index 00000000000..45857d67432
--- /dev/null
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -0,0 +1,309 @@
+//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
+{
+ if (m_type != rhs.m_type)
+ return false;
+ if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
+ return m_location.offset == rhs.m_location.offset;
+ if (m_type == inOtherRegister)
+ return m_location.reg_num == rhs.m_location.reg_num;
+ if (m_type == atDWARFExpression || m_type == 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);
+ return false;
+}
+
+// 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;
+}
+
+// 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::SetUnspecified ()
+{
+ m_type = unspecified;
+}
+
+void
+UnwindPlan::Row::RegisterLocation::SetUndefined ()
+{
+ m_type = isUndefined;
+}
+
+void
+UnwindPlan::Row::RegisterLocation::SetSame ()
+{
+ m_type = isSame;
+}
+
+
+void
+UnwindPlan::Row::RegisterLocation::SetAtCFAPlusOffset (int32_t offset)
+{
+ m_type = atCFAPlusOffset;
+ m_location.offset = offset;
+}
+
+void
+UnwindPlan::Row::RegisterLocation::SetIsCFAPlusOffset (int32_t offset)
+{
+ m_type = isCFAPlusOffset;
+ m_location.offset = offset;
+}
+
+void
+UnwindPlan::Row::RegisterLocation::SetInRegister (uint32_t reg_num)
+{
+ m_type = inOtherRegister;
+ m_location.reg_num = reg_num;
+}
+
+void
+UnwindPlan::Row::RegisterLocation::Dump (Stream &s) const
+{
+ switch (m_type)
+ {
+ case unspecified:
+ s.Printf ("unspecified");
+ break;
+ case isUndefined:
+ s.Printf ("isUndefined");
+ break;
+ case isSame:
+ s.Printf ("isSame");
+ break;
+ case atCFAPlusOffset:
+ s.Printf ("atCFAPlusOffset %d", m_location.offset);
+ break;
+ case isCFAPlusOffset:
+ s.Printf ("isCFAPlusOffset %d", m_location.offset);
+ break;
+ case inOtherRegister:
+ s.Printf ("inOtherRegister %d", m_location.reg_num);
+ break;
+ case atDWARFExpression:
+ s.Printf ("atDWARFExpression");
+ break;
+ case isDWARFExpression:
+ s.Printf ("isDWARFExpression");
+ break;
+ }
+}
+
+void
+UnwindPlan::Row::Clear ()
+{
+ m_offset = 0;
+ m_cfa_reg_num = 0;
+ m_cfa_offset = 0;
+ m_register_locations.clear();
+}
+
+void
+UnwindPlan::Row::Dump (Stream& s, int register_kind, Thread* thread) const
+{
+ RegisterContext *rctx = NULL;
+ const RegisterInfo *rinfo = NULL;
+ int translated_regnum;
+ if (thread && thread->GetRegisterContext())
+ {
+ rctx = thread->GetRegisterContext();
+ }
+ s.Printf ("offset %ld, CFA reg ", (long) GetOffset());
+ if (rctx
+ && (translated_regnum = rctx->ConvertRegisterKindToRegisterNumber (register_kind, GetCFARegister())) != -1
+ && (rinfo = rctx->GetRegisterInfoAtIndex (translated_regnum)) != NULL
+ && rinfo->name != NULL
+ && rinfo->name[0] != '\0')
+ {
+ s.Printf ("%s, ", rinfo->name);
+ }
+ else
+ {
+ s.Printf ("%d, ", (int)(int) GetCFARegister());
+ }
+ s.Printf ("CFA offset %d", (int) GetCFAOffset ());
+ for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
+ {
+ s.Printf (" [");
+ bool printed_name = false;
+ if (thread && thread->GetRegisterContext())
+ {
+ rctx = thread->GetRegisterContext();
+ translated_regnum = rctx->ConvertRegisterKindToRegisterNumber (register_kind, idx->first);
+ rinfo = rctx->GetRegisterInfoAtIndex (translated_regnum);
+ if (rinfo && rinfo->name)
+ {
+ s.Printf ("%s ", rinfo->name);
+ printed_name = true;
+ }
+ }
+ if (!printed_name)
+ {
+ s.Printf ("reg %d ", idx->first);
+ }
+ idx->second.Dump(s);
+ s.Printf ("]");
+ }
+ s.Printf ("\n");
+}
+
+UnwindPlan::Row::Row() :
+ m_offset(0),
+ m_cfa_reg_num(0),
+ m_cfa_offset(0),
+ 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;
+}
+
+void
+UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
+{
+ m_register_locations[reg_num] = register_location;
+}
+
+
+void
+UnwindPlan::AppendRow (const UnwindPlan::Row &row)
+{
+ if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
+ m_row_list.push_back(row);
+ else
+ m_row_list.back() = row;
+}
+
+const UnwindPlan::Row *
+UnwindPlan::GetRowForFunctionOffset (int offset) const
+{
+ const UnwindPlan::Row *rowp = NULL;
+ for (int i = 0; i < m_row_list.size(); ++i)
+ {
+ if (m_row_list[i].GetOffset() <= offset)
+ {
+ rowp = &m_row_list[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+ return rowp;
+}
+
+bool
+UnwindPlan::IsValidRowIndex (uint32_t idx) const
+{
+ return idx < m_row_list.size();
+}
+
+const UnwindPlan::Row&
+UnwindPlan::GetRowAtIndex (uint32_t idx) const
+{
+ // You must call IsValidRowIndex(idx) first before calling this!!!
+ return m_row_list[idx];
+}
+
+int
+UnwindPlan::GetRowCount () const
+{
+ return m_row_list.size ();
+}
+
+void
+UnwindPlan::SetRegisterKind (uint32_t rk)
+{
+ m_register_kind = rk;
+}
+
+uint32_t
+UnwindPlan::GetRegisterKind (void) const
+{
+ return m_register_kind;
+}
+
+void
+UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
+{
+ m_plan_valid_address_range = range;
+// .GetBaseAddress() = addr;
+// m_plan_valid_address_range.SetByteSize (range.GetByteSize());
+}
+
+bool
+UnwindPlan::PlanValidAtAddress (Address addr)
+{
+ if (!m_plan_valid_address_range.GetBaseAddress().IsValid())
+ return true;
+
+ if (m_plan_valid_address_range.ContainsFileAddress (addr))
+ return true;
+
+ return false;
+}
+
+void
+UnwindPlan::Dump (Stream& s, Process* process, Thread *thread) const
+{
+ s.Printf ("Address range of this UnwindPlan: ");
+ m_plan_valid_address_range.Dump (&s, process, Address::DumpStyleSectionNameOffset);
+ s.Printf ("\n");
+ s.Printf ("UnwindPlan register kind %d", m_register_kind);
+ switch (m_register_kind)
+ {
+ case eRegisterKindGCC: s.Printf (" [eRegisterKindGCC]"); break;
+ case eRegisterKindDWARF: s.Printf (" [eRegisterKindDWARF]"); break;
+ case eRegisterKindGeneric: s.Printf (" [eRegisterKindGeneric]"); break;
+ case eRegisterKindGDB: s.Printf (" [eRegisterKindGDB]"); break;
+ case eRegisterKindLLDB: s.Printf (" [eRegisterKindLLDB]"); break;
+ default: break;
+ }
+ s.Printf ("\n");
+ for (int i = 0; IsValidRowIndex (i); i++)
+ {
+ s.Printf ("UnwindPlan row at index %d: ", i);
+ m_row_list[i].Dump(s, m_register_kind, thread);
+ }
+}
OpenPOWER on IntegriCloud