blob: 29985af6ef97b45afb8c7b15e524be910313db24 [file] [log] [blame]
Jason Molendafbcb7f22010-09-10 07:49:16 +00001//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Symbol/UnwindPlan.h"
Greg Clayton79ea8782011-04-26 23:48:45 +000011
12#include "lldb/Core/ConstString.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000013#include "lldb/Target/Process.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000014#include "lldb/Target/RegisterContext.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000015#include "lldb/Target/Thread.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000016
17using namespace lldb;
18using namespace lldb_private;
19
20bool
21UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
22{
23 if (m_type != rhs.m_type)
24 return false;
25 if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
26 return m_location.offset == rhs.m_location.offset;
27 if (m_type == inOtherRegister)
28 return m_location.reg_num == rhs.m_location.reg_num;
29 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
30 if (m_location.expr.length == rhs.m_location.expr.length)
31 return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
32 return false;
33}
34
35// This function doesn't copy the dwarf expression bytes; they must remain in allocated
36// memory for the lifespan of this UnwindPlan object.
37void
38UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
39{
40 m_type = atDWARFExpression;
41 m_location.expr.opcodes = opcodes;
42 m_location.expr.length = len;
43}
44
45// This function doesn't copy the dwarf expression bytes; they must remain in allocated
46// memory for the lifespan of this UnwindPlan object.
47void
48UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
49{
50 m_type = isDWARFExpression;
51 m_location.expr.opcodes = opcodes;
52 m_location.expr.length = len;
53}
54
55void
56UnwindPlan::Row::RegisterLocation::SetUnspecified ()
57{
58 m_type = unspecified;
59}
60
61void
62UnwindPlan::Row::RegisterLocation::SetUndefined ()
63{
64 m_type = isUndefined;
65}
66
67void
68UnwindPlan::Row::RegisterLocation::SetSame ()
69{
70 m_type = isSame;
71}
72
73
74void
75UnwindPlan::Row::RegisterLocation::SetAtCFAPlusOffset (int32_t offset)
76{
77 m_type = atCFAPlusOffset;
78 m_location.offset = offset;
79}
80
81void
82UnwindPlan::Row::RegisterLocation::SetIsCFAPlusOffset (int32_t offset)
83{
84 m_type = isCFAPlusOffset;
85 m_location.offset = offset;
86}
87
88void
89UnwindPlan::Row::RegisterLocation::SetInRegister (uint32_t reg_num)
90{
91 m_type = inOtherRegister;
92 m_location.reg_num = reg_num;
93}
94
95void
96UnwindPlan::Row::RegisterLocation::Dump (Stream &s) const
97{
98 switch (m_type)
99 {
100 case unspecified:
Greg Clayton877aaa52011-01-08 21:19:00 +0000101 s.PutCString ("unspecified");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000102 break;
103 case isUndefined:
Greg Clayton877aaa52011-01-08 21:19:00 +0000104 s.PutCString ("isUndefined");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000105 break;
106 case isSame:
Greg Clayton877aaa52011-01-08 21:19:00 +0000107 s.PutCString ("isSame");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000108 break;
109 case atCFAPlusOffset:
110 s.Printf ("atCFAPlusOffset %d", m_location.offset);
111 break;
112 case isCFAPlusOffset:
113 s.Printf ("isCFAPlusOffset %d", m_location.offset);
114 break;
115 case inOtherRegister:
116 s.Printf ("inOtherRegister %d", m_location.reg_num);
117 break;
118 case atDWARFExpression:
Greg Clayton877aaa52011-01-08 21:19:00 +0000119 s.PutCString ("atDWARFExpression");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000120 break;
121 case isDWARFExpression:
Greg Clayton877aaa52011-01-08 21:19:00 +0000122 s.PutCString ("isDWARFExpression");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000123 break;
124 }
125}
126
127void
128UnwindPlan::Row::Clear ()
129{
130 m_offset = 0;
131 m_cfa_reg_num = 0;
132 m_cfa_offset = 0;
133 m_register_locations.clear();
134}
135
136void
137UnwindPlan::Row::Dump (Stream& s, int register_kind, Thread* thread) const
138{
Greg Clayton5ccbd292011-01-06 22:15:06 +0000139 RegisterContext *reg_ctx = NULL;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000140 const RegisterInfo *rinfo = NULL;
141 int translated_regnum;
142 if (thread && thread->GetRegisterContext())
Greg Clayton5ccbd292011-01-06 22:15:06 +0000143 reg_ctx = thread->GetRegisterContext().get();
144
Jason Molendafbcb7f22010-09-10 07:49:16 +0000145 s.Printf ("offset %ld, CFA reg ", (long) GetOffset());
Greg Clayton5ccbd292011-01-06 22:15:06 +0000146 if (reg_ctx
147 && (translated_regnum = reg_ctx->ConvertRegisterKindToRegisterNumber (register_kind, GetCFARegister())) != -1
148 && (rinfo = reg_ctx->GetRegisterInfoAtIndex (translated_regnum)) != NULL
Jason Molendafbcb7f22010-09-10 07:49:16 +0000149 && rinfo->name != NULL
150 && rinfo->name[0] != '\0')
151 {
152 s.Printf ("%s, ", rinfo->name);
153 }
154 else
155 {
156 s.Printf ("%d, ", (int)(int) GetCFARegister());
157 }
158 s.Printf ("CFA offset %d", (int) GetCFAOffset ());
159 for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
160 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000161 s.PutCString (" [");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000162 bool printed_name = false;
Greg Clayton5ccbd292011-01-06 22:15:06 +0000163 if (reg_ctx)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000164 {
Greg Clayton5ccbd292011-01-06 22:15:06 +0000165 translated_regnum = reg_ctx->ConvertRegisterKindToRegisterNumber (register_kind, idx->first);
166 rinfo = reg_ctx->GetRegisterInfoAtIndex (translated_regnum);
Jason Molendafbcb7f22010-09-10 07:49:16 +0000167 if (rinfo && rinfo->name)
168 {
169 s.Printf ("%s ", rinfo->name);
170 printed_name = true;
171 }
172 }
173 if (!printed_name)
174 {
175 s.Printf ("reg %d ", idx->first);
176 }
177 idx->second.Dump(s);
Greg Clayton877aaa52011-01-08 21:19:00 +0000178 s.PutCString ("]");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000179 }
Greg Clayton877aaa52011-01-08 21:19:00 +0000180 s.EOL();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000181}
182
183UnwindPlan::Row::Row() :
184 m_offset(0),
185 m_cfa_reg_num(0),
186 m_cfa_offset(0),
187 m_register_locations()
188{
189}
190
191bool
192UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
193{
194 collection::const_iterator pos = m_register_locations.find(reg_num);
195 if (pos != m_register_locations.end())
196 {
197 register_location = pos->second;
198 return true;
199 }
200 return false;
201}
202
203void
204UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
205{
206 m_register_locations[reg_num] = register_location;
207}
208
209
210void
211UnwindPlan::AppendRow (const UnwindPlan::Row &row)
212{
213 if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
214 m_row_list.push_back(row);
215 else
216 m_row_list.back() = row;
217}
218
219const UnwindPlan::Row *
220UnwindPlan::GetRowForFunctionOffset (int offset) const
221{
Greg Clayton877aaa52011-01-08 21:19:00 +0000222 const UnwindPlan::Row *row_ptr = NULL;
223 if (!m_row_list.empty())
Jason Molendaab4f1922010-10-25 11:12:07 +0000224 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000225 if (offset == -1)
226 row_ptr = &m_row_list.back();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000227 else
228 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000229 collection::const_iterator pos, end = m_row_list.end();
230 for (pos = m_row_list.begin(); pos != end; ++pos)
231 {
232 if (pos->GetOffset() <= offset)
233 row_ptr = &*pos;
234 else
235 break;
236 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000237 }
238 }
Greg Clayton877aaa52011-01-08 21:19:00 +0000239 return row_ptr;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000240}
241
242bool
243UnwindPlan::IsValidRowIndex (uint32_t idx) const
244{
245 return idx < m_row_list.size();
246}
247
248const UnwindPlan::Row&
249UnwindPlan::GetRowAtIndex (uint32_t idx) const
250{
251 // You must call IsValidRowIndex(idx) first before calling this!!!
Greg Clayton877aaa52011-01-08 21:19:00 +0000252 assert (idx < m_row_list.size());
Jason Molendafbcb7f22010-09-10 07:49:16 +0000253 return m_row_list[idx];
254}
255
256int
257UnwindPlan::GetRowCount () const
258{
259 return m_row_list.size ();
260}
261
262void
263UnwindPlan::SetRegisterKind (uint32_t rk)
264{
265 m_register_kind = rk;
266}
267
268uint32_t
269UnwindPlan::GetRegisterKind (void) const
270{
271 return m_register_kind;
272}
273
274void
275UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
276{
Jason Molendaab4f1922010-10-25 11:12:07 +0000277 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
Jason Molendaab4f1922010-10-25 11:12:07 +0000278 m_plan_valid_address_range = range;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000279}
280
281bool
282UnwindPlan::PlanValidAtAddress (Address addr)
283{
Jason Molendaab4f1922010-10-25 11:12:07 +0000284 if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000285 return true;
286
Jason Molenda59762002010-11-04 00:53:20 +0000287 if (!addr.IsValid())
288 return true;
289
Jason Molendafbcb7f22010-09-10 07:49:16 +0000290 if (m_plan_valid_address_range.ContainsFileAddress (addr))
291 return true;
292
293 return false;
294}
295
296void
Greg Claytonf5e56de2010-09-14 23:36:40 +0000297UnwindPlan::Dump (Stream& s, Thread *thread) const
Jason Molendafbcb7f22010-09-10 07:49:16 +0000298{
Jason Molendaab4f1922010-10-25 11:12:07 +0000299 if (!m_source_name.IsEmpty())
300 {
301 s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
302 }
303 if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
304 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000305 s.PutCString ("Address range of this UnwindPlan: ");
Jason Molendaab4f1922010-10-25 11:12:07 +0000306 m_plan_valid_address_range.Dump (&s, &thread->GetProcess().GetTarget(), Address::DumpStyleSectionNameOffset);
Greg Clayton877aaa52011-01-08 21:19:00 +0000307 s.EOL();
Jason Molendaab4f1922010-10-25 11:12:07 +0000308 }
309 else
310 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000311 s.PutCString ("No valid address range recorded for this UnwindPlan.\n");
Jason Molendaab4f1922010-10-25 11:12:07 +0000312 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000313 s.Printf ("UnwindPlan register kind %d", m_register_kind);
314 switch (m_register_kind)
315 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000316 case eRegisterKindGCC: s.PutCString (" [eRegisterKindGCC]"); break;
317 case eRegisterKindDWARF: s.PutCString (" [eRegisterKindDWARF]"); break;
318 case eRegisterKindGeneric: s.PutCString (" [eRegisterKindGeneric]"); break;
319 case eRegisterKindGDB: s.PutCString (" [eRegisterKindGDB]"); break;
320 case eRegisterKindLLDB: s.PutCString (" [eRegisterKindLLDB]"); break;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000321 default: break;
322 }
Greg Clayton877aaa52011-01-08 21:19:00 +0000323 s.EOL();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000324 for (int i = 0; IsValidRowIndex (i); i++)
325 {
326 s.Printf ("UnwindPlan row at index %d: ", i);
327 m_row_list[i].Dump(s, m_register_kind, thread);
328 }
329}
Jason Molendaab4f1922010-10-25 11:12:07 +0000330
331void
332UnwindPlan::SetSourceName (const char *source)
333{
334 m_source_name = ConstString (source);
335}
336
337ConstString
338UnwindPlan::GetSourceName () const
339{
340 return m_source_name;
341}